Copied Modbus-CAPL and added VisualStudio project VCSignalProtocolDLL
This commit is contained in:
		
							parent
							
								
									41ba4a3fd5
								
							
						
					
					
						commit
						f26088b1eb
					
				
					 36 changed files with 17624 additions and 0 deletions
				
			
		
							
								
								
									
										4832
									
								
								Modbus-DLL/MakeConfig.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4832
									
								
								Modbus-DLL/MakeConfig.cfg
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										7343
									
								
								Modbus-DLL/ModbusNet.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7343
									
								
								Modbus-DLL/ModbusNet.cfg
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										529
									
								
								Modbus-DLL/include/CAPL/MakeConfig.can
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										529
									
								
								Modbus-DLL/include/CAPL/MakeConfig.can
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,529 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
includes
 | 
			
		||||
{
 | 
			
		||||
	#include "include/ModbusUdpClientCommon.cin"
 | 
			
		||||
	#include "include/ModbusFunctions.cin"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
variables
 | 
			
		||||
{
 | 
			
		||||
	struct device
 | 
			
		||||
	{
 | 
			
		||||
		char Ip[16];
 | 
			
		||||
		char IpLsb[4];
 | 
			
		||||
		char IpNet[4];
 | 
			
		||||
		enum Vendor Vendor;
 | 
			
		||||
		word SerialCode;
 | 
			
		||||
		word DeviceCode;
 | 
			
		||||
		struct deviceIOs DeviceIOs;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	char[16] gIps[long];
 | 
			
		||||
	char gScanFirstIp[16];
 | 
			
		||||
	char gScanLastIp[16];
 | 
			
		||||
 | 
			
		||||
	char fnSysvar[40];		// Filename of Sysvars
 | 
			
		||||
	char fnDbc[40];			// Filename of DBC
 | 
			
		||||
	char name[20];			// Name of project
 | 
			
		||||
	dword ips[50];			// detected IPs
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	file f;
 | 
			
		||||
	byte gIpNets[long];
 | 
			
		||||
	struct device gIpsSorted[long];
 | 
			
		||||
	dword gScanFirst, gScanLast;
 | 
			
		||||
	word ADi, ADn, ADl;
 | 
			
		||||
 | 
			
		||||
	byte gMaxTransmissionCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
on preStart
 | 
			
		||||
{
 | 
			
		||||
	// List of IPs of devices go here
 | 
			
		||||
	/*
 | 
			
		||||
	strncpy(gIps[0], "192.168.1.3", 16);
 | 
			
		||||
	strncpy(gIps[2], "192.168.1.4", 16);
 | 
			
		||||
	strncpy(gIps[3], "192.168.1.8", 16);
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
	// Scan a range of IPs for devices. Start and Stop go here
 | 
			
		||||
	// Please note: Currelty .255 will be skipped!
 | 
			
		||||
	strncpy(gScanFirstIp, "192.168.1.2", 16);
 | 
			
		||||
	strncpy(gScanLastIp, "192.168.1.10", 16);
 | 
			
		||||
 | 
			
		||||
	// Name of the project
 | 
			
		||||
	strncpy(name, "Modbus", elCount(name));
 | 
			
		||||
	// Paths to the generated files relative to .cfg
 | 
			
		||||
	strncpy(fnSysvar, "include/SysVars/generated.vsysvar", elCount(fnSysvar));
 | 
			
		||||
	strncpy(fnDbc, "include/DBC/generated.dbc", elCount(fnDbc));
 | 
			
		||||
	
 | 
			
		||||
	OutputDebugLevel = Error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
on start
 | 
			
		||||
{
 | 
			
		||||
	gMaxTransmissionCount = @sysvar::Config::Modbus::MaxTransmissionCount;
 | 
			
		||||
 | 
			
		||||
	if (gIps.Size() == 0)
 | 
			
		||||
		DetectDevices();
 | 
			
		||||
	else
 | 
			
		||||
		MakeIpNets();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <PutString>
 | 
			
		||||
void PutString(file f, char str[])
 | 
			
		||||
{
 | 
			
		||||
	f.PutString(str, strlen(str));
 | 
			
		||||
}
 | 
			
		||||
/// <PutString>
 | 
			
		||||
void PutString(file f, word d)
 | 
			
		||||
{
 | 
			
		||||
	char str[6];
 | 
			
		||||
	ltoa(d, str, 10);
 | 
			
		||||
	f.PutString(str, strlen(str));
 | 
			
		||||
}
 | 
			
		||||
/// <PutString>
 | 
			
		||||
void PutString(file f, byte d)
 | 
			
		||||
{
 | 
			
		||||
	char str[4];
 | 
			
		||||
	ltoa(d, str, 10);
 | 
			
		||||
	f.PutString(str, strlen(str));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Step 1: Detect active devices and collect IP addresses
 | 
			
		||||
/// <Step1>
 | 
			
		||||
void DetectDevices()
 | 
			
		||||
{
 | 
			
		||||
	@sysvar::Config::Modbus::MaxTransmissionCount = 1;
 | 
			
		||||
	write("Scanning from %s to %s with timeout of %d ms", gScanFirstIp, gScanLastIp, @sysvar::Config::Modbus::RequestTimeout);
 | 
			
		||||
	gScanFirst = ipGetAddressAsNumber(gScanFirstIp);
 | 
			
		||||
	gScanLast = ipGetAddressAsNumber(gScanLastIp);
 | 
			
		||||
	write("%d.%d.%d.%d  ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
 | 
			
		||||
	ModbusConnectTo(gScanFirst, @sysvar::Config::Modbus::Port);
 | 
			
		||||
	ModbusReadBits(0, 1);
 | 
			
		||||
}
 | 
			
		||||
/// <Step1>
 | 
			
		||||
void DetectDevicesNext()
 | 
			
		||||
{
 | 
			
		||||
	// next IP
 | 
			
		||||
	// 0xFE...... --> Skip xxx.xxx.xxx.255 which is broadcast address in 192.168.xxx.0 nets
 | 
			
		||||
	if ((gScanFirst & 0xFFFFFF00) == 0xFEFFFF00)
 | 
			
		||||
	{
 | 
			
		||||
		gScanFirst &= 0x000000FF;
 | 
			
		||||
		gScanFirst += 0x00000001;
 | 
			
		||||
		write("%d.%d.%d.%d  ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
 | 
			
		||||
	}
 | 
			
		||||
	else if ((gScanFirst & 0xFFFF0000) == 0xFEFF0000)
 | 
			
		||||
	{
 | 
			
		||||
		gScanFirst &= 0x0000FFF;
 | 
			
		||||
		gScanFirst += 0x00000100;
 | 
			
		||||
		write("%d.%d.%d.%d  ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
 | 
			
		||||
	}
 | 
			
		||||
	else if ((gScanFirst & 0xFF000000) == 0xFE000000)
 | 
			
		||||
	{
 | 
			
		||||
		gScanFirst &= 0x00FFFFFF;
 | 
			
		||||
		gScanFirst += 0x00010000;
 | 
			
		||||
		
 | 
			
		||||
		write("%d.%d.%d.%d  ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		gScanFirst += 0x01000000;
 | 
			
		||||
	}
 | 
			
		||||
	if (gScanFirst == gScanLast)
 | 
			
		||||
	{
 | 
			
		||||
		@sysvar::Config::Modbus::MaxTransmissionCount = gMaxTransmissionCount;
 | 
			
		||||
		MakeIpNets();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	writeEx(1, 1, ".");
 | 
			
		||||
	gRemoteIP = gScanFirst;		// Don't open new socket, it takes too much time.
 | 
			
		||||
	ModbusReadBits(0, 1);
 | 
			
		||||
}
 | 
			
		||||
/// <Step1>
 | 
			
		||||
void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
 | 
			
		||||
{
 | 
			
		||||
	DetectDevicesNext();
 | 
			
		||||
}
 | 
			
		||||
/// <Step1>
 | 
			
		||||
void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq)
 | 
			
		||||
{
 | 
			
		||||
	ipGetAddressAsString(gScanFirst, gIps[gScanFirst], 16);
 | 
			
		||||
	DetectDevicesNext();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Step 2: Sort into subnets
 | 
			
		||||
// Sort the IPs from gIps to gIpsSorted and add their subnet to gIpNets
 | 
			
		||||
/// <Step2>
 | 
			
		||||
void MakeIpNets()
 | 
			
		||||
{
 | 
			
		||||
	long ipNum;
 | 
			
		||||
 | 
			
		||||
	if (gIps.Size() == 0)
 | 
			
		||||
	{
 | 
			
		||||
		stop();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (long i : gIps)
 | 
			
		||||
	{
 | 
			
		||||
		ipNum = ipGetAddressAsNumber(gIps[i]);						// convert IP to dword
 | 
			
		||||
 | 
			
		||||
		gIpNets[(ipNum >> 16) & 0xFF] = 1;							// add subnet
 | 
			
		||||
		ips[gIpsSorted.size()] = ipNum;								// add ip to array
 | 
			
		||||
		strncpy(gIpsSorted[ipNum].IP, gIps[i], 16);					// copy to new array
 | 
			
		||||
		ltoa((ipNum >> 16) & 0xFF, gIpsSorted[ipNum].IpNet, 10);	// add .IpNet
 | 
			
		||||
		ltoa((ipNum >> 24) & 0xFF, gIpsSorted[ipNum].IpLsb, 10);	// add .IpLsb
 | 
			
		||||
 | 
			
		||||
		gIps.Remove(i);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	AnalyzeDevices();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Step 3: Retreive configuration of devices
 | 
			
		||||
/// <Step3>
 | 
			
		||||
void AnalyzeDevices()
 | 
			
		||||
{
 | 
			
		||||
	ADn = 0;
 | 
			
		||||
	ADi = 0;
 | 
			
		||||
	ADl = gIpsSorted.Size();
 | 
			
		||||
	write("Analyzing %s...", gIpsSorted[ips[ADi]].Ip);
 | 
			
		||||
	gIpsSorted[ips[ADi]].Vendor = Wago;
 | 
			
		||||
	if (gRemoteIP != INVALID_IP)
 | 
			
		||||
		gRemoteIP = ips[ADi];
 | 
			
		||||
	else
 | 
			
		||||
		ModbusConnectTo(ips[ADi], @sysvar::Config::Modbus::Port);
 | 
			
		||||
	ModbusReadRegisters(0x2011, 1);
 | 
			
		||||
	ModbusReadRegisters(0x2012, 1);
 | 
			
		||||
	ModbusReadRegisters(0x2030, 65);
 | 
			
		||||
	ModbusReadRegisters(0x2031, 64);
 | 
			
		||||
	ModbusReadRegisters(0x2032, 64);
 | 
			
		||||
	ModbusReadRegisters(0x2033, 63);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <Step3>
 | 
			
		||||
void AnalyzeDevicesNext()
 | 
			
		||||
{
 | 
			
		||||
	if (++ADi >= ADl)		// we have analyzed all devices
 | 
			
		||||
	{
 | 
			
		||||
		MakeFiles();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ADn = 0;
 | 
			
		||||
	gRemoteIP = ips[ADi];
 | 
			
		||||
	write("Analyzing %s...", gIpsSorted[ips[ADi]].Ip);
 | 
			
		||||
	ModbusReadRegisters(0x2011, 1);
 | 
			
		||||
	ModbusReadRegisters(0x2012, 1);
 | 
			
		||||
	ModbusReadRegisters(0x2030, 65);
 | 
			
		||||
	ModbusReadRegisters(0x2031, 64);
 | 
			
		||||
	ModbusReadRegisters(0x2032, 64);
 | 
			
		||||
	ModbusReadRegisters(0x2033, 63);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <Step3>
 | 
			
		||||
void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
 | 
			
		||||
{
 | 
			
		||||
	switch (error)
 | 
			
		||||
	{
 | 
			
		||||
		case FinalTimeout:
 | 
			
		||||
			writeLineEx(0, 3, "Error while analyzing %s! The device did not respond! Ignoring...", gIpsSorted[ips[ADi]].IP);
 | 
			
		||||
			gQueueAck.Clear();
 | 
			
		||||
			gQueuePending.Clear();
 | 
			
		||||
			gQueueSent.Clear();
 | 
			
		||||
			gIpsSorted.Remove(ips[ADi]);
 | 
			
		||||
			AnalyzeDevicesNext();
 | 
			
		||||
			break;
 | 
			
		||||
		case Exception:
 | 
			
		||||
			writeLineEx(0, 3, "Error while analyzing %s! The device respond with exception code %d! Ignoring...", gIpsSorted[ips[ADi]].IP, ex);
 | 
			
		||||
			gQueueAck.Clear();
 | 
			
		||||
			gQueuePending.Clear();
 | 
			
		||||
			gQueueSent.Clear();
 | 
			
		||||
			gIpsSorted.Remove(ips[ADi]);
 | 
			
		||||
			AnalyzeDevicesNext();
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <Step3>
 | 
			
		||||
void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq)
 | 
			
		||||
{
 | 
			
		||||
	byte i;
 | 
			
		||||
 | 
			
		||||
	switch (mbreq.Address)
 | 
			
		||||
	{
 | 
			
		||||
		case 0x2011:
 | 
			
		||||
			gIpsSorted[ips[ADi]].serialCode = mbres.Data[0];
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x2012:
 | 
			
		||||
			gIpsSorted[ips[ADi]].deviceCode = mbres.Data[0];
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x2030:
 | 
			
		||||
		case 0x2031:
 | 
			
		||||
		case 0x2032:
 | 
			
		||||
		case 0x2033:
 | 
			
		||||
			for (i = 0; i < mbreq.Count; i++)
 | 
			
		||||
			{
 | 
			
		||||
				if (mbres.Data[i] == 0x0000)
 | 
			
		||||
					break;
 | 
			
		||||
				ParseDeviceCode(mbres.Data[i], gIpsSorted[ips[ADi]].Vendor, gIpsSorted[ips[ADi]].DeviceIOs);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (++ADn == 6)
 | 
			
		||||
		AnalyzeDevicesNext();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Step 4: Create the files with the queried data
 | 
			
		||||
/// <Step4>
 | 
			
		||||
void MakeFiles()
 | 
			
		||||
{
 | 
			
		||||
	GenSysvars();
 | 
			
		||||
	GenDbc();
 | 
			
		||||
	stop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Generate the SysVars XML
 | 
			
		||||
/// <Step4>
 | 
			
		||||
void GenSysvars()
 | 
			
		||||
{
 | 
			
		||||
	write("GenSysvars() -> %s", fnSysvar);
 | 
			
		||||
	f.Open(fnSysvar, 0, 0);	// rewrite file in ASCII
 | 
			
		||||
 | 
			
		||||
	PutString(f, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
 | 
			
		||||
	PutString(f, "<systemvariables version=\"4\">\n");
 | 
			
		||||
	PutString(f, "  <namespace name=\"\" comment=\"\">\n");
 | 
			
		||||
 | 
			
		||||
	PutString(f, "    <namespace name=\"Config\" comment=\"\">\n");
 | 
			
		||||
	PutString(f, "      <namespace name=\"Modbus\" comment=\"\">\n");
 | 
			
		||||
	PutString(f, "        <variable anlyzLocal=\"2\" readOnly=\"false\" valueSequence=\"false\" unit=\"ms\" name=\"RequestTimeout\" comment=\"The maximum duration for a Modbus-UDP/-TCP request in milliseconds. After timeout a retransmission may be started (see MaxRetransmissionCount).    Use `ping` to get the maximum latency to a device, double it and add 2-3 ms for processing.\" bitcount=\"32\" isSigned=\"true\" encoding=\"65001\" type=\"int\" startValue=\"");
 | 
			
		||||
			PutString(f, (word)@sysvar::Config::Modbus::RequestTimeout);
 | 
			
		||||
			PutString(f, "\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"1000\" maxValuePhys=\"1000\" />\n");
 | 
			
		||||
	PutString(f, "        <variable anlyzLocal=\"2\" readOnly=\"false\" valueSequence=\"false\" unit=\"\" name=\"Port\" comment=\"\" bitcount=\"32\" isSigned=\"true\" encoding=\"65001\" type=\"int\" startValue=\"");
 | 
			
		||||
			PutString(f, (word)@sysvar::Config::Modbus::Port);
 | 
			
		||||
			PutString(f, "\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"65535\" maxValuePhys=\"65535\" />\n");
 | 
			
		||||
	PutString(f, "        <variable anlyzLocal=\"2\" readOnly=\"false\" valueSequence=\"false\" unit=\"times\" name=\"MaxTransmissionCount\" comment=\"How often a retransmission of a request will be sent until it gets discarded and an error is thrown.\" bitcount=\"32\" isSigned=\"true\" encoding=\"65001\" type=\"int\" startValue=\"");
 | 
			
		||||
			PutString(f, (byte)@sysvar::Config::Modbus::MaxTransmissionCount);
 | 
			
		||||
			PutString(f, "\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10\" maxValuePhys=\"10\" />\n");
 | 
			
		||||
	PutString(f, "      </namespace>\n");
 | 
			
		||||
	PutString(f, "      <namespace name=\"TcpIp\" comment=\"\">\n");
 | 
			
		||||
	PutString(f, "        <variable anlyzLocal=\"2\" readOnly=\"false\" valueSequence=\"false\" unit=\"\" name=\"AdapterIndex\" comment=\"Index of network interface to use\" bitcount=\"32\" isSigned=\"true\" encoding=\"65001\" type=\"int\" startValue=\"2\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"20\" maxValuePhys=\"20\" />\n");
 | 
			
		||||
	PutString(f, "      </namespace>\n");
 | 
			
		||||
	PutString(f, "    </namespace>\n");
 | 
			
		||||
 | 
			
		||||
	for (long net : gIpNets)
 | 
			
		||||
	{
 | 
			
		||||
		byte nett;
 | 
			
		||||
		nett = net;
 | 
			
		||||
		PutString(f, "    <namespace name=\"Ethernet");
 | 
			
		||||
				PutString(f, nett);
 | 
			
		||||
				PutString(f, "\" comment=\"Subnet: 192.168.");
 | 
			
		||||
				PutString(f, nett);
 | 
			
		||||
				PutString(f, ".\">\n");
 | 
			
		||||
 | 
			
		||||
		for (long ipN : gIpsSorted)
 | 
			
		||||
		{
 | 
			
		||||
 | 
			
		||||
			if (((ipN >> 16) & 0xFF) != net)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			PutString(f, "      <namespace name=\"Client_");
 | 
			
		||||
					//PutString(f, netS);
 | 
			
		||||
					//PutString(f, "_");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].IpLsb);
 | 
			
		||||
					PutString(f, "\" comment=\"Server with ip address '");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].Ip);
 | 
			
		||||
					PutString(f, "'\">\n");
 | 
			
		||||
 | 
			
		||||
			// Namespace Config
 | 
			
		||||
			PutString(f, "        <namespace name=\"Config\" comment=\"Configuration section for this server\">\n");
 | 
			
		||||
			// IP
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"false\" valueSequence=\"false\" unit=\"\" name=\"IP\" comment=\"The IP address of this server\" bitcount=\"8\" isSigned=\"true\" encoding=\"65001\" type=\"string\" startValue=\"");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].Ip);
 | 
			
		||||
					PutString(f, "\" />\n");
 | 
			
		||||
			// Intveral
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"false\" valueSequence=\"false\" unit=\"ms\" name=\"Interval\" comment=\"The interval with which the device will be queried\" bitcount=\"32\" isSigned=\"true\" encoding=\"65001\" type=\"int\" startValue=\"100\" minValue=\"10\" minValuePhys=\"10\" maxValue=\"10000\" maxValuePhys=\"10000\" />\n");
 | 
			
		||||
			PutString(f, "        </namespace>\n");
 | 
			
		||||
 | 
			
		||||
			//Namespace Info
 | 
			
		||||
			PutString(f, "        <namespace name=\"Info\" comment=\"Some information about the device\">\n");
 | 
			
		||||
			// Vendor
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"true\" valueSequence=\"false\" unit=\"\" name=\"Vendor\" comment=\"The vendor of the device\" bitcount=\"32\" isSigned=\"true\" encoding=\"65001\" type=\"int\" startValue=\"");
 | 
			
		||||
					PutString(f, (byte)gIpsSorted[ipN].Vendor);
 | 
			
		||||
					PutString(f, "\">\n");
 | 
			
		||||
					PutString(f, "            <valuetable definesMinMax=\"true\">\n");
 | 
			
		||||
					PutString(f, "              <valuetableentry value=\"2\" description=\"BuR\" />\n");
 | 
			
		||||
					PutString(f, "              <valuetableentry value=\"23\" description=\"Wago\" />\n");
 | 
			
		||||
					PutString(f, "            </valuetable>\n");
 | 
			
		||||
					PutString(f, "          </variable>\n");
 | 
			
		||||
			// SerialCode
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"true\" valueSequence=\"false\" unit=\"\" name=\"SerialCode\" comment=\"The serial code of the server\" bitcount=\"32\" isSigned=\"true\" encoding=\"65001\" type=\"int\" startValue=\"");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].SerialCode);
 | 
			
		||||
					PutString(f, "\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10000\" maxValuePhys=\"10000\" />\n");
 | 
			
		||||
			// DeviceCode
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"true\" valueSequence=\"false\" unit=\"\" name=\"DeviceCode\" comment=\"The device code of the server\" bitcount=\"32\" isSigned=\"true\" encoding=\"65001\" type=\"int\" startValue=\"");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].DeviceCode);
 | 
			
		||||
					PutString(f, "\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10000\" maxValuePhys=\"10000\" />\n");
 | 
			
		||||
			// Modules
 | 
			
		||||
			gIpsSorted[ipN].DeviceIOs.Modules[strlen(gIpsSorted[ipN].DeviceIOs.Modules)-1] = 0;
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"true\" valueSequence=\"false\" unit=\"\" name=\"Modules\" comment=\"The type and number of inputs of modules that are connected to the server\" bitcount=\"8\" isSigned=\"true\" encoding=\"65001\" type=\"string\" startValue=\"");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].DeviceIOs.Modules);
 | 
			
		||||
					PutString(f, "\" />\n");
 | 
			
		||||
			// InputRegisters
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"true\" valueSequence=\"false\" unit=\"\" name=\"InputRegisters\" comment=\"Number of input registers\" bitcount=\"32\" isSigned=\"true\" encoding=\"65001\" type=\"int\" startValue=\"");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].DeviceIOs.InputRegisters);
 | 
			
		||||
					PutString(f, "\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"123\" maxValuePhys=\"123\" />\n");
 | 
			
		||||
			// InputBits
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"true\" valueSequence=\"false\" unit=\"\" name=\"InputBits\" comment=\"Number of input bits\" bitcount=\"32\" isSigned=\"true\" encoding=\"65001\" type=\"int\" startValue=\"");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].DeviceIOs.InputBits);
 | 
			
		||||
					PutString(f, "\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"2000\" maxValuePhys=\"2000\" />\n");
 | 
			
		||||
			// OutputRegisters
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"true\" valueSequence=\"false\" unit=\"\" name=\"OutputRegisters\" comment=\"Number of output registers\" bitcount=\"32\" isSigned=\"true\" encoding=\"65001\" type=\"int\" startValue=\"");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].DeviceIOs.OutputRegisters);
 | 
			
		||||
					PutString(f, "\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"123\" maxValuePhys=\"123\" />\n");
 | 
			
		||||
			// OutputBits
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"true\" valueSequence=\"false\" unit=\"\" name=\"OutputBits\" comment=\"Number of output bits\" bitcount=\"32\" isSigned=\"true\" encoding=\"65001\" type=\"int\" startValue=\"");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].DeviceIOs.OutputBits);
 | 
			
		||||
					PutString(f, "\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"2000\" maxValuePhys=\"2000\" />\n");
 | 
			
		||||
			PutString(f, "        </namespace>\n");
 | 
			
		||||
 | 
			
		||||
			// Namespace Data
 | 
			
		||||
			PutString(f, "        <namespace name=\"Data\" comment=\"The actual process image\">\n");
 | 
			
		||||
			// InputRegisters
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"false\" valueSequence=\"false\" unit=\"\" name=\"InputRegisters\" comment=\"The values of the input registers\" bitcount=\"9\" isSigned=\"true\" encoding=\"65001\" type=\"intarray\" arrayLength=\"");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].DeviceIOs.InputRegisters);
 | 
			
		||||
					PutString(f, "\" />\n");
 | 
			
		||||
			// InputBits
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"false\" valueSequence=\"false\" unit=\"\" name=\"InputBits\" comment=\"The state of the input bits\" bitcount=\"2\" isSigned=\"true\" encoding=\"65001\" type=\"intarray\" arrayLength=\"");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].DeviceIOs.InputBits);
 | 
			
		||||
					PutString(f, "\" />\n");
 | 
			
		||||
			// OutputRegisters
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"false\" valueSequence=\"false\" unit=\"\" name=\"OutputRegisters\" comment=\"The values of the output registers. Write here and the values will be sent to the device\" bitcount=\"9\" isSigned=\"true\" encoding=\"65001\" type=\"intarray\" arrayLength=\"");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].DeviceIOs.OutputRegisters);
 | 
			
		||||
					PutString(f, "\" />\n");
 | 
			
		||||
			// OutputBits
 | 
			
		||||
			PutString(f, "          <variable anlyzLocal=\"2\" readOnly=\"false\" valueSequence=\"false\" unit=\"\" name=\"OutputBits\" comment=\"The state of the output bits. Write here and the values will be sent to the device\" bitcount=\"2\" isSigned=\"true\" encoding=\"65001\" type=\"intarray\" arrayLength=\"");
 | 
			
		||||
					PutString(f, gIpsSorted[ipN].DeviceIOs.OutputBits);
 | 
			
		||||
					PutString(f, "\" />\n");
 | 
			
		||||
 | 
			
		||||
			PutString(f, "        </namespace>\n");
 | 
			
		||||
			PutString(f, "      </namespace>\n");
 | 
			
		||||
		}
 | 
			
		||||
		PutString(f, "    </namespace>\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	PutString(f, "  </namespace>\n");
 | 
			
		||||
	PutString(f, "</systemvariables>\n");
 | 
			
		||||
	
 | 
			
		||||
	f.Close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Generate the Database
 | 
			
		||||
/// <Step4>
 | 
			
		||||
void GenDbc()
 | 
			
		||||
{
 | 
			
		||||
	write("GenDbc() -> %s", fnDbc);
 | 
			
		||||
	f.Open(fnDbc, 0, 0);	// rewrite file in ASCII
 | 
			
		||||
 | 
			
		||||
	PutString(f, "VERSION \"\"\n\n\n");
 | 
			
		||||
	PutString(f, "NS_ :\n");
 | 
			
		||||
	PutString(f, "	NS_DESC_\n");
 | 
			
		||||
	PutString(f, "	CM_\n");
 | 
			
		||||
	PutString(f, "	BA_DEF_\n");
 | 
			
		||||
	PutString(f, "	BA_\n");
 | 
			
		||||
	PutString(f, "	VAL_\n");
 | 
			
		||||
	PutString(f, "	CAT_DEF_\n");
 | 
			
		||||
	PutString(f, "	CAT_\n");
 | 
			
		||||
	PutString(f, "	FILTER\n");
 | 
			
		||||
	PutString(f, "	BA_DEF_DEF_\n");
 | 
			
		||||
	PutString(f, "	EV_DATA_\n");
 | 
			
		||||
	PutString(f, "	ENVVAR_DATA_\n");
 | 
			
		||||
	PutString(f, "	SGTYPE_\n");
 | 
			
		||||
	PutString(f, "	SGTYPE_VAL_\n");
 | 
			
		||||
	PutString(f, "	BA_DEF_SGTYPE_\n");
 | 
			
		||||
	PutString(f, "	BA_SGTYPE_\n");
 | 
			
		||||
	PutString(f, "	SIG_TYPE_REF_\n");
 | 
			
		||||
	PutString(f, "	VAL_TABLE_\n");
 | 
			
		||||
	PutString(f, "	SIG_GROUP_\n");
 | 
			
		||||
	PutString(f, "	SIG_VALTYPE_\n");
 | 
			
		||||
	PutString(f, "	SIGTYPE_VALTYPE_\n");
 | 
			
		||||
	PutString(f, "	BO_TX_BU_\n");
 | 
			
		||||
	PutString(f, "	BA_DEF_REL_\n");
 | 
			
		||||
	PutString(f, "	BA_REL_\n");
 | 
			
		||||
	PutString(f, "	BA_DEF_DEF_REL_\n");
 | 
			
		||||
	PutString(f, "	BU_SG_REL_\n");
 | 
			
		||||
	PutString(f, "	BU_EV_REL_\n");
 | 
			
		||||
	PutString(f, "	BU_BO_REL_\n");
 | 
			
		||||
	PutString(f, "	SG_MUL_VAL_\n");
 | 
			
		||||
	PutString(f, "\n");
 | 
			
		||||
	PutString(f, "BS_:\n");
 | 
			
		||||
	PutString(f, "\nBU_:");
 | 
			
		||||
 | 
			
		||||
	for (long ipN : gIpsSorted)
 | 
			
		||||
	{
 | 
			
		||||
		PutString(f, " Client_");
 | 
			
		||||
				//PutString(f, gIpsSorted[ipN].IpNet);
 | 
			
		||||
				//PutString(f, "_");
 | 
			
		||||
				PutString(f, gIpsSorted[ipN].IpLsb);
 | 
			
		||||
	}
 | 
			
		||||
	PutString(f, "\n\n\n\n");
 | 
			
		||||
	PutString(f, "BA_DEF_ BU_  \"NodeLayerModules\" STRING ;\n");
 | 
			
		||||
	PutString(f, "BA_DEF_  \"DBName\" STRING ;\n");
 | 
			
		||||
	PutString(f, "BA_DEF_  \"BusType\" STRING ;\n");
 | 
			
		||||
	PutString(f, "BA_DEF_DEF_  \"NodeLayerModules\" \"Ethernet_IL.DLL\";\n");
 | 
			
		||||
	PutString(f, "BA_DEF_DEF_  \"DBName\" \"\";\n");
 | 
			
		||||
	PutString(f, "BA_DEF_DEF_  \"BusType\" \"Ethernet\";\n");
 | 
			
		||||
	PutString(f, "BA_ \"BusType\" \"Ethernet\";\n");
 | 
			
		||||
	PutString(f, "BA_ \"DBName\" \"");
 | 
			
		||||
			PutString(f, name);
 | 
			
		||||
			PutString(f, "\";\n");
 | 
			
		||||
 | 
			
		||||
	f.Close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// <zzzModbus>
 | 
			
		||||
void OnModbusClientPanics(enum FatalErrors reason)
 | 
			
		||||
{
 | 
			
		||||
	writeLineEx(0, 4, "<%NODE_NAME%> FATAL! %d", reason);
 | 
			
		||||
	switch(reason)
 | 
			
		||||
	{
 | 
			
		||||
		case ParsingBuffer:
 | 
			
		||||
		case ModbusPackageWasSplit:
 | 
			
		||||
		case DeviceCodeUnknown:
 | 
			
		||||
		case VendorIdUnknown:
 | 
			
		||||
		case ConnectionError:
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
/// <zzzModbus>
 | 
			
		||||
void OnModbusWriteBitFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap){}
 | 
			
		||||
/// <zzzModbus>
 | 
			
		||||
void OnModbusWriteRegisterFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap){}
 | 
			
		||||
/// <zzzModbus>
 | 
			
		||||
void OnModbusWriteMasksFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap){}
 | 
			
		||||
/// <zzzModbus>
 | 
			
		||||
void OnModbusReadWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap){}
 | 
			
		||||
/// <zzzModbus>
 | 
			
		||||
void OnModbusWriteBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap){}
 | 
			
		||||
/// <zzzModbus>
 | 
			
		||||
void OnModbusWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap){}
 | 
			
		||||
/// <zzzModbus>
 | 
			
		||||
void OnModbusWriteBitSuccess(struct ModbusResConfirmSingle mbc){}
 | 
			
		||||
/// <zzzModbus>
 | 
			
		||||
void OnModbusWriteRegisterSuccess(struct ModbusResConfirmSingle mbc){}
 | 
			
		||||
/// <zzzModbus>
 | 
			
		||||
void OnModbusWriteBitsSuccess(struct ModbusResConfirmMultiple mbc){}
 | 
			
		||||
/// <zzzModbus>
 | 
			
		||||
void OnModbusWriteRegistersSuccess(struct ModbusResConfirmMultiple mbc){}
 | 
			
		||||
/// <zzzModbus>
 | 
			
		||||
void OnModbusWriteMasksSuccess(struct ModbusResConfirmMasks mbc){}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Modbus-DLL/include/CAPL/MakeConfig.cbf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Modbus-DLL/include/CAPL/MakeConfig.cbf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										246
									
								
								Modbus-DLL/include/CAPL/ModbusClient.can
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								Modbus-DLL/include/CAPL/ModbusClient.can
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,246 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
 | 
			
		||||
includes
 | 
			
		||||
{
 | 
			
		||||
	#include "include\ModbusUdpClientCommon.cin"
 | 
			
		||||
	#include "include\ModbusFunctions.cin"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
variables
 | 
			
		||||
{
 | 
			
		||||
	msTimer gtRead;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get information of local network interface such like ip address
 | 
			
		||||
 | 
			
		||||
on preStart
 | 
			
		||||
{
 | 
			
		||||
	writeClear(0);
 | 
			
		||||
	setStartdelay(10);
 | 
			
		||||
	OutputDebugLevel = Warning;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
on start
 | 
			
		||||
{
 | 
			
		||||
	ModbusInit();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// Read serial code, additional stuff is done in OnModbusReceiveRegisters
 | 
			
		||||
	// This has to be done by MakeConfig to properly size the arrays
 | 
			
		||||
	//ModbusReadRegisters(0x2011, 1);
 | 
			
		||||
	//ModbusReadRegisters(0x2012, 1);
 | 
			
		||||
	//ModbusReadRegisters(0x2030, 65);
 | 
			
		||||
	//ModbusReadRegisters(0x2031, 64);
 | 
			
		||||
	//ModbusReadRegisters(0x2032, 64);
 | 
			
		||||
	//ModbusReadRegisters(0x2033, 63);
 | 
			
		||||
	if (@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits > 0)
 | 
			
		||||
		ModbusReadBits(0x200, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits);
 | 
			
		||||
	if (@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters > 0)
 | 
			
		||||
		ModbusReadRegisters(0x200, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters);
 | 
			
		||||
 | 
			
		||||
	setTimerCyclic(gtRead, 1, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Modbus events ----------------------------------------------------------------------
 | 
			
		||||
void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
 | 
			
		||||
{
 | 
			
		||||
	word i;
 | 
			
		||||
 | 
			
		||||
	switch (error)
 | 
			
		||||
	{
 | 
			
		||||
		case Exception:
 | 
			
		||||
			break;
 | 
			
		||||
		case Timeout:
 | 
			
		||||
			break;
 | 
			
		||||
		case FinalTimeout:
 | 
			
		||||
			sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits");
 | 
			
		||||
			for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputBits; i++)
 | 
			
		||||
				@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputBits[i] = -1;
 | 
			
		||||
			sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits");
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
 | 
			
		||||
{
 | 
			
		||||
	byte i;
 | 
			
		||||
 | 
			
		||||
	switch (error)
 | 
			
		||||
	{
 | 
			
		||||
		case Exception:
 | 
			
		||||
			break;
 | 
			
		||||
		case Timeout:
 | 
			
		||||
			break;
 | 
			
		||||
		case FinalTimeout:
 | 
			
		||||
			sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters");
 | 
			
		||||
			for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters; i++)
 | 
			
		||||
				@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputRegisters[i] = -1;
 | 
			
		||||
			sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters");
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OnModbusWriteBitFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
void OnModbusWriteRegisterFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
void OnModbusWriteMasksFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
void OnModbusReadWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
void OnModbusWriteBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
void OnModbusWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq)
 | 
			
		||||
{
 | 
			
		||||
	word i;
 | 
			
		||||
 | 
			
		||||
	switch(mbreq.Address)
 | 
			
		||||
	{
 | 
			
		||||
		case 0x200:		// set output bits
 | 
			
		||||
			sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
 | 
			
		||||
			for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits; i++)
 | 
			
		||||
				@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits[i] = bitStatus[i];
 | 
			
		||||
			sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
 | 
			
		||||
			break;
 | 
			
		||||
		default:		// set input bits
 | 
			
		||||
			sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits");
 | 
			
		||||
			for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputBits; i++)
 | 
			
		||||
				@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputBits[i] = bitStatus[i];
 | 
			
		||||
			sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits");
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq)
 | 
			
		||||
{
 | 
			
		||||
	char str[20*5];
 | 
			
		||||
	long fehler;
 | 
			
		||||
	byte i;
 | 
			
		||||
 | 
			
		||||
	switch (mbreq.Address)
 | 
			
		||||
	{
 | 
			
		||||
		case 0x200:		// set output registers
 | 
			
		||||
			sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputRegisters");
 | 
			
		||||
			for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters; i++)
 | 
			
		||||
				@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters[i] = mbres.Data[i];
 | 
			
		||||
			sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputRegisters");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x000:		// set output registers
 | 
			
		||||
			sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters");
 | 
			
		||||
			for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters; i++)
 | 
			
		||||
				@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputRegisters[i] = mbres.Data[i];
 | 
			
		||||
			sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters");
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			// Not recognized
 | 
			
		||||
			dbin_to_strhex(mbres.Data, str);
 | 
			
		||||
			writeLineEx(0, 1, "<%NODE_NAME%> OnModbusReceiveRegisters: Received %d bytes at 0x%04X: %s", mbres.ByteCount, mbreq.Address, str);
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OnModbusWriteBitSuccess(struct ModbusResConfirmSingle mbc)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
void OnModbusWriteRegisterSuccess(struct ModbusResConfirmSingle mbc)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
void OnModbusWriteBitsSuccess(struct ModbusResConfirmMultiple mbc)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
void OnModbusWriteRegistersSuccess(struct ModbusResConfirmMultiple mbc)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
void OnModbusWriteMasksSuccess(struct ModbusResConfirmMasks mbc)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OnModbusClientPanics(enum FatalErrors reason)
 | 
			
		||||
{
 | 
			
		||||
	writeLineEx(0, 4, "<%NODE_NAME%> FATAL! %d", reason);
 | 
			
		||||
	switch(reason)
 | 
			
		||||
	{
 | 
			
		||||
		case ParsingBuffer:
 | 
			
		||||
		case ModbusPackageWasSplit:
 | 
			
		||||
		case DeviceCodeUnknown:
 | 
			
		||||
		case VendorIdUnknown:
 | 
			
		||||
			runError(1001, reason);
 | 
			
		||||
			break;
 | 
			
		||||
		case ConnectionError:
 | 
			
		||||
			gtRead.Cancel();
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Key events -------------------------------------------------------------------------
 | 
			
		||||
on timer gtRead
 | 
			
		||||
{
 | 
			
		||||
	if (@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters > 0)
 | 
			
		||||
		ModbusReadRegisters(0x0000, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters);
 | 
			
		||||
	if (@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputBits > 0)
 | 
			
		||||
		ModbusReadBits(@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters * 2, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputBits);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits
 | 
			
		||||
{
 | 
			
		||||
	word firstBitAddr, count, i;
 | 
			
		||||
	byte bitStatus[1968];
 | 
			
		||||
 | 
			
		||||
	firstBitAddr = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters * 2;
 | 
			
		||||
	count = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < count; i++)
 | 
			
		||||
		bitStatus[i] = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits[i];
 | 
			
		||||
 | 
			
		||||
	ModbusWriteBitsB(firstBitAddr, count, bitStatus);
 | 
			
		||||
}
 | 
			
		||||
on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters
 | 
			
		||||
{
 | 
			
		||||
	word count, i;
 | 
			
		||||
	word regValues[123];
 | 
			
		||||
 | 
			
		||||
	count = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < count; i++)
 | 
			
		||||
		regValues[i] = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters[i];
 | 
			
		||||
 | 
			
		||||
	ModbusWriteRegisters(0x000, count, regValues);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval
 | 
			
		||||
{
 | 
			
		||||
	if (@this <= 0)
 | 
			
		||||
		gtRead.Cancel();
 | 
			
		||||
	else
 | 
			
		||||
		setTimerCyclic(gtRead, @this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
on key '+'
 | 
			
		||||
{
 | 
			
		||||
	word i;
 | 
			
		||||
 | 
			
		||||
	sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
 | 
			
		||||
	for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits; i++)
 | 
			
		||||
		@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits[i] = 1;
 | 
			
		||||
	sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
 | 
			
		||||
}
 | 
			
		||||
on key '-'
 | 
			
		||||
{
 | 
			
		||||
	word i;
 | 
			
		||||
 | 
			
		||||
	sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
 | 
			
		||||
	for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits; i++)
 | 
			
		||||
		@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits[i] = 0;
 | 
			
		||||
	sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Modbus-DLL/include/CAPL/ModbusClient.cbf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Modbus-DLL/include/CAPL/ModbusClient.cbf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Modbus-DLL/include/CAPL/ModbusClientUDP.cbf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Modbus-DLL/include/CAPL/ModbusClientUDP.cbf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										263
									
								
								Modbus-DLL/include/CAPL/include/Common.cin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								Modbus-DLL/include/CAPL/include/Common.cin
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,263 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
 | 
			
		||||
variables
 | 
			
		||||
{
 | 
			
		||||
	enum DebugLvl { 
 | 
			
		||||
		Debug		= 0x00,
 | 
			
		||||
		AlgoDebug	= 0x02,
 | 
			
		||||
		ConnDebug	= 0x04,
 | 
			
		||||
		MbDebug		= 0x07,
 | 
			
		||||
 | 
			
		||||
		Info		= 0x10,
 | 
			
		||||
		AlgoInfo	= 0x12,
 | 
			
		||||
		ConnInfo	= 0x14,
 | 
			
		||||
		MbInfo		= 0x17,
 | 
			
		||||
 | 
			
		||||
		Warning		= 0x20,
 | 
			
		||||
		AlgoWarning	= 0x22,
 | 
			
		||||
		ConnWarning	= 0x24,
 | 
			
		||||
		MbWarning	= 0x27,
 | 
			
		||||
 | 
			
		||||
		Error		= 0x30,
 | 
			
		||||
		AlgoError	= 0x32,
 | 
			
		||||
		ConnError	= 0x34,
 | 
			
		||||
		MbError		= 0x37
 | 
			
		||||
    };
 | 
			
		||||
	char DebugLvlStr[4][8] = {"Debug", "Info", "Warning", "Error"};
 | 
			
		||||
	enum DebugLvl OutputDebugLevel = Debug;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <writeDbg>
 | 
			
		||||
void writeDbgFormat(byte lVl, char msg[], char format[])
 | 
			
		||||
{
 | 
			
		||||
	strncpy(msg, "<%NODE_NAME%> ", elCount(msg));
 | 
			
		||||
	strncat(msg, DebugLvlStr[lVl], elCount(msg));
 | 
			
		||||
	strncat(msg, ": ", elCount(msg));
 | 
			
		||||
	strncat(msg, format, elCount(msg)-strlen(msg));
 | 
			
		||||
}
 | 
			
		||||
/// <writeDbg>
 | 
			
		||||
void writeDbg(enum DebugLvl lvl, char format[])
 | 
			
		||||
{
 | 
			
		||||
	char msg[500];
 | 
			
		||||
	byte lVl;
 | 
			
		||||
 | 
			
		||||
	if (lvl < OutputDebugLevel)
 | 
			
		||||
		return;
 | 
			
		||||
	lVl = (byte)lvl >> 4;
 | 
			
		||||
 | 
			
		||||
	writeDbgFormat(lVl, msg, format);
 | 
			
		||||
	writeLineEx(1, lVl, msg);
 | 
			
		||||
}
 | 
			
		||||
/// <writeDbg>
 | 
			
		||||
void writeDbg(enum DebugLvl lvl, char format[], char string[])
 | 
			
		||||
{
 | 
			
		||||
	char msg[500];
 | 
			
		||||
	byte lVl;
 | 
			
		||||
 | 
			
		||||
	if (lvl < OutputDebugLevel)
 | 
			
		||||
		return;
 | 
			
		||||
	lVl = (byte)lvl >> 4;
 | 
			
		||||
 | 
			
		||||
	writeDbgFormat(lVl, msg, format);
 | 
			
		||||
	writeLineEx(1, lVl, msg, string);
 | 
			
		||||
}
 | 
			
		||||
/// <writeDbg>
 | 
			
		||||
void writeDbg(enum DebugLvl lvl, char format[], char string1[], char string2[])
 | 
			
		||||
{
 | 
			
		||||
	char msg[500];
 | 
			
		||||
	byte lVl;
 | 
			
		||||
 | 
			
		||||
	if (lvl < OutputDebugLevel)
 | 
			
		||||
		return;
 | 
			
		||||
	lVl = (byte)lvl >> 4;
 | 
			
		||||
 | 
			
		||||
	writeDbgFormat(lVl, msg, format);
 | 
			
		||||
	writeLineEx(1, lVl, msg, string1, string2);
 | 
			
		||||
}
 | 
			
		||||
/// <writeDbg>
 | 
			
		||||
void writeDbg(enum DebugLvl lvl, char format[], long num, char string[])
 | 
			
		||||
{
 | 
			
		||||
	char msg[500];
 | 
			
		||||
	byte lVl;
 | 
			
		||||
 | 
			
		||||
	if (lvl < OutputDebugLevel)
 | 
			
		||||
		return;
 | 
			
		||||
	lVl = (byte)lvl >> 4;
 | 
			
		||||
 | 
			
		||||
	writeDbgFormat(lVl, msg, format);
 | 
			
		||||
	writeLineEx(1, lVl, msg, num, string);
 | 
			
		||||
}
 | 
			
		||||
/// <writeDbg>
 | 
			
		||||
void writeDbg(enum DebugLvl lvl, char format[], char string[], long num)
 | 
			
		||||
{
 | 
			
		||||
	char msg[500];
 | 
			
		||||
	byte lVl;
 | 
			
		||||
 | 
			
		||||
	if (lvl < OutputDebugLevel)
 | 
			
		||||
		return;
 | 
			
		||||
	lVl = (byte)lvl >> 4;
 | 
			
		||||
 | 
			
		||||
	writeDbgFormat(lVl, msg, format);
 | 
			
		||||
	writeLineEx(1, lVl, msg, string, num);
 | 
			
		||||
}
 | 
			
		||||
/// <writeDbg>
 | 
			
		||||
void writeDbg(enum DebugLvl lvl, char format[], long num1)
 | 
			
		||||
{
 | 
			
		||||
	char msg[500];
 | 
			
		||||
	byte lVl;
 | 
			
		||||
 | 
			
		||||
	if (lvl < OutputDebugLevel)
 | 
			
		||||
		return;
 | 
			
		||||
	lVl = (byte)lvl >> 4;
 | 
			
		||||
 | 
			
		||||
	writeDbgFormat(lVl, msg, format);
 | 
			
		||||
	writeLineEx(1, lVl, msg, num1);
 | 
			
		||||
}
 | 
			
		||||
/// <writeDbg>
 | 
			
		||||
void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, char string[])
 | 
			
		||||
{
 | 
			
		||||
	char msg[500];
 | 
			
		||||
	byte lVl;
 | 
			
		||||
 | 
			
		||||
	if (lvl < OutputDebugLevel)
 | 
			
		||||
		return;
 | 
			
		||||
	lVl = (byte)lvl >> 4;
 | 
			
		||||
 | 
			
		||||
	writeDbgFormat(lVl, msg, format);
 | 
			
		||||
	writeLineEx(1, lVl, msg, num1, num2, string);
 | 
			
		||||
}
 | 
			
		||||
/// <writeDbg>
 | 
			
		||||
void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2)
 | 
			
		||||
{
 | 
			
		||||
	char msg[500];
 | 
			
		||||
	byte lVl;
 | 
			
		||||
 | 
			
		||||
	if (lvl < OutputDebugLevel)
 | 
			
		||||
		return;
 | 
			
		||||
	lVl = (byte)lvl >> 4;
 | 
			
		||||
 | 
			
		||||
	writeDbgFormat(lVl, msg, format);
 | 
			
		||||
	writeLineEx(1, lVl, msg, num1, num2);
 | 
			
		||||
}
 | 
			
		||||
/// <writeDbg>
 | 
			
		||||
void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, long num3)
 | 
			
		||||
{
 | 
			
		||||
	char msg[500];
 | 
			
		||||
	byte lVl;
 | 
			
		||||
 | 
			
		||||
	if (lvl < OutputDebugLevel)
 | 
			
		||||
		return;
 | 
			
		||||
	lVl = (byte)lvl >> 4;
 | 
			
		||||
 | 
			
		||||
	writeDbgFormat(lVl, msg, format);
 | 
			
		||||
	writeLineEx(1, lVl, msg, num1, num2, num3);
 | 
			
		||||
}
 | 
			
		||||
/// <writeDbg>
 | 
			
		||||
void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, long num3, long num4)
 | 
			
		||||
{
 | 
			
		||||
	char msg[500];
 | 
			
		||||
	byte lVl;
 | 
			
		||||
 | 
			
		||||
	if (lvl < OutputDebugLevel)
 | 
			
		||||
		return;
 | 
			
		||||
	lVl = (byte)lvl >> 4;
 | 
			
		||||
 | 
			
		||||
	writeDbgFormat(lVl, msg, format);
 | 
			
		||||
	writeLineEx(1, lVl, msg, num1, num2, num3, num4);
 | 
			
		||||
}
 | 
			
		||||
/// <writeDbg>
 | 
			
		||||
void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, long num3, long num4, long num5, long num6)
 | 
			
		||||
{
 | 
			
		||||
	char msg[500];
 | 
			
		||||
	byte lVl;
 | 
			
		||||
 | 
			
		||||
	if (lvl < OutputDebugLevel)
 | 
			
		||||
		return;
 | 
			
		||||
	lVl = (byte)lvl >> 4;
 | 
			
		||||
 | 
			
		||||
	writeDbgFormat(lVl, msg, format);
 | 
			
		||||
	writeLineEx(1, lVl, msg, num1, num2, num3, num4, num5, num6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void bin_to_strhex(byte bin[], char result[])
 | 
			
		||||
{
 | 
			
		||||
	char hex_str[17] = "0123456789ABCDEF";
 | 
			
		||||
	word i;
 | 
			
		||||
	word binsz;
 | 
			
		||||
	
 | 
			
		||||
	binsz = elCount(bin);
 | 
			
		||||
	if (binsz > 20)
 | 
			
		||||
		binsz = 20;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < binsz; i++)
 | 
			
		||||
	{
 | 
			
		||||
		result[i * 3 + 0] = hex_str[bin[i] >> 4  ];
 | 
			
		||||
		result[i * 3 + 1] = hex_str[bin[i] & 0x0F];
 | 
			
		||||
		result[i * 3 + 2] = ' ';
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (elCount(bin) > 20)	// trailing "..."
 | 
			
		||||
	{
 | 
			
		||||
		result[56] = '.';
 | 
			
		||||
		result[57] = '.';
 | 
			
		||||
		result[58] = '.';
 | 
			
		||||
	}
 | 
			
		||||
	result[binsz * 3 - 1] = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hbin_to_strhex(byte bin[], char result[])
 | 
			
		||||
{
 | 
			
		||||
	char hex_str[17] = "0123456789ABCDEF";
 | 
			
		||||
	word i;
 | 
			
		||||
	word binsz;
 | 
			
		||||
	
 | 
			
		||||
	binsz = elCount(bin);
 | 
			
		||||
	if (binsz > 20)
 | 
			
		||||
		binsz = 20;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < binsz; i++)
 | 
			
		||||
	{
 | 
			
		||||
		result[i * 2 + 0] = hex_str[bin[i] & 0x0F];
 | 
			
		||||
		result[i * 2 + 1] = ' ';
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (elCount(bin) > 20)	// trailing "..."
 | 
			
		||||
	{
 | 
			
		||||
		result[36] = '.';
 | 
			
		||||
		result[37] = '.';
 | 
			
		||||
		result[38] = '.';
 | 
			
		||||
	}
 | 
			
		||||
	result[binsz * 2 - 1] = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dbin_to_strhex(word bin[], char result[])
 | 
			
		||||
{
 | 
			
		||||
	char hex_str[17] = "0123456789ABCDEF";
 | 
			
		||||
	word i;
 | 
			
		||||
	word binsz;
 | 
			
		||||
	byte offset;
 | 
			
		||||
	
 | 
			
		||||
	binsz = elCount(bin);
 | 
			
		||||
	if (binsz > 20)
 | 
			
		||||
		binsz = 20;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < binsz; i++)
 | 
			
		||||
	{
 | 
			
		||||
		result[i * 5 + 0] = hex_str[(bin[i] >> 12) & 0x0F];
 | 
			
		||||
		result[i * 5 + 1] = hex_str[(bin[i] >>  8) & 0x0F];
 | 
			
		||||
		result[i * 5 + 2] = hex_str[(bin[i] >>  4) & 0x0F];
 | 
			
		||||
		result[i * 5 + 3] = hex_str[(bin[i]      ) & 0x0F];
 | 
			
		||||
		result[i * 5 + 4] = ' ';
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (elCount(bin) > 20)	// trailing "..."
 | 
			
		||||
	{
 | 
			
		||||
		result[96] = '.';
 | 
			
		||||
		result[97] = '.';
 | 
			
		||||
		result[98] = '.';
 | 
			
		||||
	}
 | 
			
		||||
	result[(byte)(binsz * 2.5) - 1] = 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										167
									
								
								Modbus-DLL/include/CAPL/include/EilCommon.cin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								Modbus-DLL/include/CAPL/include/EilCommon.cin
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,167 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
includes
 | 
			
		||||
{
 | 
			
		||||
	#include "Common.cin"
 | 
			
		||||
	#include "TcpUdpCommon.cin"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
variables
 | 
			
		||||
{
 | 
			
		||||
	long gPacket;
 | 
			
		||||
	msTimer gtArp;
 | 
			
		||||
	
 | 
			
		||||
	byte gLocalMac[6];
 | 
			
		||||
	byte gRemoteMac[6];
 | 
			
		||||
	dword gLocalIP = 0xC0A80101;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
word EilConnectTo(char Remote_IP[], word remotePort)
 | 
			
		||||
{
 | 
			
		||||
	dword remoteIp;
 | 
			
		||||
 | 
			
		||||
	// Convert IP string to Number
 | 
			
		||||
	remoteIp = IpGetAddressAsNumber(Remote_IP);
 | 
			
		||||
	if (remoteIp == INVALID_IP)
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnError, "EilConnectTo: invalid server Ip address!");
 | 
			
		||||
		OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return ipGetLastError();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return EilConnectTo(remoteIp, remotePort);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
word EilConnectTo(dword remoteIp, word remotePort)
 | 
			
		||||
{
 | 
			
		||||
	long error;
 | 
			
		||||
	byte broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 | 
			
		||||
 | 
			
		||||
	if (EthGetMacId(gLocalMac) != 0)
 | 
			
		||||
	{
 | 
			
		||||
		gSocketState = ERROR;
 | 
			
		||||
		error = EthGetLastError();
 | 
			
		||||
		writeDbg(ConnError, "EthGetMacId: Could not get local MAC! %d", error);
 | 
			
		||||
		OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TCP/IP API gives IP in little endian but EIL uses big endian
 | 
			
		||||
	gRemotePort = remotePort;
 | 
			
		||||
	gRemoteIP = (remoteIp >> 24) | (remoteIp >> 8) & 0x0000FF00 | (remoteIp << 8) & 0x00FF0000 | (remoteIp << 24);
 | 
			
		||||
 | 
			
		||||
	if (gPacket != 0)
 | 
			
		||||
		ModbusDisconnect();
 | 
			
		||||
	// Try to create an ARP packet that gets the MAC from remote server
 | 
			
		||||
	gPacket = EthInitPacket("arp");
 | 
			
		||||
	if (gPacket == 0)
 | 
			
		||||
	{
 | 
			
		||||
		gSocketState = ERROR;
 | 
			
		||||
		error = EthGetLastError();
 | 
			
		||||
		writeDbg(ConnError, "EthInitPacket: Could not create ARP package! %d", error);
 | 
			
		||||
		OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	EthSetTokenData(gPacket,	"eth",	"source"				, elCount(gLocalMac), gLocalMac);
 | 
			
		||||
	EthSetTokenData(gPacket,	"eth",	"destination"			, elCount(broadcastMac), broadcastMac);
 | 
			
		||||
	EthSetTokenInt(gPacket,		"arp",	"hwType"				, 1);			// Ethernet
 | 
			
		||||
	EthSetTokenInt(gPacket,		"arp",	"protType"				, 0x0800);		// IPv4
 | 
			
		||||
	EthSetTokenInt(gPacket,		"arp",	"hwSize"				, 6);			// Ethernet addr size
 | 
			
		||||
	EthSetTokenInt(gPacket,		"arp",	"protSize"				, 4);			// IP addr size
 | 
			
		||||
	EthSetTokenInt(gPacket,		"arp",	"operation"				, 1);
 | 
			
		||||
	EthSetTokenData(gPacket,	"arp",	"hwSourceAddr"			, elCount(gLocalMac), gLocalMac);
 | 
			
		||||
	EthSetTokenInt(gPacket,		"arp",	"protSourceAddr"		, gLocalIP);
 | 
			
		||||
	//EthSetTokenData(gPacket,	"arp",	"hwDestinationAddr"		, elCount(gLocalMac), gLocalMac);
 | 
			
		||||
	EthSetTokenInt(gPacket,		"arp",	"protDestinationAddr"	, gRemoteIP);
 | 
			
		||||
 | 
			
		||||
	EthReceivePacket("OnEthReceivePacket");
 | 
			
		||||
 | 
			
		||||
	EthCompletePacket(gPacket);
 | 
			
		||||
	EthOutputPacket(gPacket);
 | 
			
		||||
	EthReleasePacket(gPacket);
 | 
			
		||||
	gSocketState = NULL;
 | 
			
		||||
	gtArp.set(@sysvar::Config::Modbus::RequestTimeout);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EilConnectTo2()
 | 
			
		||||
{
 | 
			
		||||
	gPacket = EthInitPacket("udp");
 | 
			
		||||
	if (gPacket == 0)
 | 
			
		||||
	{
 | 
			
		||||
		gSocketState = ERROR;
 | 
			
		||||
		writeDbg(ConnError, "EthInitPacket: Could not create UDP packet: %d", EthGetLastError());
 | 
			
		||||
		OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	EthSetTokenData(gPacket,	"eth",	"source"				, elCount(gLocalMac), gLocalMac);
 | 
			
		||||
	EthSetTokenData(gPacket,	"eth",	"destination"			, elCount(gRemoteMac), gRemoteMac);
 | 
			
		||||
	EthSetTokenInt(gPacket,		"ipv4",	"source"				, gLocalIP);
 | 
			
		||||
	EthSetTokenInt(gPacket,		"ipv4",	"destination"			, gRemoteIP);
 | 
			
		||||
	EthSetTokenInt(gPacket,		"udp",	"source"				, 23456);
 | 
			
		||||
	EthSetTokenInt(gPacket,		"udp",	"destination"			, 502);
 | 
			
		||||
 | 
			
		||||
	gSocketState = OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EilDisconnect()
 | 
			
		||||
{
 | 
			
		||||
	if (gPacket != 0)
 | 
			
		||||
	{
 | 
			
		||||
		EthReleasePacket(gPacket);
 | 
			
		||||
		gPacket = 0;
 | 
			
		||||
	}
 | 
			
		||||
	gSocketState = CLOSED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void EilRecv()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
byte EilSnd(byte buffer[], word length)
 | 
			
		||||
{
 | 
			
		||||
	char str[20*3];
 | 
			
		||||
 | 
			
		||||
	switch (gSocketState)
 | 
			
		||||
	{
 | 
			
		||||
		case CLOSED:
 | 
			
		||||
			EilConnectTo(gRemoteIP, gRemotePort);
 | 
			
		||||
			if (gSocketState != OK)
 | 
			
		||||
			{
 | 
			
		||||
				writeDbg(ConnWarning, "EilSnd: Reconnecting failed! Doing nothing.");
 | 
			
		||||
				return 1;
 | 
			
		||||
			}
 | 
			
		||||
		case OK:
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			writeDbg(ConnWarning, "EilSnd: Socket status is not OK! Doing nothing.");
 | 
			
		||||
			return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bin_to_strhex(buffer, str);
 | 
			
		||||
	writeDbg(ConnDebug, "EilSnd: %s (Länge: %d)", str, length);
 | 
			
		||||
 | 
			
		||||
	EthResizeToken(gPacket,		"udp",	"data"	, length*8);
 | 
			
		||||
	EthSetTokenData(gPacket,	"udp",	"data"	, length, buffer);
 | 
			
		||||
 | 
			
		||||
	EthCompletePacket(gPacket);
 | 
			
		||||
	EthOutputPacket(gPacket);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
long EilGetLastConnectionError(char string[])
 | 
			
		||||
{
 | 
			
		||||
	EthGetLastErrorText(elCount(string), string);
 | 
			
		||||
	return EthGetLastError();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
on timer gtArp
 | 
			
		||||
{
 | 
			
		||||
	gSocketState = ERROR;
 | 
			
		||||
	writeDbg(ConnError, "No (valid) ARP response detected. The host seems to be offline!");
 | 
			
		||||
	OnModbusClientPanics(ConnectionError);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										786
									
								
								Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										786
									
								
								Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,786 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
// Additionally include ModbusTcpCommon.cin or ModbusUdpCommon.cin
 | 
			
		||||
includes
 | 
			
		||||
{
 | 
			
		||||
	#include "ModbusStructs.cin"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
variables
 | 
			
		||||
{
 | 
			
		||||
	const word gMaxPacketLength = __size_of(struct ModbusReqWriteRegisters);
 | 
			
		||||
	
 | 
			
		||||
	msTimer gtRobin;				// Timer that sends the packets and watches for timeouts
 | 
			
		||||
	word gTxID = 0x0000;			// Transaction Identifier for Modbus. Used as index for gQueue
 | 
			
		||||
 | 
			
		||||
	// Global storage for pending and sent requests, associated by TxID
 | 
			
		||||
	struct QueueElement
 | 
			
		||||
	{
 | 
			
		||||
		word TimeoutTicks;
 | 
			
		||||
		byte Timeouts;
 | 
			
		||||
		word Length;
 | 
			
		||||
		byte Buffer[gMaxPacketLength];
 | 
			
		||||
	};
 | 
			
		||||
	struct QueueElement gQueuePending[long, 2];
 | 
			
		||||
	struct QueueElement gQueueSent[long, 2];
 | 
			
		||||
	struct QueueElement gQueueAck[long, 2];
 | 
			
		||||
 | 
			
		||||
	char ModbusExceptions[11][72] = {
 | 
			
		||||
		"Illegal func code (0x01). The function code is unknown by the server",
 | 
			
		||||
		"Illegal data address (0x02). Please check your configuration",
 | 
			
		||||
		"Illegal data value (0x03)",
 | 
			
		||||
		"Server failure (0x04). The server failed during execution",
 | 
			
		||||
		"Acknowledge (0x05). The server needs more time to generate the response",
 | 
			
		||||
		"Server busy (0x06). The request could not be accepted",
 | 
			
		||||
		"",
 | 
			
		||||
		"",
 | 
			
		||||
		"",
 | 
			
		||||
		"Gateway problem (0x0A). Gateway paths not available",
 | 
			
		||||
		"Gateway problem (0x0B). The targeted device failed to respond"
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusInit()
 | 
			
		||||
{
 | 
			
		||||
	char ip[16];
 | 
			
		||||
	sysGetVariableString("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config", "IP", ip, elCount(ip));
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbInfo, "Connecting to %s:%d", ip, @sysvar::Config::Modbus::Port);
 | 
			
		||||
	ModbusConnectTo(ip, @sysvar::Config::Modbus::Port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusMakeHeader(struct ModbusApHeader mbap, word length)
 | 
			
		||||
{
 | 
			
		||||
	mbap.TxID = gTxID++;		// [2] Transaction ID
 | 
			
		||||
	mbap.Protocol = 0x0000;		// [2] Protocol ID = 0 = Modbus
 | 
			
		||||
	mbap.Length = length - __offset_of(struct ModbusApHeader, UnitID);	// [2] Length; Number of bytes following
 | 
			
		||||
	mbap.UnitID = 0xFF;			// [1] Unit identifier; not relevant
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// REGION: ModbusReadBits -------------------------------------------------------------
 | 
			
		||||
/// <ModbusReadBits>
 | 
			
		||||
void ModbusReadBits(word address, word count)
 | 
			
		||||
{
 | 
			
		||||
	const byte length = __size_of(struct ModbusReqRead);
 | 
			
		||||
	const byte funcCode = 0x01;
 | 
			
		||||
	byte buffer[length];
 | 
			
		||||
	struct ModbusReqRead mbr;
 | 
			
		||||
 | 
			
		||||
	ModbusMakeHeader(mbr.Header, length);
 | 
			
		||||
	// Payload
 | 
			
		||||
	mbr.Header.FuncCode = funcCode;	// [1] Function Code; 1: Read Coils (DI), 2: Read Discret Inputs (DIO), seems to be the same for WAGO 750-881
 | 
			
		||||
	mbr.Address = address;			// [2] Start address
 | 
			
		||||
	mbr.Count = count;				// [2] Number of items; 1:max 2000=0x7D0
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbDebug, "Sending 'Read Bits' (0x01) command. Addr: 0x%04X, Count: %d", address, count);
 | 
			
		||||
	
 | 
			
		||||
	memcpy_h2n(buffer, mbr);
 | 
			
		||||
	ModbusSend(buffer, length, mbr.Header.TxID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusReadBits>
 | 
			
		||||
void OnModbusReceiveBits(byte buffer[])
 | 
			
		||||
{
 | 
			
		||||
	struct ModbusResReceiveBits mbres;
 | 
			
		||||
	struct ModbusReqRead mbreq;
 | 
			
		||||
	byte bitStatus[1968];
 | 
			
		||||
	word numBits;
 | 
			
		||||
	byte i, j;
 | 
			
		||||
 | 
			
		||||
	memcpy_n2h(mbres, buffer);
 | 
			
		||||
	memcpy_n2h(mbreq, gQueueAck[mbres.Header.TxID].Buffer);
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbDebug, "Received %d bits from 0x%04X", mbreq.Count, mbreq.Address);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < mbres.ByteCount; i++)
 | 
			
		||||
	{
 | 
			
		||||
		for (j = 0; j < 8; j++)
 | 
			
		||||
		{
 | 
			
		||||
			bitStatus[8*i+j] = (mbres.Data[i] >> j) & 0x01;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	OnModbusReadBitsSuccess(mbres, bitStatus, mbreq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusReadBits>
 | 
			
		||||
void OnModbusReceiveBitsException(struct ModbusApHeader mbap, enum ModbusException ex)
 | 
			
		||||
{
 | 
			
		||||
	writeDbg(MbError, "Received an Exception while reading bits: %s", ModbusExceptions[ex-1]);
 | 
			
		||||
	OnModbusReadBitsFailed(Exception, ex, mbap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// REGION: ModbusReadRegisters -------------------------------------------------------
 | 
			
		||||
/// <ModbusReadRegisters>
 | 
			
		||||
void ModbusReadRegisters(word address, word count)	// 16 bit
 | 
			
		||||
{
 | 
			
		||||
	const byte length = __size_of(struct ModbusReqRead);
 | 
			
		||||
	const byte funcCode = 0x03;
 | 
			
		||||
	byte buffer[length];
 | 
			
		||||
	struct ModbusReqRead mbr;
 | 
			
		||||
	
 | 
			
		||||
	ModbusMakeHeader(mbr.Header, length);
 | 
			
		||||
	// Payload
 | 
			
		||||
	mbr.Header.FuncCode = funcCode;	// [1] Function Code; 3: Read Holding Registers (AI), 4: Read Input Registers (AIO), seems to be the same for WAGO 750-881
 | 
			
		||||
	mbr.Address = address;			// [2] Start address
 | 
			
		||||
	mbr.Count = count;				// [2] Number of items; 1:max 125=0x7D
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbDebug, "Sending 'Read Registers' (0x03) command. Addr: 0x%04X, Count: %d", address, count);
 | 
			
		||||
 | 
			
		||||
	memcpy_h2n(buffer, mbr);
 | 
			
		||||
	ModbusSend(buffer, length, mbr.Header.TxID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusReadRegisters>
 | 
			
		||||
void OnModbusReceiveRegisters(byte buffer[])
 | 
			
		||||
{
 | 
			
		||||
	struct ModbusResReceiveRegisters mbres;
 | 
			
		||||
	struct ModbusReqRead mbreq;
 | 
			
		||||
 | 
			
		||||
	memcpy_n2h(mbres, buffer);
 | 
			
		||||
	memcpy_n2h(mbreq, gQueueAck[mbres.Header.TxID].Buffer);
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbDebug, "Received %d registers from 0x%04X", mbreq.Count, mbreq.Address);
 | 
			
		||||
 | 
			
		||||
	OnModbusReadRegistersSuccess(mbres, mbreq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusReadRegisters>
 | 
			
		||||
void OnModbusReceiveRegistersException(struct ModbusApHeader mbap, enum ModbusException ex)
 | 
			
		||||
{
 | 
			
		||||
	writeDbg(MbError, "Received an Exception while reading registers: %s", ModbusExceptions[ex-1]);
 | 
			
		||||
	OnModbusReadRegistersFailed(Exception, ex, mbap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// REGION: ModbusWriteBit -------------------------------------------------------------
 | 
			
		||||
/// <ModbusWriteBit>
 | 
			
		||||
void ModbusWriteBit(word address, byte value)
 | 
			
		||||
{
 | 
			
		||||
	const byte length = __size_of(struct ModbusReqWriteSingle);
 | 
			
		||||
	const byte funcCode = 0x05;
 | 
			
		||||
	byte buffer[length];
 | 
			
		||||
	struct ModbusReqWriteSingle mbw;
 | 
			
		||||
 | 
			
		||||
	if (value >= 1)
 | 
			
		||||
		value = 0xFF;
 | 
			
		||||
 | 
			
		||||
	ModbusMakeHeader(mbw.Header, length);
 | 
			
		||||
	// Payload
 | 
			
		||||
	mbw.Header.FuncCode = funcCode;	// [1] Function Code; 5: Write Single Coil (DO)
 | 
			
		||||
	mbw.Address = address;			// [2] Output address
 | 
			
		||||
	mbw.Value = value << 8;			// [2] Output value (0x0000: Off, 0xFF00: On)
 | 
			
		||||
 | 
			
		||||
	writeDbg(Debug, "Sending 'Write Bit' (0x05) command. Addr: 0x%04X, Value: 0x%02X", address, value);
 | 
			
		||||
	
 | 
			
		||||
	memcpy_h2n(buffer, mbw);
 | 
			
		||||
	ModbusSend(buffer, length, mbw.Header.TxID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusWriteBit>
 | 
			
		||||
void OnModbusConfirmBit(byte buffer[])
 | 
			
		||||
{
 | 
			
		||||
	struct ModbusResConfirmSingle mbc;
 | 
			
		||||
 | 
			
		||||
	memcpy_n2h(mbc, buffer);
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbDebug, "Set bit at 0x%04X to %d", mbc.Address, mbc.Value);
 | 
			
		||||
 | 
			
		||||
	OnModbusWriteBitSuccess(mbc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusWriteBit>
 | 
			
		||||
void OnModbusConfirmBitException(struct ModbusApHeader mbap, enum ModbusException ex)
 | 
			
		||||
{
 | 
			
		||||
	writeDbg(MbError, "Received an Exception while writing bit: %s", ModbusExceptions[ex-1]);
 | 
			
		||||
	OnModbusWriteBitFailed(Exception, ex, mbap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// REGION: ModbusWriteRegister ------------------------------------------------------
 | 
			
		||||
/// <ModbusWriteRegister>
 | 
			
		||||
void ModbusWriteRegister(word address, int value)
 | 
			
		||||
{
 | 
			
		||||
	const byte length = __size_of(struct ModbusReqWriteSingle);
 | 
			
		||||
	const byte funcCode = 0x06;
 | 
			
		||||
	byte buffer[length];
 | 
			
		||||
	struct ModbusReqWriteSingle mbw;
 | 
			
		||||
 | 
			
		||||
	ModbusMakeHeader(mbw.Header, length);
 | 
			
		||||
	// Payload
 | 
			
		||||
	mbw.Header.FuncCode = funcCode;	// [1] Function Code; 5: Write Single Register (AO)
 | 
			
		||||
	mbw.Address = address;			// [2] Output address
 | 
			
		||||
	mbw.Value = value;				// [2] Output value
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbDebug, "Sending 'Write Register' (0x06) command. Addr: 0x%04X, Value: 0x%02X", address, value);
 | 
			
		||||
 | 
			
		||||
	memcpy_h2n(buffer, mbw);
 | 
			
		||||
	ModbusSend(buffer, length, mbw.Header.TxID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusWriteRegister>
 | 
			
		||||
void OnModbusConfirmRegister(byte buffer[])
 | 
			
		||||
{
 | 
			
		||||
	struct ModbusResConfirmSingle mbc;
 | 
			
		||||
 | 
			
		||||
	memcpy_n2h(mbc, buffer);
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbDebug, "Set register at 0x%04X to %d", mbc.Address, mbc.Value);
 | 
			
		||||
 | 
			
		||||
	OnModbusWriteRegisterSuccess(mbc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusWriteRegister>
 | 
			
		||||
void OnModbusConfirmRegisterException(struct ModbusApHeader mbap, enum ModbusException ex)
 | 
			
		||||
{
 | 
			
		||||
	writeDbg(MbError, "Received an Exception while writing register: %s", ModbusExceptions[ex-1]);
 | 
			
		||||
	OnModbusWriteRegisterFailed(Exception, ex, mbap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// REGION: ModbusWriteBits ----------------------------------------------------------
 | 
			
		||||
/// <ModbusWriteBits>
 | 
			
		||||
void ModbusWriteBits(word address, word count, byte values[])
 | 
			
		||||
{
 | 
			
		||||
	const word maxLength = __size_of(struct ModbusReqWriteBits);
 | 
			
		||||
	const byte funcCode = 0x0F;
 | 
			
		||||
	byte buffer[maxLength];
 | 
			
		||||
	struct ModbusReqWriteBits mbw;
 | 
			
		||||
	byte dataLength;
 | 
			
		||||
	byte overallLength;
 | 
			
		||||
	word i;
 | 
			
		||||
 | 
			
		||||
	dataLength = _ceil(count / 8.0);
 | 
			
		||||
	overallLength = maxLength - 1968/8 + dataLength;
 | 
			
		||||
	ModbusMakeHeader(mbw.Header, overallLength);
 | 
			
		||||
	// Payload
 | 
			
		||||
	mbw.Header.FuncCode = funcCode;	// [1] Function Code; 15: Write Multiple Bits (DOs)
 | 
			
		||||
	mbw.Address = address;			// [2] Output address
 | 
			
		||||
	mbw.Count = count;				// [2] Number of items; 1:max 1968=0x7B0
 | 
			
		||||
	mbw.ByteCount = dataLength;		// [1] Number of bytes; = ceil(count/8)
 | 
			
		||||
	memcpy(mbw.Data, values, dataLength);	// this is 1 memcpy too much -.-
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. Addr: 0x%04X, Count: %d", address, count);
 | 
			
		||||
 | 
			
		||||
	memcpy_h2n(buffer, mbw);
 | 
			
		||||
	ModbusSend(buffer, overallLength, mbw.Header.TxID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusWriteBits>
 | 
			
		||||
void ModbusWriteBitsB(word address, word count, byte values[])
 | 
			
		||||
{
 | 
			
		||||
	byte buffer[2];	// length
 | 
			
		||||
	word length;
 | 
			
		||||
	dword ellCount;
 | 
			
		||||
	dword i;
 | 
			
		||||
	dword j;
 | 
			
		||||
	char str1[20*2], str2[20*3];
 | 
			
		||||
 | 
			
		||||
	length = (word)_ceil(count / 8.0);
 | 
			
		||||
	writeDbg(AlgoDebug, "ModbusWriteBitsB: count: %d; length: %d", count, length);
 | 
			
		||||
 | 
			
		||||
	if (count % 8 != 0)
 | 
			
		||||
		length--;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < length; i++)
 | 
			
		||||
	{
 | 
			
		||||
		buffer[i] = 0;
 | 
			
		||||
		for (j = 0; j < 8; j++)
 | 
			
		||||
		{
 | 
			
		||||
			buffer[i] |= (values[i*8 + j] & 0x01) << j;
 | 
			
		||||
			writeDbg(AlgoDebug, "ModbusWriteBitsB: j: %d; indx: %d; value: %d; mask: %X", j, i*8 + j, values[i*8 + j], (0x01 << j));
 | 
			
		||||
		}
 | 
			
		||||
		writeDbg(AlgoDebug, "ModbusWriteBitsB: %d: %X", i, buffer[i]);
 | 
			
		||||
	}
 | 
			
		||||
	for (j = 0; j < count % 8; j++)	// wont be executed if there is no remainder
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(AlgoDebug, "ModbusWriteBitsB: j: %d; indx: %d; value: %d; mask: %X", j, (length-1)*8 + j, values[(length-1)*8 + j], (0x01 << j));
 | 
			
		||||
		buffer[length] |= (values[(length)*8 + j] & 0x01) << j;
 | 
			
		||||
	}
 | 
			
		||||
	writeDbg(AlgoDebug, "ModbusWriteBitsB: %d: %X", length-1, buffer[length-1]);
 | 
			
		||||
 | 
			
		||||
	hbin_to_strhex(values, str1);
 | 
			
		||||
	bin_to_strhex(buffer, str2);
 | 
			
		||||
	writeDbg(AlgoDebug, "ModbusWriteBitsB: Encoded %s to %s", str1, str2);
 | 
			
		||||
	ModbusWriteBits(address, count, buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusWriteBits>
 | 
			
		||||
void OnModbusConfirmBits(byte buffer[])
 | 
			
		||||
{
 | 
			
		||||
	struct ModbusResConfirmMultiple mbc;
 | 
			
		||||
 | 
			
		||||
	memcpy_n2h(mbc, buffer);
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbDebug, "Updated &d bits at 0x%04X", mbc.Count, mbc.Address);
 | 
			
		||||
 | 
			
		||||
	OnModbusWriteBitsSuccess(mbc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusWriteBits>
 | 
			
		||||
void OnModbusConfirmBitsException(struct ModbusApHeader mbap, enum ModbusException ex)
 | 
			
		||||
{
 | 
			
		||||
	writeDbg(MbError, "Received an Exception while writing bits: %s", ModbusExceptions[ex-1]);
 | 
			
		||||
	OnModbusWriteBitsFailed(Exception, ex, mbap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// REGION: ModbusWriteRegisters -------------------------------------------------------
 | 
			
		||||
/// <ModbusWriteRegisters>
 | 
			
		||||
void ModbusWriteRegisters(word address, word count, word values[])
 | 
			
		||||
{
 | 
			
		||||
	const word maxLength = __size_of(struct ModbusReqWriteRegisters);
 | 
			
		||||
	const byte funcCode = 0x10;
 | 
			
		||||
	byte buffer[maxLength];
 | 
			
		||||
	struct ModbusReqWriteRegisters mbw;
 | 
			
		||||
	byte dataLength;
 | 
			
		||||
	word overallLength;
 | 
			
		||||
	word i;
 | 
			
		||||
 | 
			
		||||
	dataLength = 2 * count;
 | 
			
		||||
	overallLength = maxLength - 2*123 + dataLength;
 | 
			
		||||
 | 
			
		||||
	ModbusMakeHeader(mbw.Header, overallLength);
 | 
			
		||||
	// Payload
 | 
			
		||||
	mbw.Header.FuncCode = funcCode;	// [1] Function Code; 16: Write Multiple Registers (AOs)
 | 
			
		||||
	mbw.Address = address;			// [2] Output address
 | 
			
		||||
	mbw.Count = count;				// [2] Number of items; 1:max 123=0x7B
 | 
			
		||||
	mbw.ByteCount = dataLength;		// [1] Number of bytes; = 2 * count
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dataLength; i++)
 | 
			
		||||
		mbw.Data[i] = values[i];
 | 
			
		||||
 | 
			
		||||
	memcpy_h2n(buffer, mbw);
 | 
			
		||||
	ModbusSend(buffer, overallLength, mbw.Header.TxID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusWriteRegisters>
 | 
			
		||||
void OnModbusConfirmRegisters(byte buffer[])
 | 
			
		||||
{
 | 
			
		||||
	struct ModbusResConfirmMultiple mbc;
 | 
			
		||||
 | 
			
		||||
	memcpy_n2h(mbc, buffer);
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbDebug, "Updated &d registers at 0x%04X", mbc.Count, mbc.Address);
 | 
			
		||||
 | 
			
		||||
	OnModbusWriteRegistersSuccess(mbc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusWriteRegisters>
 | 
			
		||||
void OnModbusConfirmRegistersException(struct ModbusApHeader mbap, enum ModbusException ex)
 | 
			
		||||
{
 | 
			
		||||
	writeDbg(MbError, "Received an Exception while writing registers: %s", ModbusExceptions[ex-1]);
 | 
			
		||||
	OnModbusWriteRegistersFailed(Exception, ex, mbap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// REGION: ModbusWriteMasks ------------------------------------------------------------
 | 
			
		||||
/// <ModbusWriteMasks>
 | 
			
		||||
void ModbusWriteMasks(word address, word and, word or)
 | 
			
		||||
{
 | 
			
		||||
	const word length = __size_of(struct ModbusReqWriteMasks);
 | 
			
		||||
	const byte funcCode = 0x16;
 | 
			
		||||
	byte buffer[length];
 | 
			
		||||
	struct ModbusReqWriteMasks mbw;
 | 
			
		||||
 | 
			
		||||
	ModbusMakeHeader(mbw.Header, length);
 | 
			
		||||
	// Payload
 | 
			
		||||
	mbw.Header.FuncCode = funcCode;	// [1] Function Code; 22: Mask Write Registers (AO)
 | 
			
		||||
	mbw.Address = address;			// [2] Output address
 | 
			
		||||
	mbw.And = and;					// [2] AND mask
 | 
			
		||||
	mbw.Or = or;					// [2] OR mask
 | 
			
		||||
 | 
			
		||||
	memcpy_h2n(buffer, mbw);
 | 
			
		||||
	ModbusSend(buffer, length, mbw.Header.TxID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusWriteMasks>
 | 
			
		||||
void OnModbusConfirmMasks(byte buffer[])
 | 
			
		||||
{
 | 
			
		||||
	struct ModbusResConfirmMasks mbc;
 | 
			
		||||
 | 
			
		||||
	memcpy_n2h(mbc, buffer);
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbDebug, "Applied masks at 0x%04X", mbc.Address);
 | 
			
		||||
 | 
			
		||||
	OnModbusWriteMasksSuccess(mbc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusWriteMasks>
 | 
			
		||||
void OnModbusConfirmMasksException(struct ModbusApHeader mbap, enum ModbusException ex)
 | 
			
		||||
{
 | 
			
		||||
	writeDbg(MbError, "Received an Exception while applying masks: %s", ModbusExceptions[ex-1]);
 | 
			
		||||
	OnModbusWriteMasksFailed(Exception, ex, mbap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// REGION: ModbusReadWriteRegisters -------------------------------------------------------
 | 
			
		||||
/// <ModbusReadWriteRegisters>
 | 
			
		||||
void ModbusReadWriteRegisters(word readAddress, word readCount, word writeAddress, word writeCount, int values[])
 | 
			
		||||
{
 | 
			
		||||
	const word maxLength = __size_of(struct ModbusReqReadWriteRegisters);
 | 
			
		||||
	const byte funcCode = 0x17;
 | 
			
		||||
	byte buffer[maxLength];
 | 
			
		||||
	struct ModbusReqReadWriteRegisters mbw;
 | 
			
		||||
	byte dataLength;
 | 
			
		||||
	word overallLength;
 | 
			
		||||
	word i;
 | 
			
		||||
 | 
			
		||||
	dataLength = 2 * writeCount;
 | 
			
		||||
	overallLength = maxLength - 2*121 + dataLength;
 | 
			
		||||
 | 
			
		||||
	ModbusMakeHeader(mbw.Header, overallLength);
 | 
			
		||||
	// Payload
 | 
			
		||||
	mbw.Header.FuncCode = funcCode;	// [1] Function Code; 16: Write Multiple Registers (AOs)
 | 
			
		||||
	mbw.ReadAddress = readAddress;	// [2] Input address
 | 
			
		||||
	mbw.ReadCount = readCount;		// [2] Number of items; 1:max 125=0x7D
 | 
			
		||||
	mbw.WriteAddress = writeAddress;// [2] Output address
 | 
			
		||||
	mbw.WriteCount = writeCount;	// [2] Number of items; 1:max 121=0x79
 | 
			
		||||
	mbw.ByteCount = dataLength;		// [1] Number of bytes; = 2 * count
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dataLength; i++)
 | 
			
		||||
		mbw.Data[i] = values[i];
 | 
			
		||||
 | 
			
		||||
	memcpy_h2n(buffer, mbw);
 | 
			
		||||
	ModbusSend(buffer, overallLength, mbw.Header.TxID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusReadWriteRegisters>
 | 
			
		||||
void OnModbusReceiveConfirmRegisters(byte buffer[])
 | 
			
		||||
{
 | 
			
		||||
	struct ModbusResReceiveRegisters mbres;
 | 
			
		||||
	struct ModbusReqRead mbreq;
 | 
			
		||||
 | 
			
		||||
	memcpy_n2h(mbres, buffer);
 | 
			
		||||
	memcpy_n2h(mbreq, gQueueAck[mbres.Header.TxID].Buffer);
 | 
			
		||||
 | 
			
		||||
	writeDbg(MbDebug, "Wrote some registers and received %d registers from 0x%04X", mbreq.Count, mbreq.Address);
 | 
			
		||||
 | 
			
		||||
	OnModbusReadRegistersSuccess(mbres, mbreq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <ModbusReadWriteRegisters>
 | 
			
		||||
void OnModbusReceiveConfirmRegistersException(struct ModbusApHeader mbap, enum ModbusException ex)
 | 
			
		||||
{
 | 
			
		||||
	writeDbg(MbError, "Received an Exception while reading and writing registers: %s", ModbusExceptions[ex-1]);
 | 
			
		||||
	OnModbusWriteRegistersFailed(Exception, ex, mbap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------
 | 
			
		||||
// REGION: OnModbusReceive ------------------------------------------------------------
 | 
			
		||||
/// <-OnModbusReceive>
 | 
			
		||||
void OnModbusReceive(dword socket, long result, dword address, dword port, byte buffer[], dword size)
 | 
			
		||||
{
 | 
			
		||||
	writeDbg(ConnDebug, "OnModbusReceive: Received %d bytes", size);
 | 
			
		||||
	if (result == 0)
 | 
			
		||||
	{
 | 
			
		||||
		if (size == 0)
 | 
			
		||||
		{
 | 
			
		||||
			// Size of zero indicates that the socket was closed by the communication peer.
 | 
			
		||||
			writeDbg(ConnWarning, "OnModbusReceive: Socket closed by peer");
 | 
			
		||||
			ModbusDisconnect();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			// Sucessfully received some bytes over the TCP/IP connection.
 | 
			
		||||
			OnModbusReceive2(buffer, size);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		gIpLastErr = ModbusGetLastConnectionError(gIpLastErrStr);
 | 
			
		||||
		writeDbg(ConnError, "OnModbusReceive error (%d): %s", gIpLastErr, gIpLastErrStr);
 | 
			
		||||
		ModbusDisconnect();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <-OnModbusReceive>
 | 
			
		||||
void OnModbusReceive2(byte buffer[], dword size)
 | 
			
		||||
{
 | 
			
		||||
	struct ModbusApHeader mbap;
 | 
			
		||||
	int offset;
 | 
			
		||||
	char str[3*20];
 | 
			
		||||
 | 
			
		||||
	if (size < 8)						// No complete Modbus Application Header
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	offset = 0;
 | 
			
		||||
	do
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnDebug, "OnModbusReceive2: Offset pre = %d", offset);
 | 
			
		||||
		memcpy_n2h(mbap, buffer, offset);
 | 
			
		||||
		OnModbusReceive2OnePacket(buffer, offset, mbap);
 | 
			
		||||
		
 | 
			
		||||
		offset += __offset_of(struct ModbusApHeader, UnitID) + mbap.Length;
 | 
			
		||||
		writeDbg(ConnDebug, "OnModbusReceive2: offset post = %d. %d <= %d?", offset, offset, size-8);
 | 
			
		||||
	}
 | 
			
		||||
	while(offset <= size-8);			// We need at least 8 bytes for a new packet
 | 
			
		||||
	writeDbg(ConnDebug, "OnModbusReceive2: yes. finished");
 | 
			
		||||
 | 
			
		||||
	if (offset != size)	// Can be removed.
 | 
			
		||||
	{
 | 
			
		||||
		bin_to_strhex(buffer, str);
 | 
			
		||||
		writeDbg(ConnError, "OnModbusReceive2: Error while going through receive buffer. Our final offset is %d, but the size of the buffer is %d! Buffer: %s", offset, size, str);
 | 
			
		||||
		OnModbusClientPanics(ParsingBuffer);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <-OnModbusReceive>
 | 
			
		||||
void OnModbusReceive2OnePacket(byte buffer[], int offset, struct ModbusApHeader mbap)
 | 
			
		||||
{
 | 
			
		||||
	// Test transaction identifier?
 | 
			
		||||
	// Test unit/device identifier?
 | 
			
		||||
	word i;					// counter
 | 
			
		||||
	word length;			// length of current packet
 | 
			
		||||
	byte mbuffer[__size_of(struct ModbusResReceiveRegisters)];		// second buffer where we copy the message. This way the user won't overwrite other packages.
 | 
			
		||||
 | 
			
		||||
	length = __offset_of(struct ModbusApHeader, UnitID) + mbap.Length;
 | 
			
		||||
	// We cannot check this properly anymore. We have to trust the TCP/UDP stack and the sender... *sigh*
 | 
			
		||||
	if (mbap.Protocol != 0)						// Protocol is not Modbus (0x0000). Wayne.
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnDebug, "OnModbusReceive2OnePacket: packet is no Modbus packet: Protocol = %d", mbap.Protocol);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (elCount(buffer) < offset + length)		// packet larger than the (rest of the) buffer
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnError, "OnModbusReceive2OnePacket: packet did not fit into Buffer: buffer length = %d, packet length = %d, offset = %d", elCount(buffer), __offset_of(struct ModbusApHeader, UnitID) + mbap.Length, offset);
 | 
			
		||||
		// I REALLY don't want to assemble the two package fragments.
 | 
			
		||||
		OnModbusClientPanics(ModbusPackageWasSplit);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	// MBAP Header is OK :) Go on
 | 
			
		||||
	
 | 
			
		||||
	if (!gQueueSent.ContainsKey(mbap.TxID))		// We don't wait for this message!
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	//write("Received TxID: %d", mbap.TxID);
 | 
			
		||||
	memcpy(gQueueAck[mbap.TxID], gQueueSent[mbap.TxID]);
 | 
			
		||||
	gQueueSent.Remove(mbap.TxID);
 | 
			
		||||
 | 
			
		||||
	if (mbap.FuncCode > 0x80)					// Oh no, we got a exception!
 | 
			
		||||
	{
 | 
			
		||||
		OnModbusReceive2Exceptions(buffer[offset+08], mbap);
 | 
			
		||||
 | 
			
		||||
		gQueueAck.Remove(mbap.TxID);			// Remove from acknowledge queue
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// Copy the message
 | 
			
		||||
	memcpy_off(mbuffer, 0, buffer, offset, length);
 | 
			
		||||
 | 
			
		||||
	// Let's give the PDU to the corresponding function
 | 
			
		||||
	switch (mbap.FuncCode)
 | 
			
		||||
	{
 | 
			
		||||
		case 0x01:
 | 
			
		||||
		case 0x02:
 | 
			
		||||
			OnModbusReceiveBits(mbuffer);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x03:
 | 
			
		||||
		case 0x04:
 | 
			
		||||
			OnModbusReceiveRegisters(mbuffer);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x05:
 | 
			
		||||
			OnModbusConfirmBit(mbuffer);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x06:
 | 
			
		||||
			OnModbusConfirmRegister(mbuffer);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0F:
 | 
			
		||||
			OnModbusConfirmBits(mbuffer);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x10:
 | 
			
		||||
			OnModbusConfirmRegisters(mbuffer);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x16:
 | 
			
		||||
			OnModbusConfirmMasks(mbuffer);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x17:
 | 
			
		||||
			OnModbusReceiveConfirmRegisters(mbuffer);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			writeDbg(MbError, "OnModbusReceive2OnePacket: We received funcCode 0x%X!?", mbap.FuncCode);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gQueueAck.Remove(mbap.TxID);		// Remove from acknowledge queue
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <-OnModbusReceive>
 | 
			
		||||
void OnModbusReceive2Exceptions(byte exCode, struct ModbusApHeader mbap)
 | 
			
		||||
{
 | 
			
		||||
	enum ModbusException ex;
 | 
			
		||||
	ex = (enum ModbusException)exCode;
 | 
			
		||||
 | 
			
		||||
	switch (mbap.FuncCode)
 | 
			
		||||
	{
 | 
			
		||||
		case 0x81:
 | 
			
		||||
		case 0x82:
 | 
			
		||||
			OnModbusReceiveBitsException(mbap, ex);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x83:
 | 
			
		||||
		case 0x84:
 | 
			
		||||
			OnModbusReceiveRegistersException(mbap, ex);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x85:
 | 
			
		||||
			OnModbusConfirmBitException(mbap, ex);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x86:
 | 
			
		||||
			OnModbusConfirmRegisterException(mbap, ex);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x8F:
 | 
			
		||||
			OnModbusConfirmBitsException(mbap, ex);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x90:
 | 
			
		||||
			OnModbusConfirmRegistersException(mbap, ex);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x96:
 | 
			
		||||
			OnModbusConfirmMasksException(mbap, ex);
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x97:
 | 
			
		||||
			OnModbusReceiveConfirmRegistersException(mbap, ex);
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------
 | 
			
		||||
// REGION: ModbusSend -----------------------------------------------------------------
 | 
			
		||||
/// <-ModbusSend>
 | 
			
		||||
void ModbusSend(byte buffer[], word length, word TxID)
 | 
			
		||||
{
 | 
			
		||||
	struct QueueElement qe;
 | 
			
		||||
 | 
			
		||||
	qe.Length = length;
 | 
			
		||||
	memcpy(qe.Buffer, buffer, length);
 | 
			
		||||
 | 
			
		||||
	memcpy(gQueuePending[TxID], qe);
 | 
			
		||||
	writeDbg(ConnDebug, "Appended packet 0x%04X to pending queue", TxID);
 | 
			
		||||
 | 
			
		||||
	if (gQueuePending.Size() == 1 && gQueueSent.Size() == 0 && gSocketState == OK)	// start timer if connection established
 | 
			
		||||
		ModbusStartQueue();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusStartQueue()
 | 
			
		||||
{
 | 
			
		||||
	writeDbg(ConnDebug, "Starting Timer gtRobin");
 | 
			
		||||
	setTimerCyclic(gtRobin, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <-ModbusSend>
 | 
			
		||||
on timer gtRobin
 | 
			
		||||
{
 | 
			
		||||
	struct ModbusApHeader mbap;
 | 
			
		||||
	enum ModbusRequestError reqError;
 | 
			
		||||
 | 
			
		||||
	writeDbg(ConnDebug, "gtRobin: Queue Sent: %d, Queue Pending: %d, Queue Ack: %d", gQueueSent.Size(), gQueuePending.Size(), gQueueAck.Size());
 | 
			
		||||
 | 
			
		||||
	// First: check timeouts = packets that were sent in previous run and not removed by response
 | 
			
		||||
	for (long TxID : gQueueSent)
 | 
			
		||||
	{
 | 
			
		||||
		if (++gQueueSent[TxID].TimeoutTicks < @sysvar::Config::Modbus::RequestTimeout)		// not timed out yet
 | 
			
		||||
			continue;
 | 
			
		||||
																							// timed out!
 | 
			
		||||
		if (++gQueueSent[TxID].Timeouts < @sysvar::Config::Modbus::MaxTransmissionCount)	// if we may resend it
 | 
			
		||||
		{
 | 
			
		||||
			writeDbg(ConnInfo, "Packet 0x%04X timed out! Retrying...", TxID);
 | 
			
		||||
			gQueueSent[TxID].TimeoutTicks = 0;
 | 
			
		||||
			ModbusSnd(gQueueSent[TxID].Buffer, gQueueSent[TxID].Length);					// resend it
 | 
			
		||||
			reqError = Timeout;
 | 
			
		||||
			ModbusRecv();
 | 
			
		||||
		}
 | 
			
		||||
		else																				// we will NOT resend it
 | 
			
		||||
		{
 | 
			
		||||
			writeDbg(ConnWarning, "Packet 0x%04X timed out! Giving up", TxID);
 | 
			
		||||
			reqError = FinalTimeout;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		memcpy_n2h(mbap, gQueueSent[TxID].Buffer);
 | 
			
		||||
		switch(mbap.FuncCode)											// throw an "error" in each case
 | 
			
		||||
		{
 | 
			
		||||
			case ReadBits1:
 | 
			
		||||
			case ReadBits2:
 | 
			
		||||
				OnModbusReadBitsFailed(reqError, None, mbap);
 | 
			
		||||
				break;
 | 
			
		||||
			case ReadRegisters1:
 | 
			
		||||
			case ReadRegisters2:
 | 
			
		||||
				OnModbusReadRegistersFailed(reqError, None, mbap);
 | 
			
		||||
				break;
 | 
			
		||||
			case WriteBit:
 | 
			
		||||
				OnModbusWriteBitFailed(reqError, None, mbap);
 | 
			
		||||
				break;
 | 
			
		||||
			case WriteRegister:
 | 
			
		||||
				OnModbusWriteRegisterFailed(reqError, None, mbap);
 | 
			
		||||
				break;
 | 
			
		||||
			case WriteBits:
 | 
			
		||||
				OnModbusWriteBitsFailed(reqError, None, mbap);
 | 
			
		||||
				break;
 | 
			
		||||
			case WriteRegisters:
 | 
			
		||||
				OnModbusWriteRegistersFailed(reqError, None, mbap);
 | 
			
		||||
				break;
 | 
			
		||||
			case MaskRegister:
 | 
			
		||||
				OnModbusWriteMasksFailed(reqError, None, mbap);
 | 
			
		||||
				break;
 | 
			
		||||
			case ReadWriteRegisters:
 | 
			
		||||
				OnModbusReadWriteRegistersFailed(reqError, None, mbap);
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (reqError == FinalTimeout)									// remove the packet from queue
 | 
			
		||||
			gQueueSent.Remove(TxID);									// wait until here to let the methods access the request
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Second: send new packets
 | 
			
		||||
	for (long TxID : gQueuePending)
 | 
			
		||||
	{
 | 
			
		||||
		if (gQueueSent.Size() > 4)		// Wago 750-881 cannot handle more than 5 messages at a time :(
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		// if packet was sent or the socket is not currently being opened
 | 
			
		||||
		if (ModbusSnd(gQueuePending[TxID].Buffer, gQueuePending[TxID].Length) == 0 || gSocketState != NULL)
 | 
			
		||||
		{
 | 
			
		||||
			memcpy(gQueueSent[TxID], gQueuePending[TxID]);				// move packet to sent queue
 | 
			
		||||
			gQueuePending.Remove(TxID);
 | 
			
		||||
			ModbusRecv();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (gSocketState == ERROR || gQueueSent.Size() == 0 && gQueuePending.Size() == 0)	// Stop timer to reduce latency of first packet
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnDebug, "Stopping Timer gtRobin");
 | 
			
		||||
		this.Cancel();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<breakpoints>
 | 
			
		||||
  <breakpoint Active="true" HaltsSimulation="true" AbsoluteLine="352" Function="" RelativeLine="9" />
 | 
			
		||||
</breakpoints>
 | 
			
		||||
							
								
								
									
										64
									
								
								Modbus-DLL/include/CAPL/include/ModbusEilClientCommon.cin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								Modbus-DLL/include/CAPL/include/ModbusEilClientCommon.cin
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,64 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
 | 
			
		||||
includes
 | 
			
		||||
{
 | 
			
		||||
	#include "EilCommon.cin"
 | 
			
		||||
	#include "ModbusClientCommon.cin"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusConnectTo(char Remote_IP[], word Remote_Port)
 | 
			
		||||
{
 | 
			
		||||
	EilConnectTo(Remote_IP, Remote_Port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusConnectTo(dword Remote_IP, word Remote_Port)
 | 
			
		||||
{
 | 
			
		||||
	EilConnectTo(Remote_IP, Remote_Port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
byte ModbusSnd(byte buffer[], word length)
 | 
			
		||||
{
 | 
			
		||||
	return EilSnd(buffer, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusRecv()
 | 
			
		||||
{
 | 
			
		||||
	EilRecv();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusDisconnect()
 | 
			
		||||
{
 | 
			
		||||
	EilDisconnect();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
long ModbusGetLastConnectionError(char string[])
 | 
			
		||||
{
 | 
			
		||||
	return EilGetLastConnectionError(string);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OnEthReceivePacket(long channel, long dir, long packet)
 | 
			
		||||
{
 | 
			
		||||
	byte buffer[gMaxPacketLength];
 | 
			
		||||
	long size;
 | 
			
		||||
 | 
			
		||||
	if (dir == TX)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (EthGetTokenInt(packet, "arp", "protSourceAddr") == gRemoteIP)		// this was our ARP package
 | 
			
		||||
	{
 | 
			
		||||
		if (EthGetTokenData(packet, "arp", "hwSourceAddr", elCount(gRemoteMac), gRemoteMac) == 6)
 | 
			
		||||
		{
 | 
			
		||||
			gtArp.Cancel();
 | 
			
		||||
			writeDbg(ConnDebug, "Remote Mac: %02X:%02X:%02X:%02X:%02X:%02X", gRemoteMac[0], gRemoteMac[1], gRemoteMac[2], gRemoteMac[3], gRemoteMac[4], gRemoteMac[5]);
 | 
			
		||||
			EilConnectTo2();		// create the UDP package
 | 
			
		||||
			ModbusStartQueue();
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (EthGetTokenInt(packet, "ipv4", "protocol") == 0x11 && EthGetTokenInt(packet, "ipv4", "source") == gRemoteIP)	// if this is a UDP package from our server
 | 
			
		||||
	{
 | 
			
		||||
	size = EthGetThisData(0, gMaxPacketLength, buffer);
 | 
			
		||||
	OnModbusReceive(0, 0, EthGetTokenInt(packet, "ipv4", "source"), gRemoteIP, buffer, size);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										86
									
								
								Modbus-DLL/include/CAPL/include/ModbusFunctions.cin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								Modbus-DLL/include/CAPL/include/ModbusFunctions.cin
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,86 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
variables
 | 
			
		||||
{
 | 
			
		||||
	enum Vendor
 | 
			
		||||
	{
 | 
			
		||||
		BuR = 2,
 | 
			
		||||
		Wago = 23
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct deviceIOs
 | 
			
		||||
	{
 | 
			
		||||
		byte InputRegisters;
 | 
			
		||||
		word InputBits;
 | 
			
		||||
		byte OutputRegisters;
 | 
			
		||||
		word OutputBits;
 | 
			
		||||
		char Modules[1024];
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ParseDeviceCode(word dev, enum Vendor vendor, struct deviceIOs dios)
 | 
			
		||||
{
 | 
			
		||||
	byte input;
 | 
			
		||||
	byte numChannels;
 | 
			
		||||
	char module[10];
 | 
			
		||||
 | 
			
		||||
	switch(vendor)
 | 
			
		||||
	{
 | 
			
		||||
		case Wago:		// if this is a Wago device
 | 
			
		||||
 | 
			
		||||
			if (dev & 0x8000)					// Digital Module
 | 
			
		||||
			{
 | 
			
		||||
				numChannels = (dev >> 8) & 0x007F;
 | 
			
		||||
 | 
			
		||||
				if (dev & 0x0001)				// Input Module
 | 
			
		||||
				{
 | 
			
		||||
					input = 1;
 | 
			
		||||
					strncpy(module, "DI%d,", elCount(module));
 | 
			
		||||
					dios.InputBits += numChannels;
 | 
			
		||||
				}
 | 
			
		||||
				else if (dev & 0x0002)			// Output Module
 | 
			
		||||
				{
 | 
			
		||||
					input = 0;
 | 
			
		||||
					strncpy(module, "DO%d,", elCount(module));
 | 
			
		||||
					dios.OutputBits += numChannels;
 | 
			
		||||
				}
 | 
			
		||||
				else							// blööd
 | 
			
		||||
				{
 | 
			
		||||
					writeDbg(AlgoError, "ParseDeviceCode: Device code 0x%X cannot be decoded", dev);
 | 
			
		||||
					OnModbusClientPanics(DeviceCodeUnknown);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				switch (dev)
 | 
			
		||||
				{
 | 
			
		||||
					case 881:					// devices that have no inputs/outputs
 | 
			
		||||
						return;
 | 
			
		||||
					case 477:					// devices that have 2 outputs
 | 
			
		||||
						input = 0;
 | 
			
		||||
						numChannels = 2;
 | 
			
		||||
						break;
 | 
			
		||||
					default:					// unknown device. Ouch!
 | 
			
		||||
						writeDbg(AlgoInfo, "Connected device: 750-%d", dev);
 | 
			
		||||
						return;
 | 
			
		||||
				}
 | 
			
		||||
				if (input)
 | 
			
		||||
				{
 | 
			
		||||
					strncpy(module, "AI%d,", elCount(module));
 | 
			
		||||
					dios.InputRegisters += numChannels;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					strncpy(module, "AO%d,", elCount(module));
 | 
			
		||||
					dios.OutputRegisters += numChannels;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			break;	// switch(vendor)
 | 
			
		||||
		default:
 | 
			
		||||
			writeDbg(AlgoError, "ParseDeviceCode: Unknown vendor id: %d", vendor);
 | 
			
		||||
			OnModbusClientPanics(VendorIdUnknown);
 | 
			
		||||
			return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	snprintf(module, elCount(module), module, numChannels);
 | 
			
		||||
	strncat(dios.Modules, module, elCount(dios.Modules));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										146
									
								
								Modbus-DLL/include/CAPL/include/ModbusStructs.cin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								Modbus-DLL/include/CAPL/include/ModbusStructs.cin
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,146 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
variables
 | 
			
		||||
{
 | 
			
		||||
	// A normal Modbus Application Header. Every Modbus Packet begins with these 7 (+FuncCode) Bytes
 | 
			
		||||
	_align(1) struct ModbusApHeader
 | 
			
		||||
	{
 | 
			
		||||
		word TxID;
 | 
			
		||||
		word Protocol;
 | 
			
		||||
		word Length;
 | 
			
		||||
		byte UnitID;
 | 
			
		||||
		byte FuncCode;
 | 
			
		||||
	};
 | 
			
		||||
	// Read Data from the host. We only need the start address and the number of bits/registers we want to read
 | 
			
		||||
	_align(1) struct ModbusReqRead
 | 
			
		||||
	{
 | 
			
		||||
		struct ModbusApHeader Header;
 | 
			
		||||
		word Address;
 | 
			
		||||
		word Count;
 | 
			
		||||
	};
 | 
			
		||||
	// Write a single value to a bit/register
 | 
			
		||||
	_align(1) struct ModbusReqWriteSingle
 | 
			
		||||
	{
 | 
			
		||||
		struct ModbusApHeader Header;
 | 
			
		||||
		word Address;
 | 
			
		||||
		word Value;
 | 
			
		||||
	};
 | 
			
		||||
	// Write several values to a bit/register starting with Address
 | 
			
		||||
	_align(1) struct ModbusReqWriteBits
 | 
			
		||||
	{
 | 
			
		||||
		struct ModbusApHeader Header;
 | 
			
		||||
		word Address;
 | 
			
		||||
		word Count;
 | 
			
		||||
		byte ByteCount;
 | 
			
		||||
		byte Data[246];		// Max length: 1968 bits
 | 
			
		||||
	};
 | 
			
		||||
	// Write several values to bits starting with Address
 | 
			
		||||
	_align(1) struct ModbusReqWriteRegisters
 | 
			
		||||
	{
 | 
			
		||||
		struct ModbusApHeader Header;
 | 
			
		||||
		word Address;
 | 
			
		||||
		word Count;
 | 
			
		||||
		byte ByteCount;
 | 
			
		||||
		word Data[123];		// Max length: 123 registers
 | 
			
		||||
	};
 | 
			
		||||
	// Write AND and OR masks to a holding register
 | 
			
		||||
	_align(1) struct ModbusReqWriteMasks
 | 
			
		||||
	{
 | 
			
		||||
		struct ModbusApHeader Header;
 | 
			
		||||
		word Address;
 | 
			
		||||
		word And;
 | 
			
		||||
		word Or;
 | 
			
		||||
	};
 | 
			
		||||
	// Read and write multiple registers
 | 
			
		||||
	_align(1) struct ModbusReqReadWriteRegisters
 | 
			
		||||
	{
 | 
			
		||||
		struct ModbusApHeader Header;
 | 
			
		||||
		word ReadAddress;
 | 
			
		||||
		word ReadCount;
 | 
			
		||||
		word WriteAddress;
 | 
			
		||||
		word WriteCount;
 | 
			
		||||
		byte ByteCount;
 | 
			
		||||
		word Data[121];		// Max length: 123-2 registers
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// Receive several bit values
 | 
			
		||||
	_align(1) struct ModbusResReceiveBits
 | 
			
		||||
	{
 | 
			
		||||
		struct ModbusApHeader Header;
 | 
			
		||||
		byte ByteCount;
 | 
			
		||||
		byte Data[250];		// Max length: 2000 bits
 | 
			
		||||
	};
 | 
			
		||||
	// Receive several register values
 | 
			
		||||
	_align(1) struct ModbusResReceiveRegisters
 | 
			
		||||
	{
 | 
			
		||||
		struct ModbusApHeader Header;
 | 
			
		||||
		byte ByteCount;
 | 
			
		||||
		word Data[125];		// Max length: 125 registers
 | 
			
		||||
	};
 | 
			
		||||
	// Confirm the write of a single bit/register
 | 
			
		||||
	_align(1) struct ModbusResConfirmSingle
 | 
			
		||||
	{
 | 
			
		||||
		struct ModbusApHeader Header;
 | 
			
		||||
		word Address;
 | 
			
		||||
		int Value;
 | 
			
		||||
	};
 | 
			
		||||
	// Confirm the write of several bits/registers
 | 
			
		||||
	_align(1) struct ModbusResConfirmMultiple
 | 
			
		||||
	{
 | 
			
		||||
		struct ModbusApHeader Header;
 | 
			
		||||
		word Address;
 | 
			
		||||
		word Count;
 | 
			
		||||
	};
 | 
			
		||||
	// Confirm the write of AND and OR mask
 | 
			
		||||
	_align(1) struct ModbusResConfirmMasks
 | 
			
		||||
	{
 | 
			
		||||
		struct ModbusApHeader Header;
 | 
			
		||||
		word Address;
 | 
			
		||||
		word And;
 | 
			
		||||
		word Or;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	enum ModbusRequestError
 | 
			
		||||
	{
 | 
			
		||||
		Exception,
 | 
			
		||||
		Timeout,
 | 
			
		||||
		FinalTimeout
 | 
			
		||||
    };
 | 
			
		||||
	enum ModbusException
 | 
			
		||||
	{
 | 
			
		||||
		None = 0x00,
 | 
			
		||||
		IllegalFuncCode = 0x01,
 | 
			
		||||
		IllegalDataAddress = 0x02,
 | 
			
		||||
		IllegalDataValue = 0x03,
 | 
			
		||||
		ServerFailure = 0x04,
 | 
			
		||||
		Acknowledge = 0x05,
 | 
			
		||||
		ServerBusy = 0x06,
 | 
			
		||||
		GatewayPathsNA = 0x0A,
 | 
			
		||||
		TargetOffline = 0x0B
 | 
			
		||||
	};
 | 
			
		||||
	enum ModbusFuncCode
 | 
			
		||||
	{
 | 
			
		||||
		ReadBits1 = 0x01,
 | 
			
		||||
		ReadBits2 = 0x02,
 | 
			
		||||
		ReadRegisters1 = 0x03,
 | 
			
		||||
		ReadRegisters2 = 0x04,
 | 
			
		||||
		WriteBit = 0x05,
 | 
			
		||||
		WriteRegister = 0x06,
 | 
			
		||||
		WriteBits = 0x0F,
 | 
			
		||||
		WriteRegisters = 0x10,
 | 
			
		||||
		MaskRegister = 0x16,
 | 
			
		||||
		ReadWriteRegisters = 0x17
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	enum FatalErrors
 | 
			
		||||
	{
 | 
			
		||||
		ParsingBuffer = 0x00,
 | 
			
		||||
		ModbusPackageWasSplit = 0x01,
 | 
			
		||||
		DeviceCodeUnknown = 0x02,
 | 
			
		||||
		VendorIdUnknown = 0x03,
 | 
			
		||||
		ConnectionError = 0x04
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								Modbus-DLL/include/CAPL/include/ModbusTcpClientCommon.cin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								Modbus-DLL/include/CAPL/include/ModbusTcpClientCommon.cin
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
 | 
			
		||||
includes
 | 
			
		||||
{
 | 
			
		||||
	#include "TcpCommon.cin"
 | 
			
		||||
	#include "ModbusClientCommon.cin"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusConnectTo(char Remote_IP[], word Remote_Port)
 | 
			
		||||
{
 | 
			
		||||
	TcpConnectTo(Remote_IP, Remote_Port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusConnectTo(dword Remote_IP, word Remote_Port)
 | 
			
		||||
{
 | 
			
		||||
	TcpConnectTo(Remote_IP, Remote_Port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusDisconnect()
 | 
			
		||||
{
 | 
			
		||||
	TcpDisconnect();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
byte ModbusSnd(byte buffer[], word length)
 | 
			
		||||
{
 | 
			
		||||
	return TcpSnd(buffer, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusRecv()
 | 
			
		||||
{
 | 
			
		||||
	TcpRecv();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
long ModbusGetLastConnectionError(char string[])
 | 
			
		||||
{
 | 
			
		||||
	return TcpGetLastConnectionError(string);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OnTcpReceive(dword socket, long result, dword address, dword port, byte buffer[], dword size)
 | 
			
		||||
{
 | 
			
		||||
	OnModbusReceive(socket, result, address, port, buffer, size);
 | 
			
		||||
	if (result == 0 && size != 0)
 | 
			
		||||
		TcpRecv();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								Modbus-DLL/include/CAPL/include/ModbusUdpClientCommon.cin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								Modbus-DLL/include/CAPL/include/ModbusUdpClientCommon.cin
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
 | 
			
		||||
includes
 | 
			
		||||
{
 | 
			
		||||
	#include "UdpCommon.cin"
 | 
			
		||||
	#include "ModbusClientCommon.cin"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusConnectTo(char Remote_IP[], word Remote_Port)
 | 
			
		||||
{
 | 
			
		||||
	UdpConnectTo(Remote_IP, Remote_Port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusConnectTo(dword Remote_IP, word Remote_Port)
 | 
			
		||||
{
 | 
			
		||||
	UdpConnectTo(Remote_IP, Remote_Port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusDisconnect()
 | 
			
		||||
{
 | 
			
		||||
	UdpDisconnect();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
byte ModbusSnd(byte buffer[], word length)
 | 
			
		||||
{
 | 
			
		||||
	return UdpSnd(buffer, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModbusRecv()
 | 
			
		||||
{
 | 
			
		||||
	UdpRecv();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
long ModbusGetLastConnectionError(char string[])
 | 
			
		||||
{
 | 
			
		||||
	return UdpGetLastConnectionError(string);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OnUdpReceiveFrom(dword socket, long result, dword address, dword port, byte buffer[], dword size)
 | 
			
		||||
{
 | 
			
		||||
	OnModbusReceive(socket, result, address, port, buffer, size);
 | 
			
		||||
	if (result == 0 && size != 0)
 | 
			
		||||
		UdpRecv();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										204
									
								
								Modbus-DLL/include/CAPL/include/TcpCommon.cin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								Modbus-DLL/include/CAPL/include/TcpCommon.cin
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,204 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
includes
 | 
			
		||||
{
 | 
			
		||||
	#include "Common.cin"
 | 
			
		||||
	#include "TcpUdpCommon.cin"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
variables
 | 
			
		||||
{
 | 
			
		||||
	TcpSocket gSocket;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
word TcpOpenSocket()
 | 
			
		||||
{
 | 
			
		||||
	byte i;
 | 
			
		||||
	CHAR errorText[200];
 | 
			
		||||
	long error;
 | 
			
		||||
 | 
			
		||||
	if (EthGetAdapterStatus() != 2)			// Not connected
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnError, "TcpOpenSocket: Adapter status not ok: %d!", EthGetAdapterStatus());
 | 
			
		||||
		OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return INVALID_IP;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Try to open socket
 | 
			
		||||
	i = 0;
 | 
			
		||||
	do
 | 
			
		||||
	{
 | 
			
		||||
		gSocket = TcpSocket::Open(0, 0);
 | 
			
		||||
		error = gSocket.GetLastSocketError();
 | 
			
		||||
		if (error != 0)
 | 
			
		||||
		{
 | 
			
		||||
			gSocket.GetLastSocketErrorAsString(errorText, elcount(errorText));
 | 
			
		||||
			writeDbg(ConnInfo, "TcpOpenSocket: could not open socket: (%d) %s", error, errorText);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	while (error != 0 && i++ < 9);
 | 
			
		||||
	
 | 
			
		||||
	if (error != 0)
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnError, "TcpOpenSocket: could not open socket: (%d) %s", error, errorText);
 | 
			
		||||
		OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return error;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnInfo, "Tcp socket opened.");
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
word TcpConnectTo(char Remote_IP[], word remotePort)
 | 
			
		||||
{
 | 
			
		||||
	dword remoteIp;
 | 
			
		||||
 | 
			
		||||
	// Convert IP string to Number
 | 
			
		||||
	remoteIp = IpGetAddressAsNumber(Remote_IP);
 | 
			
		||||
	if (remoteIp == INVALID_IP)
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnError, "TcpConnectTo: invalid server Ip address: %s", Remote_IP);
 | 
			
		||||
		OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return TcpConnectTo(remoteIp, remotePort);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
word TcpConnectTo(dword remoteIp, word remotePort)
 | 
			
		||||
{
 | 
			
		||||
	long fehler;
 | 
			
		||||
 | 
			
		||||
	// Try to open a socket
 | 
			
		||||
	fehler = TcpOpenSocket();
 | 
			
		||||
	if (fehler != 0)
 | 
			
		||||
	{
 | 
			
		||||
		gSocketState = ERROR;
 | 
			
		||||
		return fehler;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gRemoteIP = remoteIp;
 | 
			
		||||
	gRemotePort = remotePort;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// Connect to Server
 | 
			
		||||
	if (gSocket.Connect(remoteIp, remotePort) != 0)
 | 
			
		||||
	{
 | 
			
		||||
		fehler = gSocket.GetLastSocketError();
 | 
			
		||||
 | 
			
		||||
		if (fehler != WSAEWOULDBLOCK)		// OnTcpConnect will be called otherwise
 | 
			
		||||
		{
 | 
			
		||||
			writeDbg(ConnError, "TcpConnectTo: No connection established: %d", fehler);
 | 
			
		||||
			gSocketState = ERROR;
 | 
			
		||||
			OnModbusClientPanics(ConnectionError);
 | 
			
		||||
			return fehler;
 | 
			
		||||
		}
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnInfo, "TcpConnectTo: Successfully connected to server");
 | 
			
		||||
		gSocketState = OK;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OnTcpConnect(dword socket, long result)
 | 
			
		||||
{
 | 
			
		||||
	if (result != 0)
 | 
			
		||||
	{
 | 
			
		||||
		gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr));
 | 
			
		||||
		writeDbg(ConnError, "OnTcpConnect: (%d) %s", gSocket.GetLastSocketError(), gIpLastErrStr);
 | 
			
		||||
		gSocketState = ERROR;
 | 
			
		||||
			OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnInfo, "OnTcpConnect: Successfully connected to server");
 | 
			
		||||
		gSocketState = OK;
 | 
			
		||||
		ModbusStartQueue();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TcpDisconnect()
 | 
			
		||||
{
 | 
			
		||||
	gSocket.Close();
 | 
			
		||||
	gSocketState = CLOSED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TcpRecv()
 | 
			
		||||
{
 | 
			
		||||
	int result;
 | 
			
		||||
 | 
			
		||||
	if (gSocketState != OK)
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnWarning, "TcpRecv: Socket status is not OK! Doing nothing.");
 | 
			
		||||
		OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	result = gSocket.Receive(gRxBuffer, elcount(gRxBuffer));
 | 
			
		||||
 | 
			
		||||
	if (result != 0)	// Calling OnTcpReceive otherwise
 | 
			
		||||
	{
 | 
			
		||||
		gIpLastErr = gSocket.GetLastSocketError();
 | 
			
		||||
 | 
			
		||||
		if (gIpLastErr != WSA_IO_PENDING)	// Calling OnTcpReceive otherwise
 | 
			
		||||
		{
 | 
			
		||||
			gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr));
 | 
			
		||||
			writeDbg(ConnError, "TcpReceive: (%d) %s", gIpLastErr, gIpLastErrStr);
 | 
			
		||||
			TcpDisconnect();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
word TcpSnd(byte buffer[], word length)
 | 
			
		||||
{
 | 
			
		||||
	char str[20*3];
 | 
			
		||||
 | 
			
		||||
	switch (gSocketState)
 | 
			
		||||
	{
 | 
			
		||||
		case CLOSED:
 | 
			
		||||
			TcpConnectTo(gRemoteIP, gRemotePort);
 | 
			
		||||
			if (gSocketState != OK)
 | 
			
		||||
			{
 | 
			
		||||
				writeDbg(ConnError, "TcpSnd: Reconnecting failed!");
 | 
			
		||||
				OnModbusClientPanics(ConnectionError);
 | 
			
		||||
				return 1;
 | 
			
		||||
			}
 | 
			
		||||
		case OK:
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			writeDbg(ConnError, "TcpSnd: Socket status is not OK! Doing nothing.");
 | 
			
		||||
			OnModbusClientPanics(ConnectionError);
 | 
			
		||||
			return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bin_to_strhex(buffer, str);
 | 
			
		||||
	writeDbg(ConnDebug, "TcpSnd: %s (Länge: %d)", str, length);
 | 
			
		||||
	
 | 
			
		||||
	if (gSocket.Send(buffer, length) != 0)
 | 
			
		||||
	{
 | 
			
		||||
		gIpLastErr = gSocket.GetLastSocketError();
 | 
			
		||||
 | 
			
		||||
		if (gIpLastErr != WSA_IO_PENDING)
 | 
			
		||||
		{
 | 
			
		||||
			gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr));
 | 
			
		||||
			writeDbg(ConnError, "TcpSnd: (%d) %s", gIpLastErr, gIpLastErrStr);
 | 
			
		||||
			TcpDisconnect();
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
long TcpGetLastConnectionError(char string[])
 | 
			
		||||
{
 | 
			
		||||
	gSocket.GetLastSocketErrorAsString(string, elCount(string));
 | 
			
		||||
	return gSocket.GetLastSocketError();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								Modbus-DLL/include/CAPL/include/TcpUdpCommon.cin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								Modbus-DLL/include/CAPL/include/TcpUdpCommon.cin
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
 | 
			
		||||
variables
 | 
			
		||||
{
 | 
			
		||||
	const long	WSA_IO_PENDING		= 997;
 | 
			
		||||
	const long	WSAEWOULDBLOCK		= 10035;
 | 
			
		||||
	const dword INVALID_IP			= 0xffffffff;
 | 
			
		||||
	
 | 
			
		||||
	long gIpLastErr					= 0;
 | 
			
		||||
	char gIpLastErrStr[512]			= "";
 | 
			
		||||
 | 
			
		||||
	enum SocketState { NULL, OK, ERROR, CLOSED };
 | 
			
		||||
	enum SocketState gSocketState = NULL;
 | 
			
		||||
 | 
			
		||||
	dword gRemoteIP		= INVALID_IP;
 | 
			
		||||
	word gRemotePort	= 0;
 | 
			
		||||
 | 
			
		||||
	byte gRxBuffer[8192];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										166
									
								
								Modbus-DLL/include/CAPL/include/UdpCommon.cin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								Modbus-DLL/include/CAPL/include/UdpCommon.cin
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,166 @@
 | 
			
		|||
/*@!Encoding:1252*/
 | 
			
		||||
includes
 | 
			
		||||
{
 | 
			
		||||
	#include "Common.cin"
 | 
			
		||||
	#include "TcpUdpCommon.cin"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
variables
 | 
			
		||||
{
 | 
			
		||||
	UdpSocket gSocket;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
word UdpOpenSocket()
 | 
			
		||||
{
 | 
			
		||||
	byte i;
 | 
			
		||||
	char errorText[200];
 | 
			
		||||
	long error;
 | 
			
		||||
 | 
			
		||||
	if (EthGetAdapterStatus() != 2)			// Not connected
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnError, "UdpOpenSocket: Adapter status not ok: %d!", EthGetAdapterStatus());
 | 
			
		||||
		OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return INVALID_IP;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Try to open socket
 | 
			
		||||
	i = 0;
 | 
			
		||||
	do
 | 
			
		||||
	{
 | 
			
		||||
		gSocket = UdpSocket::Open(0, 0);
 | 
			
		||||
		error = gSocket.GetLastSocketError();
 | 
			
		||||
		if (error != 0)
 | 
			
		||||
		{
 | 
			
		||||
			gSocket.GetLastSocketErrorAsString(errorText, elcount(errorText));
 | 
			
		||||
			writeDbg(ConnInfo, "UdpOpenSocket: could not open socket: (%d) %s", error, errorText);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	while (error != 0 && i++ < 9);
 | 
			
		||||
	
 | 
			
		||||
	if (error != 0)
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnError, "UdpOpenSocket: could not open socket: (%d) %s", error, errorText);
 | 
			
		||||
		OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return error;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnInfo, "Udp socket opened.");
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
word UdpConnectTo(char Remote_IP[], word remotePort)
 | 
			
		||||
{
 | 
			
		||||
	dword remoteIp;
 | 
			
		||||
 | 
			
		||||
	// Convert IP string to Number
 | 
			
		||||
	remoteIp = IpGetAddressAsNumber(Remote_IP);
 | 
			
		||||
	if (remoteIp == INVALID_IP)
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnError, "UdpConnectTo: invalid server Ip address: %s", Remote_IP);
 | 
			
		||||
		OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return UdpConnectTo(remoteIp, remotePort);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
word UdpConnectTo(dword remoteIp, word remotePort)
 | 
			
		||||
{
 | 
			
		||||
	long fehler;
 | 
			
		||||
 | 
			
		||||
	// Try to open a socket
 | 
			
		||||
	fehler = UdpOpenSocket();
 | 
			
		||||
	if (fehler != 0)
 | 
			
		||||
	{
 | 
			
		||||
		gSocketState = ERROR;
 | 
			
		||||
		return fehler;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gRemoteIP = remoteIp;
 | 
			
		||||
	gRemotePort = remotePort;
 | 
			
		||||
	gSocketState = OK;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UdpDisconnect()
 | 
			
		||||
{
 | 
			
		||||
	gSocket.Close();
 | 
			
		||||
	gSocketState = CLOSED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UdpRecv()
 | 
			
		||||
{
 | 
			
		||||
	int result;
 | 
			
		||||
 | 
			
		||||
	if (gSocketState != OK)
 | 
			
		||||
	{
 | 
			
		||||
		writeDbg(ConnError, "UdpRecv: Socket status is not OK! Doing nothing.");
 | 
			
		||||
		OnModbusClientPanics(ConnectionError);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	result = gSocket.ReceiveFrom(gRxBuffer, elCount(gRxBuffer));
 | 
			
		||||
 | 
			
		||||
	if (result != 0)	// Calling OnUdpReceive otherwise
 | 
			
		||||
	{
 | 
			
		||||
		gIpLastErr = gSocket.GetLastSocketError();
 | 
			
		||||
 | 
			
		||||
		if (gIpLastErr != WSA_IO_PENDING)	// Calling OnUdpReceive otherwise
 | 
			
		||||
		{
 | 
			
		||||
			gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elCount(gIpLastErrStr));
 | 
			
		||||
			writeDbg(ConnError, "UdpReceiveFrom: (%d) %s", gIpLastErr, gIpLastErrStr);
 | 
			
		||||
			UdpDisconnect();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
byte UdpSnd(byte buffer[], word length)
 | 
			
		||||
{
 | 
			
		||||
	char str[20*3];
 | 
			
		||||
 | 
			
		||||
	switch (gSocketState)
 | 
			
		||||
	{
 | 
			
		||||
		case CLOSED:
 | 
			
		||||
			UdpConnectTo(gRemoteIP, gRemotePort);
 | 
			
		||||
			if (gSocketState != OK)
 | 
			
		||||
			{
 | 
			
		||||
				writeDbg(ConnError, "UdpSnd: Reconnecting failed!");
 | 
			
		||||
				OnModbusClientPanics(ConnectionError);
 | 
			
		||||
				return 1;
 | 
			
		||||
			}
 | 
			
		||||
		case OK:
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			writeDbg(ConnError, "UdpSnd: Socket status is not OK! Doing nothing.");
 | 
			
		||||
			OnModbusClientPanics(ConnectionError);
 | 
			
		||||
			return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bin_to_strhex(buffer, str);
 | 
			
		||||
	writeDbg(ConnDebug, "UdpSnd: %s (Länge: %d)", str, length);
 | 
			
		||||
	
 | 
			
		||||
	if (gSocket.SendTo(gRemoteIP, gRemotePort, buffer, length) != 0)
 | 
			
		||||
	{
 | 
			
		||||
		gIpLastErr = gSocket.GetLastSocketError();
 | 
			
		||||
 | 
			
		||||
		if (gIpLastErr != WSA_IO_PENDING)
 | 
			
		||||
		{
 | 
			
		||||
			gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr));
 | 
			
		||||
			writeDbg(ConnError, "UdpSnd error (%d): %s", gIpLastErr, gIpLastErrStr);
 | 
			
		||||
			UdpDisconnect();
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
long UdpGetLastConnectionError(char string[])
 | 
			
		||||
{
 | 
			
		||||
	gSocket.GetLastSocketErrorAsString(string, elCount(string));
 | 
			
		||||
	return gSocket.GetLastSocketError();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								Modbus-DLL/include/DBC/MakeConfig.dbc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								Modbus-DLL/include/DBC/MakeConfig.dbc
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
VERSION ""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
NS_ : 
 | 
			
		||||
	NS_DESC_
 | 
			
		||||
	CM_
 | 
			
		||||
	BA_DEF_
 | 
			
		||||
	BA_
 | 
			
		||||
	VAL_
 | 
			
		||||
	CAT_DEF_
 | 
			
		||||
	CAT_
 | 
			
		||||
	FILTER
 | 
			
		||||
	BA_DEF_DEF_
 | 
			
		||||
	EV_DATA_
 | 
			
		||||
	ENVVAR_DATA_
 | 
			
		||||
	SGTYPE_
 | 
			
		||||
	SGTYPE_VAL_
 | 
			
		||||
	BA_DEF_SGTYPE_
 | 
			
		||||
	BA_SGTYPE_
 | 
			
		||||
	SIG_TYPE_REF_
 | 
			
		||||
	VAL_TABLE_
 | 
			
		||||
	SIG_GROUP_
 | 
			
		||||
	SIG_VALTYPE_
 | 
			
		||||
	SIGTYPE_VALTYPE_
 | 
			
		||||
	BO_TX_BU_
 | 
			
		||||
	BA_DEF_REL_
 | 
			
		||||
	BA_REL_
 | 
			
		||||
	BA_DEF_DEF_REL_
 | 
			
		||||
	BU_SG_REL_
 | 
			
		||||
	BU_EV_REL_
 | 
			
		||||
	BU_BO_REL_
 | 
			
		||||
	SG_MUL_VAL_
 | 
			
		||||
 | 
			
		||||
BS_:
 | 
			
		||||
 | 
			
		||||
BU_: MakeConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BA_DEF_ BU_  "NodeLayerModules" STRING ;
 | 
			
		||||
BA_DEF_  "DBName" STRING ;
 | 
			
		||||
BA_DEF_  "BusType" STRING ;
 | 
			
		||||
BA_DEF_DEF_  "NodeLayerModules" "ETHERNET_IL.dll";
 | 
			
		||||
BA_DEF_DEF_  "DBName" "";
 | 
			
		||||
BA_DEF_DEF_  "BusType" "Ethernet";
 | 
			
		||||
BA_ "BusType" "Ethernet";
 | 
			
		||||
BA_ "DBName" "MakeConfig";
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										165
									
								
								Modbus-DLL/include/DBC/MakeConfig.ini
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								Modbus-DLL/include/DBC/MakeConfig.ini
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,165 @@
 | 
			
		|||
[View_Vehicles]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,150,
 | 
			
		||||
[View_Vehicle]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,
 | 
			
		||||
[View_VehicleNetworks]
 | 
			
		||||
HIDDEN=3,5,
 | 
			
		||||
ORDER=0,1,2,3,4,
 | 
			
		||||
DEFINITIONS=2,3,
 | 
			
		||||
COLUMNWIDTHS=125,125,100,100,150,100,100,
 | 
			
		||||
[View_VehicleNetwork]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,
 | 
			
		||||
DEFINITIONS=1,
 | 
			
		||||
COLUMNWIDTHS=125,125,100,125,150,100,
 | 
			
		||||
[View_VehicleNetworkTxMessages]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,55,100,50,100,100,100,150,
 | 
			
		||||
[View_VehicleNetworkSignals]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,100,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_VehicleControlUnit]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,
 | 
			
		||||
DEFINITIONS=1,
 | 
			
		||||
COLUMNWIDTHS=125,125,100,125,150,100,
 | 
			
		||||
[View_VehicleGateways]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,
 | 
			
		||||
[View_VehicleGatewaySignals]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,125,125,125,125,125,
 | 
			
		||||
[View_Networks]
 | 
			
		||||
HIDDEN=2,4,
 | 
			
		||||
ORDER=0,1,2,3,
 | 
			
		||||
DEFINITIONS=2,3,
 | 
			
		||||
COLUMNWIDTHS=125,100,100,150,100,100,
 | 
			
		||||
[View_Network]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,
 | 
			
		||||
DEFINITIONS=1,
 | 
			
		||||
COLUMNWIDTHS=125,125,100,150,100,
 | 
			
		||||
[View_NetworkTxMessages]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,55,100,50,100,100,100,150,
 | 
			
		||||
[View_NetworkTxSignals]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,100,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NetworkNodeGroup]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,
 | 
			
		||||
DEFINITIONS=1,
 | 
			
		||||
COLUMNWIDTHS=125,100,150,100,
 | 
			
		||||
[View_Ecus]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,150,
 | 
			
		||||
[View_Ecu]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,
 | 
			
		||||
DEFINITIONS=1,
 | 
			
		||||
COLUMNWIDTHS=125,125,100,150,100,
 | 
			
		||||
[View_EnvVars]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_EnvVar]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NodeGroups]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,150,
 | 
			
		||||
[View_NodeGroup]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,55,150,
 | 
			
		||||
[View_Nodes]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,
 | 
			
		||||
DEFINITIONS=1,
 | 
			
		||||
COLUMNWIDTHS=125,100,150,100,
 | 
			
		||||
[View_Node]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NodeTxMessages]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,55,100,50,100,100,150,
 | 
			
		||||
[View_NodeTxMsg]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NodeTxSignals]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NodeRxSignals]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NodeTxSigs]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NodeRxSigs]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_Messages]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,55,100,50,100,100,100,150,
 | 
			
		||||
[View_Message]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_Signals]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_ValueTables]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,150,
 | 
			
		||||
[View_AttrDefs]
 | 
			
		||||
HIDDEN=6,
 | 
			
		||||
ORDER=0,1,2,3,4,5,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,100,100,50,50,100,150,
 | 
			
		||||
							
								
								
									
										47
									
								
								Modbus-DLL/include/DBC/generated.dbc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								Modbus-DLL/include/DBC/generated.dbc
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
VERSION ""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
NS_ :
 | 
			
		||||
	NS_DESC_
 | 
			
		||||
	CM_
 | 
			
		||||
	BA_DEF_
 | 
			
		||||
	BA_
 | 
			
		||||
	VAL_
 | 
			
		||||
	CAT_DEF_
 | 
			
		||||
	CAT_
 | 
			
		||||
	FILTER
 | 
			
		||||
	BA_DEF_DEF_
 | 
			
		||||
	EV_DATA_
 | 
			
		||||
	ENVVAR_DATA_
 | 
			
		||||
	SGTYPE_
 | 
			
		||||
	SGTYPE_VAL_
 | 
			
		||||
	BA_DEF_SGTYPE_
 | 
			
		||||
	BA_SGTYPE_
 | 
			
		||||
	SIG_TYPE_REF_
 | 
			
		||||
	VAL_TABLE_
 | 
			
		||||
	SIG_GROUP_
 | 
			
		||||
	SIG_VALTYPE_
 | 
			
		||||
	SIGTYPE_VALTYPE_
 | 
			
		||||
	BO_TX_BU_
 | 
			
		||||
	BA_DEF_REL_
 | 
			
		||||
	BA_REL_
 | 
			
		||||
	BA_DEF_DEF_REL_
 | 
			
		||||
	BU_SG_REL_
 | 
			
		||||
	BU_EV_REL_
 | 
			
		||||
	BU_BO_REL_
 | 
			
		||||
	SG_MUL_VAL_
 | 
			
		||||
 | 
			
		||||
BS_:
 | 
			
		||||
 | 
			
		||||
BU_: Client_2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BA_DEF_ BU_  "NodeLayerModules" STRING ;
 | 
			
		||||
BA_DEF_  "DBName" STRING ;
 | 
			
		||||
BA_DEF_  "BusType" STRING ;
 | 
			
		||||
BA_DEF_DEF_  "NodeLayerModules" "Ethernet_IL.DLL";
 | 
			
		||||
BA_DEF_DEF_  "DBName" "";
 | 
			
		||||
BA_DEF_DEF_  "BusType" "Ethernet";
 | 
			
		||||
BA_ "BusType" "Ethernet";
 | 
			
		||||
BA_ "DBName" "Modbus";
 | 
			
		||||
							
								
								
									
										165
									
								
								Modbus-DLL/include/DBC/generated.ini
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								Modbus-DLL/include/DBC/generated.ini
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,165 @@
 | 
			
		|||
[View_Vehicles]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,150,
 | 
			
		||||
[View_Vehicle]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,
 | 
			
		||||
[View_VehicleNetworks]
 | 
			
		||||
HIDDEN=3,5,
 | 
			
		||||
ORDER=0,1,2,3,4,
 | 
			
		||||
DEFINITIONS=2,3,
 | 
			
		||||
COLUMNWIDTHS=125,125,100,100,150,100,100,
 | 
			
		||||
[View_VehicleNetwork]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,
 | 
			
		||||
DEFINITIONS=1,
 | 
			
		||||
COLUMNWIDTHS=125,125,100,125,150,100,
 | 
			
		||||
[View_VehicleNetworkTxMessages]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,55,100,50,100,100,100,150,
 | 
			
		||||
[View_VehicleNetworkSignals]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,100,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_VehicleControlUnit]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,
 | 
			
		||||
DEFINITIONS=1,
 | 
			
		||||
COLUMNWIDTHS=125,125,100,125,150,100,
 | 
			
		||||
[View_VehicleGateways]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,
 | 
			
		||||
[View_VehicleGatewaySignals]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,125,125,125,125,125,
 | 
			
		||||
[View_Networks]
 | 
			
		||||
HIDDEN=2,4,
 | 
			
		||||
ORDER=0,1,2,3,
 | 
			
		||||
DEFINITIONS=2,3,
 | 
			
		||||
COLUMNWIDTHS=125,100,100,150,100,100,
 | 
			
		||||
[View_Network]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,
 | 
			
		||||
DEFINITIONS=1,
 | 
			
		||||
COLUMNWIDTHS=125,125,100,150,100,
 | 
			
		||||
[View_NetworkTxMessages]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,55,100,50,100,100,100,150,
 | 
			
		||||
[View_NetworkTxSignals]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,100,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NetworkNodeGroup]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,
 | 
			
		||||
DEFINITIONS=1,
 | 
			
		||||
COLUMNWIDTHS=125,100,150,100,
 | 
			
		||||
[View_Ecus]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,150,
 | 
			
		||||
[View_Ecu]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,
 | 
			
		||||
DEFINITIONS=1,
 | 
			
		||||
COLUMNWIDTHS=125,125,100,150,100,
 | 
			
		||||
[View_EnvVars]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_EnvVar]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NodeGroups]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,150,
 | 
			
		||||
[View_NodeGroup]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,55,150,
 | 
			
		||||
[View_Nodes]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,
 | 
			
		||||
DEFINITIONS=1,
 | 
			
		||||
COLUMNWIDTHS=125,100,150,100,
 | 
			
		||||
[View_Node]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NodeTxMessages]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,55,100,50,100,100,150,
 | 
			
		||||
[View_NodeTxMsg]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NodeTxSignals]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NodeRxSignals]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NodeTxSigs]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_NodeRxSigs]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_Messages]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,55,100,50,100,100,100,150,
 | 
			
		||||
[View_Message]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,125,100,50,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_Signals]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,2,3,4,5,6,7,8,9,10,11,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,50,100,100,100,50,50,50,50,100,100,150,
 | 
			
		||||
[View_ValueTables]
 | 
			
		||||
HIDDEN=
 | 
			
		||||
ORDER=0,1,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,150,
 | 
			
		||||
[View_AttrDefs]
 | 
			
		||||
HIDDEN=6,
 | 
			
		||||
ORDER=0,1,2,3,4,5,
 | 
			
		||||
DEFINITIONS=
 | 
			
		||||
COLUMNWIDTHS=125,100,100,50,50,100,150,
 | 
			
		||||
							
								
								
									
										44
									
								
								Modbus-DLL/include/SysVars/generated.vsysvar
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								Modbus-DLL/include/SysVars/generated.vsysvar
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<systemvariables version="4">
 | 
			
		||||
  <namespace name="" comment="">
 | 
			
		||||
    <namespace name="Config" comment="">
 | 
			
		||||
      <namespace name="Modbus" comment="">
 | 
			
		||||
        <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="ms" name="RequestTimeout" comment="The maximum duration for a Modbus-UDP/-TCP request in milliseconds. After timeout a retransmission may be started (see MaxRetransmissionCount).    Use `ping` to get the maximum latency to a device, double it and add 2-3 ms for processing." bitcount="32" isSigned="true" encoding="65001" type="int" startValue="7" minValue="1" minValuePhys="1" maxValue="1000" maxValuePhys="1000" />
 | 
			
		||||
        <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="Port" comment="" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="502" minValue="1" minValuePhys="1" maxValue="65535" maxValuePhys="65535" />
 | 
			
		||||
        <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="times" name="MaxTransmissionCount" comment="How often a retransmission of a request will be sent until it gets discarded and an error is thrown." bitcount="32" isSigned="true" encoding="65001" type="int" startValue="2" minValue="1" minValuePhys="1" maxValue="10" maxValuePhys="10" />
 | 
			
		||||
      </namespace>
 | 
			
		||||
      <namespace name="TcpIp" comment="">
 | 
			
		||||
        <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="AdapterIndex" comment="Index of network interface to use" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="2" minValue="1" minValuePhys="1" maxValue="20" maxValuePhys="20" />
 | 
			
		||||
      </namespace>
 | 
			
		||||
    </namespace>
 | 
			
		||||
    <namespace name="Ethernet1" comment="Subnet: 192.168.1.">
 | 
			
		||||
      <namespace name="Client_2" comment="Server with ip address '192.168.1.2'">
 | 
			
		||||
        <namespace name="Config" comment="Configuration section for this server">
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="IP" comment="The IP address of this server" bitcount="8" isSigned="true" encoding="65001" type="string" startValue="192.168.1.2" />
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="ms" name="Interval" comment="The interval with which the device will be queried" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="100" minValue="10" minValuePhys="10" maxValue="10000" maxValuePhys="10000" />
 | 
			
		||||
        </namespace>
 | 
			
		||||
        <namespace name="Info" comment="Some information about the device">
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="true" valueSequence="false" unit="" name="Vendor" comment="The vendor of the device" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="23">
 | 
			
		||||
            <valuetable definesMinMax="true">
 | 
			
		||||
              <valuetableentry value="2" description="BuR" />
 | 
			
		||||
              <valuetableentry value="23" description="Wago" />
 | 
			
		||||
            </valuetable>
 | 
			
		||||
          </variable>
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="true" valueSequence="false" unit="" name="SerialCode" comment="The serial code of the server" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="750" minValue="1" minValuePhys="1" maxValue="10000" maxValuePhys="10000" />
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="true" valueSequence="false" unit="" name="DeviceCode" comment="The device code of the server" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="881" minValue="1" minValuePhys="1" maxValue="10000" maxValuePhys="10000" />
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="true" valueSequence="false" unit="" name="Modules" comment="The type and number of inputs of modules that are connected to the server" bitcount="8" isSigned="true" encoding="65001" type="string" startValue="DI2,DO16" />
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="true" valueSequence="false" unit="" name="InputRegisters" comment="Number of input registers" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="123" maxValuePhys="123" />
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="true" valueSequence="false" unit="" name="InputBits" comment="Number of input bits" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="2" minValue="0" minValuePhys="0" maxValue="2000" maxValuePhys="2000" />
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="true" valueSequence="false" unit="" name="OutputRegisters" comment="Number of output registers" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="123" maxValuePhys="123" />
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="true" valueSequence="false" unit="" name="OutputBits" comment="Number of output bits" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="16" minValue="0" minValuePhys="0" maxValue="2000" maxValuePhys="2000" />
 | 
			
		||||
        </namespace>
 | 
			
		||||
        <namespace name="Data" comment="The actual process image">
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="InputRegisters" comment="The values of the input registers" bitcount="9" isSigned="true" encoding="65001" type="intarray" arrayLength="0" />
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="InputBits" comment="The state of the input bits" bitcount="2" isSigned="true" encoding="65001" type="intarray" arrayLength="2" />
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="OutputRegisters" comment="The values of the output registers. Write here and the values will be sent to the device" bitcount="9" isSigned="true" encoding="65001" type="intarray" arrayLength="0" />
 | 
			
		||||
          <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="OutputBits" comment="The state of the output bits. Write here and the values will be sent to the device" bitcount="2" isSigned="true" encoding="65001" type="intarray" arrayLength="16" />
 | 
			
		||||
        </namespace>
 | 
			
		||||
      </namespace>
 | 
			
		||||
    </namespace>
 | 
			
		||||
  </namespace>
 | 
			
		||||
</systemvariables>
 | 
			
		||||
							
								
								
									
										1118
									
								
								Modbus-DLL/include/VCSignalProtocolDLL/Include/IPBPacketAPI.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1118
									
								
								Modbus-DLL/include/VCSignalProtocolDLL/Include/IPBPacketAPI.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										9
									
								
								Modbus-DLL/include/VCSignalProtocolDLL/Stdafx.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Modbus-DLL/include/VCSignalProtocolDLL/Stdafx.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
/*-------------------------------------------------------------------
 | 
			
		||||
  StdAfx.cpp
 | 
			
		||||
  -------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  (c) 2009 Vector Informatik GmbH. All rights reserved.
 | 
			
		||||
 | 
			
		||||
  ------------------------------------------------------------------- */ 
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
							
								
								
									
										21
									
								
								Modbus-DLL/include/VCSignalProtocolDLL/Stdafx.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								Modbus-DLL/include/VCSignalProtocolDLL/Stdafx.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
/*-------------------------------------------------------------------
 | 
			
		||||
  StdAfx.h
 | 
			
		||||
  -------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  (c) 2009 Vector Informatik GmbH. All rights reserved.
 | 
			
		||||
 | 
			
		||||
  ------------------------------------------------------------------- */ 
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Library includes
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Project specific includes
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include "include/IPBPacketAPI.h"
 | 
			
		||||
							
								
								
									
										481
									
								
								Modbus-DLL/include/VCSignalProtocolDLL/VCSignalProtocol.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										481
									
								
								Modbus-DLL/include/VCSignalProtocolDLL/VCSignalProtocol.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,481 @@
 | 
			
		|||
/*-------------------------------------------------------------------
 | 
			
		||||
  VCSignalProtocol.h
 | 
			
		||||
  -------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  (c) Vector Informatik GmbH. All rights reserved.
 | 
			
		||||
 | 
			
		||||
  ------------------------------------------------------------------- */ 
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "VCSignalProtocol.h"
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
// Implementaiton of VExampleSignalProtocol
 | 
			
		||||
//
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------------
 | 
			
		||||
//! Constructor
 | 
			
		||||
/**
 | 
			
		||||
*/
 | 
			
		||||
VCSignalProtocol::VCSignalProtocol() :
 | 
			
		||||
  mProtocolId( NIPB::kNil ),
 | 
			
		||||
  mContentId ( 0    )
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// IProtocol
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Initialize the protocol
 | 
			
		||||
/*! 
 | 
			
		||||
  Register the protocol and its tokens at the IPB Packet Lib.
 | 
			
		||||
 | 
			
		||||
  \param protocolManager The protocol manager for this protocol. The pointer can be stored and is valid
 | 
			
		||||
                         during the whole lifetime of the IProtocol object.
 | 
			
		||||
  \param networkModel    The network model for this protocol. The pointer can be stored and is valid
 | 
			
		||||
                         during the whole lifetime of the IProtocol object.
 | 
			
		||||
  \param modelCreator    Define network model entities with this object. Pointer is only valid during this call.
 | 
			
		||||
*/
 | 
			
		||||
VDEF VCSignalProtocol::Initialize( NIPB::IProtocolManager /*in*/ *protocolManager, NIPB::INetworkModel /*in*/ *networkModel, NIPB::INetworkModelCreator /*in*/ *modelCreator )
 | 
			
		||||
{
 | 
			
		||||
  if (protocolManager == 0) return NIPB::kInvalidArg;
 | 
			
		||||
  if (networkModel    == 0) return NIPB::kInvalidArg;
 | 
			
		||||
  if (modelCreator    == 0) return NIPB::kInvalidArg;
 | 
			
		||||
 | 
			
		||||
  mProtocolManager = protocolManager;
 | 
			
		||||
 | 
			
		||||
  NIPB::ITokenDefinitionCreator *protocol = 0;
 | 
			
		||||
  if (modelCreator->DefineProtocol( "vc-sig", &mProtocolId, &protocol ) == NIPB::kOK)
 | 
			
		||||
  {
 | 
			
		||||
    modelCreator->DefineProtocolField( protocol, "contentId", &mContentId, 0 );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return NIPB::kOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Denitialize the protocol
 | 
			
		||||
/*!
 | 
			
		||||
  \param protocolManager The protocol manager for this protocol. The pointer is invalid after Deinitialize.
 | 
			
		||||
  \param networkModel    The network model for this protocol. The pointer is invalid after Deinitialize.
 | 
			
		||||
*/
 | 
			
		||||
VDEF VCSignalProtocol::Deinitialize( NIPB::IProtocolManager /*in*/ * /*protocolManager*/, NIPB::INetworkModel /*in*/ * /*networkModel*/ )
 | 
			
		||||
{
 | 
			
		||||
  return NIPB::kOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Returns the textual designator of the protocol
 | 
			
		||||
/*!
 | 
			
		||||
    The designator is used to access the protocol in CAPL (via Nodelayer) or the GUI of CANoe/CANalyzer.
 | 
			
		||||
 | 
			
		||||
    \param bufferSize   Length of 'buffer'. Must not > 0
 | 
			
		||||
    \param buffer       The designator is copied to this buffer. Must not be 0
 | 
			
		||||
*/
 | 
			
		||||
VDEF VCSignalProtocol::GetDesignator( unsigned long /*in*/ bufferSize, char /*out**/ *buffer )
 | 
			
		||||
{
 | 
			
		||||
  if (bufferSize == 0) return NIPB::kInvalidArg;
 | 
			
		||||
  if (buffer     == 0) return NIPB::kInvalidArg;
 | 
			
		||||
 | 
			
		||||
  strcpy_s( buffer, bufferSize, "vc-sig" );
 | 
			
		||||
 | 
			
		||||
  return NIPB::kOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Unique token identifier of the protocol
 | 
			
		||||
/*!
 | 
			
		||||
    The VTokenId of the protocol is registerd on startup during defintion of the protocol token.
 | 
			
		||||
 | 
			
		||||
    \param identifier  A pointer to a VTokenId, which retrieves the identifier. Must not be 0
 | 
			
		||||
*/
 | 
			
		||||
VDEF VCSignalProtocol::GetIdentifier( NIPB::VTokenId /*out*/ *identifier )
 | 
			
		||||
{
 | 
			
		||||
  if (identifier == 0) return NIPB::kInvalidArg;
 | 
			
		||||
 | 
			
		||||
  *identifier = mProtocolId;
 | 
			
		||||
 | 
			
		||||
  return NIPB::kOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Returns specific encoder for a token ID
 | 
			
		||||
/*!
 | 
			
		||||
    The IEncoder is used to access a token within a IPacket.
 | 
			
		||||
 | 
			
		||||
    \param tokenId  Token identifier for which the encoder is requested.
 | 
			
		||||
    \param encoder  Returns a pointer to the encoder. Must not be 0.
 | 
			
		||||
*/
 | 
			
		||||
VDEF VCSignalProtocol::GetEncoder( NIPB::VTokenId /*in*/ tokenId, NIPB::IEncoder /*out*/ **encoder )
 | 
			
		||||
{
 | 
			
		||||
  if (encoder == 0) return NIPB::kInvalidArg;
 | 
			
		||||
 | 
			
		||||
  if (tokenId == mContentId)
 | 
			
		||||
  {
 | 
			
		||||
    return mProtocolManager->GetEncoder( NIPB::kEncoderUnsignedLE, encoder );
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    return NIPB::kEncodingNotSupported;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Initialize a specific protocol during creation of a new packet
 | 
			
		||||
/*!
 | 
			
		||||
    Use this method to setup a protocol within a packet.
 | 
			
		||||
 | 
			
		||||
    \param packet           The packet where the protocol should be setup. Must not be 0.
 | 
			
		||||
    \param protocolTypeId   Type ID for a specific type of the protocol, i.e ARP request or ARP response
 | 
			
		||||
    \param topProtocolToken Points to the top most protocol within the packet.
 | 
			
		||||
    \param protocolToken    This strucuture must be filled in InitProtocol.
 | 
			
		||||
*/
 | 
			
		||||
VDEF VCSignalProtocol::InitProtocol( NIPB::IPacket /*in*/ *packet, NIPB::VTokenId /*in*/ /*protocolTypeId*/, const NIPB::VProtocolToken /*in*/ * /*topProtocolToken*/, NIPB::VProtocolToken /*out*/ *vc_sig )
 | 
			
		||||
{
 | 
			
		||||
  if (mProtocolManager == 0)    return NIPB::kInternalError;
 | 
			
		||||
  if (packet           == 0)    return NIPB::kInvalidArg;
 | 
			
		||||
 | 
			
		||||
  NIPB::VResult result            = NIPB::kError;
 | 
			
		||||
  BYTE          broadcastMacId[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Init Ethernet protocol
 | 
			
		||||
  //
 | 
			
		||||
  NIPB::VProtocolToken eth;
 | 
			
		||||
  if ((result = mProtocolManager->GetProtocolByIndex( packet, 0, ð )) != NIPB::kOK)
 | 
			
		||||
  {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
  SetTokenData( eth, NIPB::kEthDestination, 6, broadcastMacId ); // Set destination MAC ID to Broadcast
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Init IPv4 protocol
 | 
			
		||||
  //
 | 
			
		||||
  NIPB::VProtocolToken ipv4;
 | 
			
		||||
  if ((result = mProtocolManager->InitProtocol( packet, NIPB::kIPv4, 0, &ipv4 )) != NIPB::kOK)
 | 
			
		||||
  {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
  SetTokenUnsigned( ipv4, NIPB::kIPv4Destination, 4, 0xFFFFFFFF ); // Set destination IP address to Broadcast
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Init UDP protocol
 | 
			
		||||
  //
 | 
			
		||||
  NIPB::VProtocolToken udp;
 | 
			
		||||
  if ((result = mProtocolManager->InitProtocol( packet, NIPB::kUDP, 0, &udp )) != NIPB::kOK)
 | 
			
		||||
  {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
  SetTokenUnsigned( udp, NIPB::kUDPSource     , 2, 40001 ); // Set source port
 | 
			
		||||
  SetTokenUnsigned( udp, NIPB::kUDPDestination, 2, 40001 ); // Set destination port
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Init VCSig protocol
 | 
			
		||||
  //
 | 
			
		||||
  if (result == (mProtocolManager->ResizeToken( &udp, kHeaderBitLength, 0 )))
 | 
			
		||||
  {
 | 
			
		||||
    vc_sig->tokenId         = mProtocolId;
 | 
			
		||||
    vc_sig->protocol        = this;
 | 
			
		||||
    vc_sig->packet          = packet;
 | 
			
		||||
    vc_sig->headerBitOffset = udp.bitOffset;
 | 
			
		||||
    vc_sig->headerBitLength = kHeaderBitLength;
 | 
			
		||||
    vc_sig->bitOffset       = udp.bitOffset + kHeaderBitLength;
 | 
			
		||||
    vc_sig->bitLength       = 0;
 | 
			
		||||
 | 
			
		||||
    SetTokenUnsigned( *vc_sig, mContentId, 4, 0xFFFFFFFF ); // Set invalid content ID
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Complete the protocol at the end of creation/modification of a packet.
 | 
			
		||||
/*!
 | 
			
		||||
  In this function the checksum or length field of a protocol can be calculated.
 | 
			
		||||
 | 
			
		||||
  \param packet   The packet to complete
 | 
			
		||||
  \param protocol Points to the protocol token for this protocol
 | 
			
		||||
*/
 | 
			
		||||
VDEF VCSignalProtocol::CompleteProtocol( NIPB::IPacket /*in*/ *packet, const NIPB::VProtocolToken /*in*/ *vc_sig )
 | 
			
		||||
{
 | 
			
		||||
  if (packet          == 0)           return NIPB::kInvalidArg;
 | 
			
		||||
  if (vc_sig          == 0)           return NIPB::kInvalidArg;
 | 
			
		||||
  if (vc_sig->tokenId != mProtocolId) return NIPB::kError;
 | 
			
		||||
 | 
			
		||||
  return NIPB::kOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Parse a received packet.
 | 
			
		||||
/*!
 | 
			
		||||
    The method is called, when a packet is parsed. During parsing the VProtocols structure is initialzed
 | 
			
		||||
    with the protocol information, whiche are returnd with 'protocolToken'.
 | 
			
		||||
 | 
			
		||||
    \param packet            The packet to parse.
 | 
			
		||||
    \param topProtocolToken  Points to the top most, already parsed protocol within the packet.
 | 
			
		||||
    \param errorWriter       Use this interface to returne parsing errors, i.e wrong checksum
 | 
			
		||||
    \param nextProcotolId    Return the VTokenId of the next protocol.
 | 
			
		||||
    \param protocolToken     Fill this strucutre to setup the VProtocols structure.
 | 
			
		||||
*/
 | 
			
		||||
VDEF VCSignalProtocol::ParsePacket( NIPB::IPacket /*in*/ *packet, const NIPB::VProtocolToken /*in*/ *topProtocolToken, NIPB::IFormatter /*in*/ * /*errorWriter*/, NIPB::VTokenId /*out*/ *nextProcotolId, NIPB::VProtocolToken /*out*/ *protocolToken )
 | 
			
		||||
{
 | 
			
		||||
  if (packet                    == 0   ) return NIPB::kInvalidArg;
 | 
			
		||||
  if (nextProcotolId            == 0   ) return NIPB::kInvalidArg;
 | 
			
		||||
  if (protocolToken             == 0   ) return NIPB::kInvalidArg;
 | 
			
		||||
  if (topProtocolToken          == 0   ) return NIPB::kInvalidArg;
 | 
			
		||||
  if (topProtocolToken->tokenId != NIPB::kUDP) return NIPB::kInvalidArg;
 | 
			
		||||
 | 
			
		||||
  NIPB::VResult     result       = NIPB::kError;
 | 
			
		||||
  const BYTE       *packetData   = 0;
 | 
			
		||||
  ULONG             packetLength = 0;
 | 
			
		||||
  NIPB::VProtocols *protocols    = 0;
 | 
			
		||||
 | 
			
		||||
  if (   ((result = packet->GetDataSize( &packetLength       )) == NIPB::kOK)
 | 
			
		||||
      && ((result = packet->GetDataPtr ( (void**)&packetData )) == NIPB::kOK) 
 | 
			
		||||
      && ((result = packet->GetProtocols( &protocols         )) == NIPB::kOK) 
 | 
			
		||||
      )
 | 
			
		||||
  {
 | 
			
		||||
    result = NIPB::kPacketParseError;
 | 
			
		||||
 | 
			
		||||
    if (BI2BY(topProtocolToken->bitLength) >= kHeaderLength)
 | 
			
		||||
    {
 | 
			
		||||
      protocolToken->tokenId         = mProtocolId;
 | 
			
		||||
      protocolToken->protocol        = this;
 | 
			
		||||
      protocolToken->packet          = packet;
 | 
			
		||||
      protocolToken->headerBitOffset = topProtocolToken->bitOffset;
 | 
			
		||||
      protocolToken->headerBitLength = kHeaderBitLength;
 | 
			
		||||
      protocolToken->bitOffset       = kHeaderBitLength + topProtocolToken->bitOffset;
 | 
			
		||||
      protocolToken->bitLength       = topProtocolToken->bitLength - kHeaderBitLength;
 | 
			
		||||
 | 
			
		||||
      protocols->contentId           = GetContentId( packetData, packetLength, *protocolToken );
 | 
			
		||||
 | 
			
		||||
      *nextProcotolId = 0;
 | 
			
		||||
       result = NIPB::kOK;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Return a token of a protocol.
 | 
			
		||||
/*!
 | 
			
		||||
  The function must fill the 'token' with the information of the request 'tokenId'.
 | 
			
		||||
 | 
			
		||||
  \param protocolToken  Points the the VProtocolToken for the protocol.
 | 
			
		||||
  \param tokenId        The identifier of the requested token.
 | 
			
		||||
  \param token          Points to a VToken, which must be fille by this function.
 | 
			
		||||
*/
 | 
			
		||||
VDEF VCSignalProtocol::GetToken( const NIPB::VProtocolToken /*in*/ *protocolToken, NIPB::VTokenId /*in*/ tokenId, NIPB::VToken /*out*/ *token )
 | 
			
		||||
{
 | 
			
		||||
  if (token                  == 0)           return NIPB::kInvalidArg;
 | 
			
		||||
  if (protocolToken          == 0)           return NIPB::kInvalidArg;
 | 
			
		||||
  if (protocolToken->tokenId != mProtocolId) return NIPB::kTokenNotFound;
 | 
			
		||||
  
 | 
			
		||||
  if (tokenId == mContentId)
 | 
			
		||||
  {
 | 
			
		||||
    return MakeHeaderToken( protocolToken, mContentId, 0, 32, token );
 | 
			
		||||
  }
 | 
			
		||||
  else if (tokenId == NIPB::kData)
 | 
			
		||||
  {
 | 
			
		||||
    return MakePayloadToken( protocolToken, NIPB::kData, 0, protocolToken->bitLength, token );
 | 
			
		||||
  }
 | 
			
		||||
  else if (tokenId == NIPB::kHeader)
 | 
			
		||||
  {
 | 
			
		||||
    return MakeHeaderToken( protocolToken, NIPB::kHeader, 0, protocolToken->bitLength, token );
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    return NIPB::kTokenNotFound;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Build a tree with information of the protocol.
 | 
			
		||||
/*!
 | 
			
		||||
    The function is used in CANoe/CANalyzer in the detail view of the trace window to build
 | 
			
		||||
    a tree with protocols and fields.
 | 
			
		||||
 | 
			
		||||
    \param protocolToken  Protocol token of this protocol
 | 
			
		||||
    \param type           Inspection type
 | 
			
		||||
    \param inspector      IPacketInspectore to create the output.
 | 
			
		||||
*/
 | 
			
		||||
VDEF VCSignalProtocol::InspectProtocol ( const NIPB::VProtocolToken /*in*/ *protocolToken, NIPB::VInspectionType /*in*/ type, NIPB::IPacketInspector /*in*/ *inspector )
 | 
			
		||||
{
 | 
			
		||||
  if (protocolToken         == 0) return NIPB::kInvalidArg;
 | 
			
		||||
  if (protocolToken->packet == 0) return NIPB::kInvalidArg;
 | 
			
		||||
  if (inspector             == 0) return NIPB::kInvalidArg;
 | 
			
		||||
 | 
			
		||||
  NIPB::VResult result       = NIPB::kError;
 | 
			
		||||
  const BYTE   *packetData   = 0;
 | 
			
		||||
  ULONG         packetLength = 0;
 | 
			
		||||
 | 
			
		||||
  if (   ((result = protocolToken->packet->GetDataSize( &packetLength       )) == NIPB::kOK)
 | 
			
		||||
      && ((result = protocolToken->packet->GetDataPtr ( (void**)&packetData )) == NIPB::kOK) )
 | 
			
		||||
  {
 | 
			
		||||
    switch(type)
 | 
			
		||||
    {
 | 
			
		||||
      //
 | 
			
		||||
      // Protocol Info column
 | 
			
		||||
      //
 | 
			
		||||
    case NIPB::kInspectionInfoColumn:
 | 
			
		||||
      break;
 | 
			
		||||
      //
 | 
			
		||||
      // Detail View
 | 
			
		||||
      //
 | 
			
		||||
    case NIPB::kInspectionDetailTree:
 | 
			
		||||
      // UDP
 | 
			
		||||
      if (inspector->BeginToken( mProtocolId, 0, 0) == NIPB::kOK)
 | 
			
		||||
      {
 | 
			
		||||
        NIPB::IFormatter *formatter = 0;
 | 
			
		||||
        if (inspector->SelectField( NIPB::kFieldLabel, &formatter ) == NIPB::kOK)
 | 
			
		||||
        {
 | 
			
		||||
          formatter->FormatString( "vc-sig" );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Source port
 | 
			
		||||
        ULONG val = GetContentId( packetData, packetLength, *protocolToken );
 | 
			
		||||
        FormatUnsigned( inspector, "contentId", mContentId, val, 4 );
 | 
			
		||||
 | 
			
		||||
        inspector->EndToken();
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Methods
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Returns the content ID
 | 
			
		||||
/*!
 | 
			
		||||
*/
 | 
			
		||||
ULONG VCSignalProtocol::GetContentId( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol )
 | 
			
		||||
{
 | 
			
		||||
  ULONG offset = BI2BY(protocol.headerBitOffset);
 | 
			
		||||
 | 
			
		||||
  if (offset+4 < packetLength)
 | 
			
		||||
  {
 | 
			
		||||
    return *((ULONG*)&packetData[offset]);
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Fill a VToken structure.
 | 
			
		||||
/*! 
 | 
			
		||||
*/
 | 
			
		||||
NIPB::VResult VCSignalProtocol::MakeHeaderToken( const NIPB::VProtocolToken /*in*/ *protocolToken, NIPB::VTokenId /*in*/ tokenId, ULONG /*in*/ offset, ULONG /*in*/ length, NIPB::VToken /*out*/ *token )
 | 
			
		||||
{
 | 
			
		||||
  if (token         == 0) return NIPB::kInvalidArg;
 | 
			
		||||
  if (protocolToken == 0) return NIPB::kInvalidArg;
 | 
			
		||||
 | 
			
		||||
  token->protocol  = protocolToken->protocol;
 | 
			
		||||
  token->packet    = protocolToken->packet;
 | 
			
		||||
  token->tokenId   = tokenId;
 | 
			
		||||
  token->bitOffset = offset + protocolToken->headerBitOffset;
 | 
			
		||||
  token->bitLength = length;
 | 
			
		||||
 | 
			
		||||
  return NIPB::kOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Fill a VToken structure.
 | 
			
		||||
/*! 
 | 
			
		||||
*/
 | 
			
		||||
NIPB::VResult VCSignalProtocol::MakePayloadToken( const NIPB::VProtocolToken /*in*/ *protocolToken, NIPB::VTokenId /*in*/ tokenId, ULONG /*in*/ offset, ULONG /*in*/ length, NIPB::VToken /*out*/ *token )
 | 
			
		||||
{
 | 
			
		||||
  if (token         == 0) return NIPB::kInvalidArg;
 | 
			
		||||
  if (protocolToken == 0) return NIPB::kInvalidArg;
 | 
			
		||||
 | 
			
		||||
  token->protocol  = protocolToken->protocol;
 | 
			
		||||
  token->packet    = protocolToken->packet;
 | 
			
		||||
  token->tokenId   = tokenId;
 | 
			
		||||
  token->bitOffset = offset + protocolToken->bitOffset;
 | 
			
		||||
  token->bitLength = length;
 | 
			
		||||
 | 
			
		||||
  return NIPB::kOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Format a unsigned token.
 | 
			
		||||
/*! 
 | 
			
		||||
*/
 | 
			
		||||
void VCSignalProtocol::FormatUnsigned( NIPB::IPacketInspector *inspector, LPCTSTR label, NIPB::VTokenId tokenId, ULONG value, ULONG valueLength )
 | 
			
		||||
{
 | 
			
		||||
  if ((inspector) && (inspector->BeginToken( tokenId, 0, 0) == NIPB::kOK))
 | 
			
		||||
  {
 | 
			
		||||
    NIPB::IFormatter *formatter = 0;
 | 
			
		||||
 | 
			
		||||
    if (inspector->SelectField( NIPB::kFieldLabel, &formatter ) == NIPB::kOK)
 | 
			
		||||
    {
 | 
			
		||||
      formatter->FormatString( label );
 | 
			
		||||
    }
 | 
			
		||||
    if (inspector->SelectField( NIPB::kFieldValue, &formatter ) == NIPB::kOK)
 | 
			
		||||
    {
 | 
			
		||||
      formatter->FormatUnsigned( value, valueLength, 0 );
 | 
			
		||||
    }
 | 
			
		||||
    inspector->EndToken();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Set the value of a unsigned token.
 | 
			
		||||
/*! 
 | 
			
		||||
*/
 | 
			
		||||
NIPB::VResult VCSignalProtocol::SetTokenUnsigned( NIPB::VProtocolToken &protocolToken, NIPB::VTokenId tokenId, ULONG valueLength, ULONG value )
 | 
			
		||||
{
 | 
			
		||||
  if (protocolToken.protocol == 0) return NIPB::kInvalidArg;
 | 
			
		||||
 | 
			
		||||
  NIPB::VResult result  = NIPB::kError;
 | 
			
		||||
  NIPB::VToken  token;
 | 
			
		||||
  if ((result = protocolToken.protocol->GetToken( &protocolToken, tokenId, &token)) == NIPB::kOK)
 | 
			
		||||
  {
 | 
			
		||||
    NIPB::IEncoder *encoder = 0;
 | 
			
		||||
    if (((result = token.protocol->GetEncoder( tokenId, &encoder )) == NIPB::kOK) && (encoder))
 | 
			
		||||
    {
 | 
			
		||||
      result = encoder->Encode( &token, 0, NIPB::kEncodingUnsigned, valueLength, &value );
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Set the data of a data token.
 | 
			
		||||
/*! 
 | 
			
		||||
*/
 | 
			
		||||
NIPB::VResult VCSignalProtocol::SetTokenData( NIPB::VProtocolToken &protocolToken, NIPB::VTokenId tokenId, ULONG dataLength, const BYTE *data )
 | 
			
		||||
{
 | 
			
		||||
  if (protocolToken.protocol == 0) return NIPB::kInvalidArg;
 | 
			
		||||
 | 
			
		||||
  NIPB::VResult result  = NIPB::kError;
 | 
			
		||||
  NIPB::VToken  token;
 | 
			
		||||
  if ((result = protocolToken.protocol->GetToken( &protocolToken, tokenId, &token)) == NIPB::kOK)
 | 
			
		||||
  {
 | 
			
		||||
    NIPB::IEncoder *encoder = 0;
 | 
			
		||||
    if (((result = token.protocol->GetEncoder( tokenId, &encoder )) == NIPB::kOK) && (encoder))
 | 
			
		||||
    {
 | 
			
		||||
      result = encoder->Encode( &token, 0, NIPB::kEncodingData, dataLength, data );
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										76
									
								
								Modbus-DLL/include/VCSignalProtocolDLL/VCSignalProtocol.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								Modbus-DLL/include/VCSignalProtocolDLL/VCSignalProtocol.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,76 @@
 | 
			
		|||
/*-------------------------------------------------------------------
 | 
			
		||||
  VCSignalProtocol.h
 | 
			
		||||
  -------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  (c) Vector Informatik GmbH. All rights reserved.
 | 
			
		||||
 | 
			
		||||
  ------------------------------------------------------------------- */ 
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Signal protocol class
 | 
			
		||||
/*! 
 | 
			
		||||
    This class implements the NIPB::IProtocol interface. It handles a
 | 
			
		||||
    proprietary signal protocol for the Vector Conecept Car Ethernet
 | 
			
		||||
    Network.
 | 
			
		||||
 | 
			
		||||
    The protocol is located within a UDP protocol and uses the UDP
 | 
			
		||||
    ports 40001. The first 32bit of the UDP payload are the content ID.
 | 
			
		||||
    The 32-bit content ID represents the header of this Signal protocol.
 | 
			
		||||
    The payload of this protocol is interpreted by the DBC.
 | 
			
		||||
*/
 | 
			
		||||
class VCSignalProtocol : 
 | 
			
		||||
  public NIPB::IProtocol
 | 
			
		||||
{
 | 
			
		||||
  static const ULONG kHeaderLength    = 4;
 | 
			
		||||
  static const ULONG kHeaderBitLength = 32;
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Construction
 | 
			
		||||
  //
 | 
			
		||||
public:
 | 
			
		||||
  VCSignalProtocol();
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // IProtocol
 | 
			
		||||
  //
 | 
			
		||||
public:
 | 
			
		||||
  VDECL Initialize      ( NIPB::IProtocolManager /*in*/ *protocolManager, NIPB::INetworkModel /*in*/ *networkModel, NIPB::INetworkModelCreator /*in*/ *modelCreator );
 | 
			
		||||
  VDECL Deinitialize    ( NIPB::IProtocolManager /*in*/ *protocolManager, NIPB::INetworkModel /*in*/ *networkModel );
 | 
			
		||||
  VDECL GetDesignator   ( unsigned long /*in*/ bufferSize, char /*out**/ *buffer );
 | 
			
		||||
  VDECL GetIdentifier   ( NIPB::VTokenId /*out*/ *identifier );
 | 
			
		||||
  VDECL GetEncoder      ( NIPB::VTokenId /*in*/ tokenId, NIPB::IEncoder /*out*/ **encoder );
 | 
			
		||||
  VDECL InitProtocol    ( NIPB::IPacket /*in*/ *packet, NIPB::VTokenId /*in*/ protocolTypeId, const NIPB::VProtocolToken /*in*/ *topProtocolToken, NIPB::VProtocolToken /*out*/ *protocolToken);
 | 
			
		||||
  VDECL CompleteProtocol( NIPB::IPacket /*in*/ *packet, const NIPB::VProtocolToken /*in*/ *udp );
 | 
			
		||||
  VDECL ParsePacket     ( NIPB::IPacket /*in*/ *packet, const NIPB::VProtocolToken /*in*/ *topProtocolToken, NIPB::IFormatter /*in*/ *errorWriter, NIPB::VTokenId /*out*/ *nextProcotolId, NIPB::VProtocolToken /*out*/ *protocolToken );
 | 
			
		||||
  VDECL GetToken        ( const NIPB::VProtocolToken /*in*/ *protocolToken, NIPB::VTokenId /*in*/ tokenId, NIPB::VToken /*out*/ *token );
 | 
			
		||||
  VDECL InspectProtocol ( const NIPB::VProtocolToken /*in*/ *protocolToken, NIPB::VInspectionType /*in*/ type, NIPB::IPacketInspector /*in*/ *inspector );
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Methods
 | 
			
		||||
  //
 | 
			
		||||
public:
 | 
			
		||||
  ULONG GetContentId( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol );
 | 
			
		||||
 | 
			
		||||
  static NIPB::VResult MakeHeaderToken( const NIPB::VProtocolToken /*in*/ *protocolToken, NIPB::VTokenId /*in*/ tokenId, ULONG /*in*/ offset, ULONG /*in*/ length, NIPB::VToken /*out*/ *token );
 | 
			
		||||
  static NIPB::VResult MakePayloadToken( const NIPB::VProtocolToken /*in*/ *protocolToken, NIPB::VTokenId /*in*/ tokenId, ULONG /*in*/ offset, ULONG /*in*/ length, NIPB::VToken /*out*/ *token );
 | 
			
		||||
  static void          FormatUnsigned( NIPB::IPacketInspector *inspector, LPCTSTR label, NIPB::VTokenId tokenId, ULONG value, ULONG valueLength );
 | 
			
		||||
 | 
			
		||||
  static NIPB::VResult SetTokenUnsigned( NIPB::VProtocolToken &protocolToken, NIPB::VTokenId tokenId, ULONG valueLength, ULONG value );
 | 
			
		||||
  static NIPB::VResult SetTokenData( NIPB::VProtocolToken &protocolToken, NIPB::VTokenId tokenId, ULONG dataLength, const BYTE *data );
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Attributes
 | 
			
		||||
  //
 | 
			
		||||
private:
 | 
			
		||||
  NIPB::VTokenId          mProtocolId;      //!< Token ID of this protocol
 | 
			
		||||
  NIPB::VTokenId          mContentId;       //!< Token ID of the 'contentID' field
 | 
			
		||||
  NIPB::IProtocolManager *mProtocolManager;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,86 @@
 | 
			
		|||
/*-------------------------------------------------------------------
 | 
			
		||||
  VCSignalProtocolAddOn.h
 | 
			
		||||
  -------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  (c) Vector Informatik GmbH. All rights reserved.
 | 
			
		||||
 | 
			
		||||
  ------------------------------------------------------------------- */ 
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "VCSignalProtocolAddOn.h"
 | 
			
		||||
#include "VCSignalProtocol.h"
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
// Implementaiton of VCSignalProtocolAddOn
 | 
			
		||||
//
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
VCSignalProtocolAddOn *VCSignalProtocolAddOn::sInstance = NULL;
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------------
 | 
			
		||||
//!
 | 
			
		||||
/**
 | 
			
		||||
*/
 | 
			
		||||
VCSignalProtocolAddOn::VCSignalProtocolAddOn()
 | 
			
		||||
{
 | 
			
		||||
  sInstance = this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------------
 | 
			
		||||
//!
 | 
			
		||||
/**
 | 
			
		||||
*/
 | 
			
		||||
VCSignalProtocolAddOn& VCSignalProtocolAddOn::Instance()
 | 
			
		||||
{
 | 
			
		||||
  if (sInstance == 0) throw;
 | 
			
		||||
 | 
			
		||||
  return *sInstance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// IProtocolAddOn
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------------
 | 
			
		||||
//!
 | 
			
		||||
/**
 | 
			
		||||
*/
 | 
			
		||||
VDEF VCSignalProtocolAddOn::CreateProtocol( const char /*in*/ *protocolSymbol, NIPB::IProtocol /*out*/ **protocol )
 | 
			
		||||
{
 | 
			
		||||
  if (protocol       == 0) return NIPB::kInvalidArg;
 | 
			
		||||
  if (protocolSymbol == 0) return NIPB::kInvalidArg;
 | 
			
		||||
 | 
			
		||||
  *protocol = new VCSignalProtocol();
 | 
			
		||||
 | 
			
		||||
  return NIPB::kOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------------
 | 
			
		||||
//!
 | 
			
		||||
/**
 | 
			
		||||
*/
 | 
			
		||||
VDEF VCSignalProtocolAddOn::ReleaseProtocol( NIPB::IProtocol /*in*/ *protocol)
 | 
			
		||||
{
 | 
			
		||||
  VCSignalProtocol *prot = dynamic_cast<VCSignalProtocol*>( protocol );
 | 
			
		||||
  delete prot;
 | 
			
		||||
 | 
			
		||||
  return NIPB::kOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Public Methods
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------------
 | 
			
		||||
//!
 | 
			
		||||
/**
 | 
			
		||||
*/
 | 
			
		||||
void VCSignalProtocolAddOn::Release()
 | 
			
		||||
{
 | 
			
		||||
  delete this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
/*-------------------------------------------------------------------
 | 
			
		||||
  VCSignalProtocolAddOn.h
 | 
			
		||||
  -------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  (c) Vector Informatik GmbH. All rights reserved.
 | 
			
		||||
 | 
			
		||||
  ------------------------------------------------------------------- */ 
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Factory for the VCSignalProtocol
 | 
			
		||||
/*! 
 | 
			
		||||
    This class is registered at the NIPB::IAddOnRegistrar registrar. It
 | 
			
		||||
    is responsible to create a instance of the VCSignalProtocol, when needed.
 | 
			
		||||
*/
 | 
			
		||||
class VCSignalProtocolAddOn : 
 | 
			
		||||
  public NIPB::IProtocolAddOn
 | 
			
		||||
{
 | 
			
		||||
  //
 | 
			
		||||
  // Construction
 | 
			
		||||
  //
 | 
			
		||||
public:
 | 
			
		||||
  VCSignalProtocolAddOn();
 | 
			
		||||
 | 
			
		||||
  static VCSignalProtocolAddOn& Instance();
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // IProtocolAddOn
 | 
			
		||||
  //
 | 
			
		||||
public:
 | 
			
		||||
  VDECL CreateProtocol( const char /*in*/ *protocolSymbol, NIPB::IProtocol /*out*/ **protocol );
 | 
			
		||||
  VDECL ReleaseProtocol( NIPB::IProtocol /*in*/ *protocol);
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Methods
 | 
			
		||||
  //
 | 
			
		||||
public:
 | 
			
		||||
  void Release();
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Attributes
 | 
			
		||||
  //
 | 
			
		||||
private:
 | 
			
		||||
  static VCSignalProtocolAddOn *sInstance;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,69 @@
 | 
			
		|||
/*-------------------------------------------------------------------
 | 
			
		||||
  VCSignalProtocolDLL.cpp
 | 
			
		||||
  -------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  (c) 2009 Vector Informatik GmbH. All rights reserved.
 | 
			
		||||
 | 
			
		||||
  ------------------------------------------------------------------- */ 
 | 
			
		||||
 | 
			
		||||
#include "StdAfx.h"
 | 
			
		||||
#include "VCSignalProtocolDLL.h"
 | 
			
		||||
#include "VCSignalProtocolAddOn.h"
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Reply new ProtocolManager instance
 | 
			
		||||
/*! 
 | 
			
		||||
    This function is called on loading of this DLL by the IPB Packet API.
 | 
			
		||||
    It must register the protocol of this DLL.
 | 
			
		||||
*/
 | 
			
		||||
STDAPI DllRegisterAddOn( NIPB::IAddOnRegistrar* registrar )
 | 
			
		||||
{
 | 
			
		||||
  if (registrar == NULL)
 | 
			
		||||
  {
 | 
			
		||||
    return E_INVALIDARG;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // register the signal protocol at the IPB Packet Lib. For the protocol
 | 
			
		||||
  // UDP with source port 40001 is used.
 | 
			
		||||
  //
 | 
			
		||||
  if (registrar->RegisterProtocol( "vc-sig", new VCSignalProtocolAddOn(), "udp", 40001, 0xFFFFFFFF ) != NIPB::kOK)
 | 
			
		||||
  {
 | 
			
		||||
    VCSignalProtocolAddOn::Instance().Release();
 | 
			
		||||
    return NIPB::kError;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*--------------------------------------------------------------------*/
 | 
			
		||||
//! Return interface version
 | 
			
		||||
/*! 
 | 
			
		||||
    This DLL must support a proper version of the IBP Packet API.
 | 
			
		||||
*/
 | 
			
		||||
STDAPI DllGetApiVersion( unsigned long /*out*/*major, unsigned long /*out*/*minor, unsigned long /*out*/*structVersion )
 | 
			
		||||
{
 | 
			
		||||
  if (major)
 | 
			
		||||
  {
 | 
			
		||||
    *major = IPB_PACKET_LIB_INTERFACE_VERSION_MAJOR;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (minor)
 | 
			
		||||
  {
 | 
			
		||||
    *minor = IPB_PACKET_LIB_INTERFACE_VERSION_MINOR;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (structVersion)
 | 
			
		||||
  {
 | 
			
		||||
    *structVersion = IPB_PACKET_LIB_STRUCT_VERSION;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return S_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
; VCSignalProtocolDLL.def : Declares the module parameters.
 | 
			
		||||
 | 
			
		||||
LIBRARY      "VCSignalProtocolDLL.DLL"
 | 
			
		||||
 | 
			
		||||
EXPORTS
 | 
			
		||||
  DllGetApiVersion PRIVATE
 | 
			
		||||
  DllRegisterAddOn PRIVATE
 | 
			
		||||
							
								
								
									
										10
									
								
								Modbus-DLL/include/VCSignalProtocolDLL/VCSignalProtocolDLL.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Modbus-DLL/include/VCSignalProtocolDLL/VCSignalProtocolDLL.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
/*-------------------------------------------------------------------
 | 
			
		||||
  VCSignalProtocolDLL.h
 | 
			
		||||
  -------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  (c) 2009 Vector Informatik GmbH. All rights reserved.
 | 
			
		||||
 | 
			
		||||
  ------------------------------------------------------------------- */ 
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
 | 
			
		||||
Microsoft Visual Studio Solution File, Format Version 9.00
 | 
			
		||||
# Visual Studio 2005
 | 
			
		||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCSignalProtocolDLL", "VCSignalProtocolDLL.vcproj", "{0015F4D0-0830-408B-97FB-D9748FD43623}"
 | 
			
		||||
EndProject
 | 
			
		||||
Global
 | 
			
		||||
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 | 
			
		||||
		Debug|Win32 = Debug|Win32
 | 
			
		||||
		Release|Win32 = Release|Win32
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 | 
			
		||||
		{0015F4D0-0830-408B-97FB-D9748FD43623}.Debug|Win32.ActiveCfg = Debug|Win32
 | 
			
		||||
		{0015F4D0-0830-408B-97FB-D9748FD43623}.Debug|Win32.Build.0 = Debug|Win32
 | 
			
		||||
		{0015F4D0-0830-408B-97FB-D9748FD43623}.Release|Win32.ActiveCfg = Release|Win32
 | 
			
		||||
		{0015F4D0-0830-408B-97FB-D9748FD43623}.Release|Win32.Build.0 = Release|Win32
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(SolutionProperties) = preSolution
 | 
			
		||||
		HideSolutionNode = FALSE
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
EndGlobal
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,261 @@
 | 
			
		|||
<?xml version="1.0" encoding="Windows-1252"?>
 | 
			
		||||
<VisualStudioProject
 | 
			
		||||
	ProjectType="Visual C++"
 | 
			
		||||
	Version="8,00"
 | 
			
		||||
	Name="VCSignalProtocolDLL"
 | 
			
		||||
	ProjectGUID="{0015F4D0-0830-408B-97FB-D9748FD43623}"
 | 
			
		||||
	RootNamespace="VCSignalProtocolDLL"
 | 
			
		||||
	Keyword="ManagedCProj"
 | 
			
		||||
	>
 | 
			
		||||
	<Platforms>
 | 
			
		||||
		<Platform
 | 
			
		||||
			Name="Win32"
 | 
			
		||||
		/>
 | 
			
		||||
	</Platforms>
 | 
			
		||||
	<ToolFiles>
 | 
			
		||||
	</ToolFiles>
 | 
			
		||||
	<Configurations>
 | 
			
		||||
		<Configuration
 | 
			
		||||
			Name="Debug|Win32"
 | 
			
		||||
			OutputDirectory="debug"
 | 
			
		||||
			IntermediateDirectory="debug"
 | 
			
		||||
			ConfigurationType="2"
 | 
			
		||||
			CharacterSet="2"
 | 
			
		||||
			ManagedExtensions="0"
 | 
			
		||||
			>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCPreBuildEventTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCCustomBuildTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCXMLDataGeneratorTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCWebServiceProxyGeneratorTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCMIDLTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCCLCompilerTool"
 | 
			
		||||
				AdditionalOptions="/analyze"
 | 
			
		||||
				Optimization="0"
 | 
			
		||||
				AdditionalIncludeDirectories=".,source,common"
 | 
			
		||||
				PreprocessorDefinitions="WIN32;_DEBUG"
 | 
			
		||||
				RuntimeLibrary="3"
 | 
			
		||||
				UsePrecompiledHeader="2"
 | 
			
		||||
				WarningLevel="4"
 | 
			
		||||
				DebugInformationFormat="3"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCManagedResourceCompilerTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCResourceCompilerTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCPreLinkEventTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCLinkerTool"
 | 
			
		||||
				AdditionalDependencies="$(NoInherit)"
 | 
			
		||||
				OutputFile="..\VCSignalProtocol.dll"
 | 
			
		||||
				LinkIncremental="2"
 | 
			
		||||
				ModuleDefinitionFile="VCSignalProtocolDLL.def"
 | 
			
		||||
				GenerateDebugInformation="true"
 | 
			
		||||
				AssemblyDebug="1"
 | 
			
		||||
				TargetMachine="1"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCALinkTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCManifestTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCXDCMakeTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCBscMakeTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCFxCopTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCAppVerifierTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCWebDeploymentTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCPostBuildEventTool"
 | 
			
		||||
				CommandLine=""
 | 
			
		||||
			/>
 | 
			
		||||
		</Configuration>
 | 
			
		||||
		<Configuration
 | 
			
		||||
			Name="Release|Win32"
 | 
			
		||||
			OutputDirectory="release"
 | 
			
		||||
			IntermediateDirectory="release"
 | 
			
		||||
			ConfigurationType="2"
 | 
			
		||||
			CharacterSet="2"
 | 
			
		||||
			ManagedExtensions="0"
 | 
			
		||||
			WholeProgramOptimization="1"
 | 
			
		||||
			>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCPreBuildEventTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCCustomBuildTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCXMLDataGeneratorTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCWebServiceProxyGeneratorTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCMIDLTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCCLCompilerTool"
 | 
			
		||||
				AdditionalOptions="/analyze"
 | 
			
		||||
				AdditionalIncludeDirectories=".,source,common"
 | 
			
		||||
				PreprocessorDefinitions="WIN32;NDEBUG"
 | 
			
		||||
				RuntimeLibrary="2"
 | 
			
		||||
				UsePrecompiledHeader="2"
 | 
			
		||||
				WarningLevel="4"
 | 
			
		||||
				DebugInformationFormat="3"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCManagedResourceCompilerTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCResourceCompilerTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCPreLinkEventTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCLinkerTool"
 | 
			
		||||
				AdditionalDependencies="$(NoInherit)"
 | 
			
		||||
				OutputFile="..\VCSignalProtocol.dll"
 | 
			
		||||
				LinkIncremental="1"
 | 
			
		||||
				ModuleDefinitionFile="VCSignalProtocolDLL.def"
 | 
			
		||||
				GenerateDebugInformation="true"
 | 
			
		||||
				TargetMachine="1"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCALinkTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCManifestTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCXDCMakeTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCBscMakeTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCFxCopTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCAppVerifierTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCWebDeploymentTool"
 | 
			
		||||
			/>
 | 
			
		||||
			<Tool
 | 
			
		||||
				Name="VCPostBuildEventTool"
 | 
			
		||||
			/>
 | 
			
		||||
		</Configuration>
 | 
			
		||||
	</Configurations>
 | 
			
		||||
	<References>
 | 
			
		||||
		<AssemblyReference
 | 
			
		||||
			RelativePath="System.dll"
 | 
			
		||||
			AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
 | 
			
		||||
		/>
 | 
			
		||||
		<AssemblyReference
 | 
			
		||||
			RelativePath="System.Data.dll"
 | 
			
		||||
			AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"
 | 
			
		||||
		/>
 | 
			
		||||
		<AssemblyReference
 | 
			
		||||
			RelativePath="System.XML.dll"
 | 
			
		||||
			AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
 | 
			
		||||
		/>
 | 
			
		||||
	</References>
 | 
			
		||||
	<Files>
 | 
			
		||||
		<Filter
 | 
			
		||||
			Name="DLL"
 | 
			
		||||
			>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath=".\Stdafx.cpp"
 | 
			
		||||
				>
 | 
			
		||||
				<FileConfiguration
 | 
			
		||||
					Name="Debug|Win32"
 | 
			
		||||
					>
 | 
			
		||||
					<Tool
 | 
			
		||||
						Name="VCCLCompilerTool"
 | 
			
		||||
						UsePrecompiledHeader="1"
 | 
			
		||||
					/>
 | 
			
		||||
				</FileConfiguration>
 | 
			
		||||
				<FileConfiguration
 | 
			
		||||
					Name="Release|Win32"
 | 
			
		||||
					>
 | 
			
		||||
					<Tool
 | 
			
		||||
						Name="VCCLCompilerTool"
 | 
			
		||||
						UsePrecompiledHeader="1"
 | 
			
		||||
					/>
 | 
			
		||||
				</FileConfiguration>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath=".\Stdafx.h"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath=".\VCSignalProtocolDLL.cpp"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath=".\VCSignalProtocolDLL.def"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath=".\VCSignalProtocolDLL.h"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
		</Filter>
 | 
			
		||||
		<Filter
 | 
			
		||||
			Name="Protocol"
 | 
			
		||||
			>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath=".\VCSignalProtocol.cpp"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath=".\VCSignalProtocol.h"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath=".\VCSignalProtocolAddOn.cpp"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath=".\VCSignalProtocolAddOn.h"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
		</Filter>
 | 
			
		||||
		<Filter
 | 
			
		||||
			Name="Include"
 | 
			
		||||
			>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath=".\Include\IPBPacketAPI.h"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
		</Filter>
 | 
			
		||||
	</Files>
 | 
			
		||||
	<Globals>
 | 
			
		||||
	</Globals>
 | 
			
		||||
</VisualStudioProject>
 | 
			
		||||
		Loading…
	
		Reference in a new issue