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