Comments in MakeConfig.can

This commit is contained in:
Jonny007-MKD 2014-06-12 15:28:05 +00:00
parent 23e0b8af56
commit 57ea11238f

View file

@ -7,32 +7,32 @@ includes
variables variables
{ {
struct device struct device // A structure that contains information about an Modbus device
{ {
char Ip[16]; char Ip[16]; // String: The IP address
char IpLsb[4]; char IpLsb[4]; // String: The last byte of the IP address. Used as index of node name
char IpNet[4]; char IpNet[4]; // String: The second last byte of the IP. Used as index of net
enum Vendor Vendor; enum Vendor Vendor; // The Vendor (Wago / B&R)
word SerialCode; word SerialCode; // Serial Code
word DeviceCode; word DeviceCode; // Device Code
struct deviceIOs DeviceIOs; struct deviceIOs DeviceIOs; // A structure with more information about IOs
}; };
char[16] gIps[long]; char[16] gIps[long]; // List IP addresses. These will be analysed
char gScanFirstIp[16]; char gScanFirstIp[16]; // The first IP address that will be scanned
char gScanLastIp[16]; char gScanLastIp[16]; // The first IP address that will not be scanned anymore.
char fnSysvar[40]; // Filename of Sysvars char fnSysvar[40]; // Filename of Sysvars
char fnDbc[40]; // Filename of DBC char fnDbc[40]; // Filename of DBC
char name[20]; // Name of project char name[20]; // Name of project (not important)
dword ips[50]; // detected IPs dword ips[50]; // detected IPs. We need this array for enumeration with integers
file f; file f; // The file we are writing to
byte gIpNets[long]; byte gIpNets[long]; // A list of nets
struct device gIpsSorted[long]; struct device gIpsSorted[long]; // The final array with the devices
dword gScanFirst, gScanLast; dword gScanFirst, gScanLast; // The first and last IP address as dword
word ADi, ADn, ADl; word ADi, ADn, ADl; // Some variables for "AnalyzeDevices"
byte gMaxTransmissionCount; byte gMaxTransmissionCount;
} }
@ -47,13 +47,14 @@ on preStart
*/ */
// Scan a range of IPs for devices. Start and Stop go here // Scan a range of IPs for devices. Start and Stop go here
// Please note: Currelty .255 will be skipped! // Please note: Currently .255 will be skipped! Don't use it for devices and as stop address
strncpy(gScanFirstIp, "192.168.1.2", 16); strncpy(gScanFirstIp, "192.168.1.2", 16);
strncpy(gScanLastIp, "192.168.1.10", 16); strncpy(gScanLastIp, "192.168.1.10", 16);
// Name of the project // Name of the project
strncpy(name, "Modbus", elCount(name)); strncpy(name, "Modbus", elCount(name));
// Paths to the generated files relative to .cfg
// Paths to the generated files relative to MakeConfig.cfg
strncpy(fnSysvar, "include/SysVars/generated.vsysvar", elCount(fnSysvar)); strncpy(fnSysvar, "include/SysVars/generated.vsysvar", elCount(fnSysvar));
strncpy(fnDbc, "include/DBC/generated.dbc", elCount(fnDbc)); strncpy(fnDbc, "include/DBC/generated.dbc", elCount(fnDbc));
@ -62,28 +63,29 @@ on preStart
on start on start
{ {
gMaxTransmissionCount = @sysvar::Config::Modbus::MaxTransmissionCount; gMaxTransmissionCount = @sysvar::Config::Modbus::MaxTransmissionCount; // save the value
@sysvar::Config::Modbus::MaxTransmissionCount = 1; // and then don't retransmit
if (gIps.Size() == 0) if (gIps.Size() == 0) // if no IP address were specified
DetectDevices(); DetectDevices(); // scan network for devices (Step1)
else else
MakeIpNets(); MakeIpNets(); // else continue with Step2
} }
/// <PutString> /// <PutString>
void PutString(file f, char str[]) void PutString(char str[])
{ {
f.PutString(str, strlen(str)); f.PutString(str, strlen(str));
} }
/// <PutString> /// <PutString>
void PutString(file f, word d) void PutString(word d)
{ {
char str[6]; char str[6];
ltoa(d, str, 10); ltoa(d, str, 10);
f.PutString(str, strlen(str)); f.PutString(str, strlen(str));
} }
/// <PutString> /// <PutString>
void PutString(file f, byte d) void PutString(byte d)
{ {
char str[4]; char str[4];
ltoa(d, str, 10); ltoa(d, str, 10);
@ -91,94 +93,106 @@ void PutString(file f, byte d)
} }
// Step 1: Detect active devices and collect IP addresses // Step 1: Detect active devices and collect IP addresses
// This function will convert the IP address, open the socket and start the detection. The rest will be done by events
/// <Step1> /// <Step1>
void DetectDevices() void DetectDevices()
{ {
@sysvar::Config::Modbus::MaxTransmissionCount = 1;
write("Scanning from %s to %s with timeout of %d ms", gScanFirstIp, gScanLastIp, @sysvar::Config::Modbus::RequestTimeout); write("Scanning from %s to %s with timeout of %d ms", gScanFirstIp, gScanLastIp, @sysvar::Config::Modbus::RequestTimeout);
gScanFirst = ipGetAddressAsNumber(gScanFirstIp); gScanFirst = ipGetAddressAsNumber(gScanFirstIp);
gScanLast = ipGetAddressAsNumber(gScanLastIp); gScanLast = ipGetAddressAsNumber(gScanLastIp);
write("%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24); write("%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
ModbusConnectTo(gScanFirst, @sysvar::Config::Modbus::Port); ModbusConnectTo(gScanFirst, @sysvar::Config::Modbus::Port); // Open socket and set variables
ModbusReadBits(0, 1); ModbusReadBits(0, 1); // Start device detection
} }
// This function will increment the IP address and continue the detection
/// <Step1> /// <Step1>
void DetectDevicesNext() void DetectDevicesNext()
{ {
// next IP // next IP
// Note: IP address is stored as big endian, comments are notated as little endian :)
// 0xFE...... --> Skip xxx.xxx.xxx.255 which is broadcast address in 192.168.xxx.0 nets // 0xFE...... --> Skip xxx.xxx.xxx.255 which is broadcast address in 192.168.xxx.0 nets
// If first three bytes are full (123.255.255.255), set those to 0 and increment the first byte (124.0.0.0)
if ((gScanFirst & 0xFFFFFF00) == 0xFEFFFF00) if ((gScanFirst & 0xFFFFFF00) == 0xFEFFFF00)
{ {
gScanFirst &= 0x000000FF; gScanFirst &= 0x000000FF;
gScanFirst += 0x00000001; gScanFirst += 0x00000001;
write("%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24); write("%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
} }
// If first two bytes are full (124.111.255.255), set those to 0 and increment the second byte (124.112.0.0)
else if ((gScanFirst & 0xFFFF0000) == 0xFEFF0000) else if ((gScanFirst & 0xFFFF0000) == 0xFEFF0000)
{ {
gScanFirst &= 0x0000FFF; gScanFirst &= 0x0000FFF;
gScanFirst += 0x00000100; gScanFirst += 0x00000100;
write("%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24); write("%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
} }
// If first last byte is full (124.112.222.255), set it to 0 and increment the third byte (124.112.223.0)
else if ((gScanFirst & 0xFF000000) == 0xFE000000) else if ((gScanFirst & 0xFF000000) == 0xFE000000)
{ {
gScanFirst &= 0x00FFFFFF; gScanFirst &= 0x00FFFFFF;
gScanFirst += 0x00010000; gScanFirst += 0x00010000;
write("%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24); write("%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
} }
// Else simply increment the LSB
else else
{ {
gScanFirst += 0x01000000; gScanFirst += 0x01000000;
} }
if (gScanFirst == gScanLast)
if (gScanFirst == gScanLast) // If this is the last address we stop the detection
{ {
@sysvar::Config::Modbus::MaxTransmissionCount = gMaxTransmissionCount; @sysvar::Config::Modbus::MaxTransmissionCount = gMaxTransmissionCount;
MakeIpNets(); MakeIpNets();
return; return;
} }
writeEx(1, 1, ".");
gRemoteIP = gScanFirst; // Don't open new socket, it takes too much time. writeEx(1, 1, "."); // Write something so the user knows something is happening
ModbusReadBits(0, 1); gRemoteIP = gScanFirst; // Don't open new socket, it takes too much time. This means we should use UDP here!
ModbusReadBits(0, 1); // Scan the next device
} }
/// <Step1> /// <Step1>
void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
{ {
DetectDevicesNext(); DetectDevicesNext(); // Timeout! We will go to the next device
} }
/// <Step1> /// <Step1>
void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq) void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq)
{ {
ipGetAddressAsString(gScanFirst, gIps[gScanFirst], 16); ipGetAddressAsString(gScanFirst, gIps[gScanFirst], 16); // store the detected device's IP address
DetectDevicesNext(); DetectDevicesNext(); // and continue
} }
// Step 2: Sort into subnets
// Step 2: Sort into subnets and create structure
// Sort the IPs from gIps to gIpsSorted and add their subnet to gIpNets // Sort the IPs from gIps to gIpsSorted and add their subnet to gIpNets
/// <Step2> /// <Step2>
void MakeIpNets() void MakeIpNets()
{ {
long ipNum; long ipNum;
if (gIps.Size() == 0) if (gIps.Size() == 0) // If no devices were specified and detected
{ {
stop(); stop(); // Don't do anything
return; return;
} }
for (long i : gIps) for (long i : gIps) // Go through all devices
{ {
ipNum = ipGetAddressAsNumber(gIps[i]); // convert IP to dword ipNum = ipGetAddressAsNumber(gIps[i]); // convert IP to dword
gIpNets[(ipNum >> 16) & 0xFF] = 1; // add subnet gIpNets[(ipNum >> 16) & 0xFF] = 1; // register subnet
ips[gIpsSorted.size()] = ipNum; // add ip to array ips[gIpsSorted.size()] = ipNum; // add ip address to normal array
strncpy(gIpsSorted[ipNum].IP, gIps[i], 16); // copy to new array // fill the device structure array:
ltoa((ipNum >> 16) & 0xFF, gIpsSorted[ipNum].IpNet, 10); // add .IpNet strncpy(gIpsSorted[ipNum].IP, gIps[i], 16); // set .IP
ltoa((ipNum >> 24) & 0xFF, gIpsSorted[ipNum].IpLsb, 10); // add .IpLsb ltoa((ipNum >> 16) & 0xFF, gIpsSorted[ipNum].IpNet, 10); // set .IpNet
ltoa((ipNum >> 24) & 0xFF, gIpsSorted[ipNum].IpLsb, 10); // set .IpLsb
gIps.Remove(i); gIps.Remove(i);
} }
AnalyzeDevices(); AnalyzeDevices(); // Continue with step 3
} }
@ -186,21 +200,26 @@ void MakeIpNets()
/// <Step3> /// <Step3>
void AnalyzeDevices() void AnalyzeDevices()
{ {
ADn = 0; // Init counters
ADi = 0; ADn = 0; // Zero message received
ADi = 0; // First IP address
ADl = gIpsSorted.Size(); ADl = gIpsSorted.Size();
write("Analyzing %s...", gIpsSorted[ips[ADi]].Ip); write("Analyzing %s...", gIpsSorted[ips[ADi]].Ip);
gIpsSorted[ips[ADi]].Vendor = Wago; gIpsSorted[ips[ADi]].Vendor = Wago;
if (gRemoteIP != INVALID_IP)
gRemoteIP = ips[ADi]; if (gRemoteIP != INVALID_IP) // If we already do have a socket
else gRemoteIP = ips[ADi]; // use it
else // else create a new one
ModbusConnectTo(ips[ADi], @sysvar::Config::Modbus::Port); ModbusConnectTo(ips[ADi], @sysvar::Config::Modbus::Port);
ModbusReadRegisters(0x2011, 1);
ModbusReadRegisters(0x2012, 1); // read the important registers from the device
ModbusReadRegisters(0x2030, 65); ModbusReadRegisters(0x2011, 1); // Serial Code
ModbusReadRegisters(0x2031, 64); ModbusReadRegisters(0x2012, 1); // Device Code
ModbusReadRegisters(0x2032, 64); ModbusReadRegisters(0x2030, 65); // Connected IO 1
ModbusReadRegisters(0x2033, 63); ModbusReadRegisters(0x2031, 64); // Connected IO 2
ModbusReadRegisters(0x2032, 64); // Connected IO 3
ModbusReadRegisters(0x2033, 63); // Connected IO 4
} }
/// <Step3> /// <Step3>
@ -208,19 +227,19 @@ void AnalyzeDevicesNext()
{ {
if (++ADi >= ADl) // we have analyzed all devices if (++ADi >= ADl) // we have analyzed all devices
{ {
MakeFiles(); MakeFiles(); // go to Step4
return; return;
} }
ADn = 0; ADn = 0; // Zero message received
gRemoteIP = ips[ADi]; gRemoteIP = ips[ADi]; // Next IP address
write("Analyzing %s...", gIpsSorted[ips[ADi]].Ip); write("Analyzing %s...", gIpsSorted[ips[ADi]].Ip);
ModbusReadRegisters(0x2011, 1); ModbusReadRegisters(0x2011, 1); // Serial Code
ModbusReadRegisters(0x2012, 1); ModbusReadRegisters(0x2012, 1); // Device Code
ModbusReadRegisters(0x2030, 65); ModbusReadRegisters(0x2030, 65); // Connected IO 1
ModbusReadRegisters(0x2031, 64); ModbusReadRegisters(0x2031, 64); // Connected IO 2
ModbusReadRegisters(0x2032, 64); ModbusReadRegisters(0x2032, 64); // Connected IO 3
ModbusReadRegisters(0x2033, 63); ModbusReadRegisters(0x2033, 63); // Connected IO 4
} }
/// <Step3> /// <Step3>
@ -230,19 +249,19 @@ void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusExcep
{ {
case FinalTimeout: case FinalTimeout:
writeLineEx(0, 3, "Error while analyzing %s! The device did not respond! Ignoring...", gIpsSorted[ips[ADi]].IP); writeLineEx(0, 3, "Error while analyzing %s! The device did not respond! Ignoring...", gIpsSorted[ips[ADi]].IP);
gQueueAck.Clear(); gQueueAck.Clear(); // Clear all queues
gQueuePending.Clear(); gQueuePending.Clear();
gQueueSent.Clear(); gQueueSent.Clear();
gIpsSorted.Remove(ips[ADi]); gIpsSorted.Remove(ips[ADi]); // Remove the IP
AnalyzeDevicesNext(); AnalyzeDevicesNext(); // And go to the next device
break; break;
case Exception: case Exception:
writeLineEx(0, 3, "Error while analyzing %s! The device respond with exception code %d! Ignoring...", gIpsSorted[ips[ADi]].IP, ex); writeLineEx(0, 3, "Error while analyzing %s! The device respond with exception code %d! Ignoring...", gIpsSorted[ips[ADi]].IP, ex);
gQueueAck.Clear(); gQueueAck.Clear(); // Clear all queues
gQueuePending.Clear(); gQueuePending.Clear();
gQueueSent.Clear(); gQueueSent.Clear();
gIpsSorted.Remove(ips[ADi]); gIpsSorted.Remove(ips[ADi]); // Remove the IP
AnalyzeDevicesNext(); AnalyzeDevicesNext(); // And go to the next device
break; break;
} }
} }
@ -252,6 +271,7 @@ void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct
{ {
byte i; byte i;
// Parse the received data
switch (mbreq.Address) switch (mbreq.Address)
{ {
case 0x2011: case 0x2011:
@ -266,14 +286,14 @@ void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct
case 0x2033: case 0x2033:
for (i = 0; i < mbreq.Count; i++) for (i = 0; i < mbreq.Count; i++)
{ {
if (mbres.Data[i] == 0x0000) if (mbres.Data[i] == 0x0000) // No more devices --> end
break; break;
ParseDeviceCode(mbres.Data[i], gIpsSorted[ips[ADi]].Vendor, gIpsSorted[ips[ADi]].DeviceIOs); ParseDeviceCode(mbres.Data[i], gIpsSorted[ips[ADi]].Vendor, gIpsSorted[ips[ADi]].DeviceIOs);
} }
break; break;
} }
if (++ADn == 6) if (++ADn == 6) // If we received all registers (6 messages)
AnalyzeDevicesNext(); AnalyzeDevicesNext();
} }
@ -293,36 +313,36 @@ void GenSysvars()
write("GenSysvars() -> %s", fnSysvar); write("GenSysvars() -> %s", fnSysvar);
f.Open(fnSysvar, 0, 0); // rewrite file in ASCII f.Open(fnSysvar, 0, 0); // rewrite file in ASCII
PutString(f, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); PutString("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
PutString(f, "<systemvariables version=\"4\">\n"); PutString("<systemvariables version=\"4\">\n");
PutString(f, " <namespace name=\"\" comment=\"\">\n"); PutString(" <namespace name=\"\" comment=\"\">\n");
PutString(f, " <namespace name=\"Config\" comment=\"\">\n"); PutString(" <namespace name=\"Config\" comment=\"\">\n");
PutString(f, " <namespace name=\"Modbus\" comment=\"\">\n"); PutString(" <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(" <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((word)@sysvar::Config::Modbus::RequestTimeout);
PutString(f, "\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"1000\" maxValuePhys=\"1000\" />\n"); PutString("\" 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(" <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((word)@sysvar::Config::Modbus::Port);
PutString(f, "\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"65535\" maxValuePhys=\"65535\" />\n"); PutString("\" 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(" <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((byte)@sysvar::Config::Modbus::MaxTransmissionCount);
PutString(f, "\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10\" maxValuePhys=\"10\" />\n"); PutString("\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10\" maxValuePhys=\"10\" />\n");
PutString(f, " </namespace>\n"); PutString(" </namespace>\n");
PutString(f, " <namespace name=\"TcpIp\" comment=\"\">\n"); PutString(" <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(" <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(" </namespace>\n");
PutString(f, " </namespace>\n"); PutString(" </namespace>\n");
for (long net : gIpNets) for (long net : gIpNets)
{ {
byte nett; byte nett;
nett = net; nett = net;
PutString(f, " <namespace name=\"Ethernet"); PutString(" <namespace name=\"Ethernet");
PutString(f, nett); PutString(nett);
PutString(f, "\" comment=\"Subnet: 192.168."); PutString("\" comment=\"Subnet: 192.168.");
PutString(f, nett); PutString(nett);
PutString(f, ".\">\n"); PutString(".\">\n");
for (long ipN : gIpsSorted) for (long ipN : gIpsSorted)
{ {
@ -330,93 +350,93 @@ void GenSysvars()
if (((ipN >> 16) & 0xFF) != net) if (((ipN >> 16) & 0xFF) != net)
continue; continue;
PutString(f, " <namespace name=\"Client_"); PutString(" <namespace name=\"Client_");
//PutString(f, netS); //PutString(netS);
//PutString(f, "_"); //PutString("_");
PutString(f, gIpsSorted[ipN].IpLsb); PutString(gIpsSorted[ipN].IpLsb);
PutString(f, "\" comment=\"Server with ip address '"); PutString("\" comment=\"Server with ip address '");
PutString(f, gIpsSorted[ipN].Ip); PutString(gIpsSorted[ipN].Ip);
PutString(f, "'\">\n"); PutString("'\">\n");
// Namespace Config // Namespace Config
PutString(f, " <namespace name=\"Config\" comment=\"Configuration section for this server\">\n"); PutString(" <namespace name=\"Config\" comment=\"Configuration section for this server\">\n");
// IP // 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(" <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(gIpsSorted[ipN].Ip);
PutString(f, "\" />\n"); PutString("\" />\n");
// Intveral // 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(" <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"); PutString(" </namespace>\n");
//Namespace Info //Namespace Info
PutString(f, " <namespace name=\"Info\" comment=\"Some information about the device\">\n"); PutString(" <namespace name=\"Info\" comment=\"Some information about the device\">\n");
// Vendor // 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(" <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((byte)gIpsSorted[ipN].Vendor);
PutString(f, "\">\n"); PutString("\">\n");
PutString(f, " <valuetable definesMinMax=\"true\">\n"); PutString(" <valuetable definesMinMax=\"true\">\n");
PutString(f, " <valuetableentry value=\"2\" description=\"BuR\" />\n"); PutString(" <valuetableentry value=\"2\" description=\"BuR\" />\n");
PutString(f, " <valuetableentry value=\"23\" description=\"Wago\" />\n"); PutString(" <valuetableentry value=\"23\" description=\"Wago\" />\n");
PutString(f, " </valuetable>\n"); PutString(" </valuetable>\n");
PutString(f, " </variable>\n"); PutString(" </variable>\n");
// SerialCode // 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(" <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(gIpsSorted[ipN].SerialCode);
PutString(f, "\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10000\" maxValuePhys=\"10000\" />\n"); PutString("\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10000\" maxValuePhys=\"10000\" />\n");
// DeviceCode // 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(" <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(gIpsSorted[ipN].DeviceCode);
PutString(f, "\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10000\" maxValuePhys=\"10000\" />\n"); PutString("\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10000\" maxValuePhys=\"10000\" />\n");
// Modules // Modules
gIpsSorted[ipN].DeviceIOs.Modules[strlen(gIpsSorted[ipN].DeviceIOs.Modules)-1] = 0; 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(" <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(gIpsSorted[ipN].DeviceIOs.Modules);
PutString(f, "\" />\n"); PutString("\" />\n");
// InputRegisters // 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(" <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(gIpsSorted[ipN].DeviceIOs.InputRegisters);
PutString(f, "\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"123\" maxValuePhys=\"123\" />\n"); PutString("\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"123\" maxValuePhys=\"123\" />\n");
// InputBits // 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(" <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(gIpsSorted[ipN].DeviceIOs.InputBits);
PutString(f, "\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"2000\" maxValuePhys=\"2000\" />\n"); PutString("\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"2000\" maxValuePhys=\"2000\" />\n");
// OutputRegisters // 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(" <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(gIpsSorted[ipN].DeviceIOs.OutputRegisters);
PutString(f, "\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"123\" maxValuePhys=\"123\" />\n"); PutString("\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"123\" maxValuePhys=\"123\" />\n");
// OutputBits // 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(" <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(gIpsSorted[ipN].DeviceIOs.OutputBits);
PutString(f, "\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"2000\" maxValuePhys=\"2000\" />\n"); PutString("\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"2000\" maxValuePhys=\"2000\" />\n");
PutString(f, " </namespace>\n"); PutString(" </namespace>\n");
// Namespace Data // Namespace Data
PutString(f, " <namespace name=\"Data\" comment=\"The actual process image\">\n"); PutString(" <namespace name=\"Data\" comment=\"The actual process image\">\n");
// InputRegisters // 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(" <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(gIpsSorted[ipN].DeviceIOs.InputRegisters);
PutString(f, "\" />\n"); PutString("\" />\n");
// InputBits // 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(" <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(gIpsSorted[ipN].DeviceIOs.InputBits);
PutString(f, "\" />\n"); PutString("\" />\n");
// OutputRegisters // 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(" <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(gIpsSorted[ipN].DeviceIOs.OutputRegisters);
PutString(f, "\" />\n"); PutString("\" />\n");
// OutputBits // 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(" <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(gIpsSorted[ipN].DeviceIOs.OutputBits);
PutString(f, "\" />\n"); PutString("\" />\n");
PutString(f, " </namespace>\n"); PutString(" </namespace>\n");
PutString(f, " </namespace>\n"); PutString(" </namespace>\n");
} }
PutString(f, " </namespace>\n"); PutString(" </namespace>\n");
} }
PutString(f, " </namespace>\n"); PutString(" </namespace>\n");
PutString(f, "</systemvariables>\n"); PutString("</systemvariables>\n");
f.Close(); f.Close();
} }
@ -428,58 +448,58 @@ void GenDbc()
write("GenDbc() -> %s", fnDbc); write("GenDbc() -> %s", fnDbc);
f.Open(fnDbc, 0, 0); // rewrite file in ASCII f.Open(fnDbc, 0, 0); // rewrite file in ASCII
PutString(f, "VERSION \"\"\n\n\n"); PutString("VERSION \"\"\n\n\n");
PutString(f, "NS_ :\n"); PutString("NS_ :\n");
PutString(f, " NS_DESC_\n"); PutString(" NS_DESC_\n");
PutString(f, " CM_\n"); PutString(" CM_\n");
PutString(f, " BA_DEF_\n"); PutString(" BA_DEF_\n");
PutString(f, " BA_\n"); PutString(" BA_\n");
PutString(f, " VAL_\n"); PutString(" VAL_\n");
PutString(f, " CAT_DEF_\n"); PutString(" CAT_DEF_\n");
PutString(f, " CAT_\n"); PutString(" CAT_\n");
PutString(f, " FILTER\n"); PutString(" FILTER\n");
PutString(f, " BA_DEF_DEF_\n"); PutString(" BA_DEF_DEF_\n");
PutString(f, " EV_DATA_\n"); PutString(" EV_DATA_\n");
PutString(f, " ENVVAR_DATA_\n"); PutString(" ENVVAR_DATA_\n");
PutString(f, " SGTYPE_\n"); PutString(" SGTYPE_\n");
PutString(f, " SGTYPE_VAL_\n"); PutString(" SGTYPE_VAL_\n");
PutString(f, " BA_DEF_SGTYPE_\n"); PutString(" BA_DEF_SGTYPE_\n");
PutString(f, " BA_SGTYPE_\n"); PutString(" BA_SGTYPE_\n");
PutString(f, " SIG_TYPE_REF_\n"); PutString(" SIG_TYPE_REF_\n");
PutString(f, " VAL_TABLE_\n"); PutString(" VAL_TABLE_\n");
PutString(f, " SIG_GROUP_\n"); PutString(" SIG_GROUP_\n");
PutString(f, " SIG_VALTYPE_\n"); PutString(" SIG_VALTYPE_\n");
PutString(f, " SIGTYPE_VALTYPE_\n"); PutString(" SIGTYPE_VALTYPE_\n");
PutString(f, " BO_TX_BU_\n"); PutString(" BO_TX_BU_\n");
PutString(f, " BA_DEF_REL_\n"); PutString(" BA_DEF_REL_\n");
PutString(f, " BA_REL_\n"); PutString(" BA_REL_\n");
PutString(f, " BA_DEF_DEF_REL_\n"); PutString(" BA_DEF_DEF_REL_\n");
PutString(f, " BU_SG_REL_\n"); PutString(" BU_SG_REL_\n");
PutString(f, " BU_EV_REL_\n"); PutString(" BU_EV_REL_\n");
PutString(f, " BU_BO_REL_\n"); PutString(" BU_BO_REL_\n");
PutString(f, " SG_MUL_VAL_\n"); PutString(" SG_MUL_VAL_\n");
PutString(f, "\n"); PutString("\n");
PutString(f, "BS_:\n"); PutString("BS_:\n");
PutString(f, "\nBU_:"); PutString("\nBU_:");
for (long ipN : gIpsSorted) for (long ipN : gIpsSorted)
{ {
PutString(f, " Client_"); PutString(" Client_");
//PutString(f, gIpsSorted[ipN].IpNet); //PutString(gIpsSorted[ipN].IpNet);
//PutString(f, "_"); //PutString("_");
PutString(f, gIpsSorted[ipN].IpLsb); PutString(gIpsSorted[ipN].IpLsb);
} }
PutString(f, "\n\n\n\n"); PutString("\n\n\n\n");
PutString(f, "BA_DEF_ BU_ \"NodeLayerModules\" STRING ;\n"); PutString("BA_DEF_ BU_ \"NodeLayerModules\" STRING ;\n");
PutString(f, "BA_DEF_ \"DBName\" STRING ;\n"); PutString("BA_DEF_ \"DBName\" STRING ;\n");
PutString(f, "BA_DEF_ \"BusType\" STRING ;\n"); PutString("BA_DEF_ \"BusType\" STRING ;\n");
PutString(f, "BA_DEF_DEF_ \"NodeLayerModules\" \"Ethernet_IL.DLL\";\n"); PutString("BA_DEF_DEF_ \"NodeLayerModules\" \"Ethernet_IL.DLL\";\n");
PutString(f, "BA_DEF_DEF_ \"DBName\" \"\";\n"); PutString("BA_DEF_DEF_ \"DBName\" \"\";\n");
PutString(f, "BA_DEF_DEF_ \"BusType\" \"Ethernet\";\n"); PutString("BA_DEF_DEF_ \"BusType\" \"Ethernet\";\n");
PutString(f, "BA_ \"BusType\" \"Ethernet\";\n"); PutString("BA_ \"BusType\" \"Ethernet\";\n");
PutString(f, "BA_ \"DBName\" \""); PutString("BA_ \"DBName\" \"");
PutString(f, name); PutString(name);
PutString(f, "\";\n"); PutString("\";\n");
f.Close(); f.Close();
} }
@ -491,11 +511,12 @@ void GenDbc()
// The stuff below is not needed
/// <zzzModbus> /// <zzzModbus>
void OnModbusClientPanics(enum FatalErrors reason) void OnModbusClientPanics(enum FatalErrors reason)
{ {
writeLineEx(0, 4, "<%NODE_NAME%> FATAL! %d", reason); writeLineEx(0, 4, "<%NODE_NAME%> FATAL! %d", reason);
switch(reason) /* switch(reason)
{ {
case ParsingBuffer: case ParsingBuffer:
case ModbusPackageWasSplit: case ModbusPackageWasSplit:
@ -504,6 +525,7 @@ void OnModbusClientPanics(enum FatalErrors reason)
case ConnectionError: case ConnectionError:
break; break;
} }
*/
} }
/// <zzzModbus> /// <zzzModbus>
void OnModbusWriteBitFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap){} void OnModbusWriteBitFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap){}