Copied Modbus-CAPL and added VisualStudio project VCSignalProtocolDLL

This commit is contained in:
Jonny007-MKD 2014-05-28 09:20:38 +00:00
parent 41ba4a3fd5
commit f26088b1eb
36 changed files with 17624 additions and 0 deletions

4832
Modbus-DLL/MakeConfig.cfg Normal file

File diff suppressed because it is too large Load diff

7343
Modbus-DLL/ModbusNet.cfg Normal file

File diff suppressed because it is too large Load diff

View 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){}

Binary file not shown.

View 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");
}

Binary file not shown.

Binary file not shown.

View 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;
}

View 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);
}

View 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();
}
}

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<breakpoints>
<breakpoint Active="true" HaltsSimulation="true" AbsoluteLine="352" Function="" RelativeLine="9" />
</breakpoints>

View 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);
}
}

View 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));
}

View 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
};
}

View 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();
}

View 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();
}

View 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();
}

View 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];
}

View 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();
}

View 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";

View 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,

View 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";

View 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,

View 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>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,9 @@
/*-------------------------------------------------------------------
StdAfx.cpp
-------------------------------------------------------------------
(c) 2009 Vector Informatik GmbH. All rights reserved.
------------------------------------------------------------------- */
#include "StdAfx.h"

View 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"

View 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, &eth )) != 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;
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

View 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;
};
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

View file

@ -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;
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

View file

@ -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;
};
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

View file

@ -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;
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

View file

@ -0,0 +1,7 @@
; VCSignalProtocolDLL.def : Declares the module parameters.
LIBRARY "VCSignalProtocolDLL.DLL"
EXPORTS
DllGetApiVersion PRIVATE
DllRegisterAddOn PRIVATE

View file

@ -0,0 +1,10 @@
/*-------------------------------------------------------------------
VCSignalProtocolDLL.h
-------------------------------------------------------------------
(c) 2009 Vector Informatik GmbH. All rights reserved.
------------------------------------------------------------------- */
#pragma once

View file

@ -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

View file

@ -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>