Rename generated.dbc and generated.vsysvar into Modbus.*
DeviceInformation.cin struct device now contains all 4 bytes of the IP as fields MakeConfig.can Improved code and comments MakeConfig.can PollingModbusClient.can Removed the subnetting stuff. We simply can add the net to the node name
This commit is contained in:
parent
c181aa857b
commit
eb6d28c71b
7 changed files with 228 additions and 223 deletions
|
@ -1,14 +1,4 @@
|
|||
/*@!Encoding:1252*/
|
||||
includes
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
variables
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
on sysvar sysvar::Airbus::ESS_DC1
|
||||
{
|
||||
if (@this)
|
||||
|
|
|
@ -8,25 +8,25 @@ includes
|
|||
|
||||
variables
|
||||
{
|
||||
char[16] gIps[long]; // List IP addresses. These will be analysed
|
||||
char[16] gIps[long]; // List of IP addresses. These will be analysed
|
||||
char gScanFirstIp[16]; // The first IP address that will be scanned
|
||||
char gScanLastIp[16]; // The first IP address that will not be scanned anymore.
|
||||
char gScanLastIp[16]; // The first IP address that will be scanned
|
||||
byte skip255; // Whether the IP address .255 (broadcast in /24 nets) shall be skipped
|
||||
|
||||
char fnSysvar[40]; // Filename of Sysvars
|
||||
char fnDbc[40]; // Filename of DBC
|
||||
char name[20]; // Name of project (not important)
|
||||
dword ips[50]; // detected IPs. We need this array for enumeration with integers
|
||||
char fnSysvar[100]; // Filename of Sysvars
|
||||
char fnDbc[100]; // Filename of DBC
|
||||
dword ips[50]; // detected IPs. We need this array for enumeration with integers (assoc. arrays cannot be enumerated with integers :( )
|
||||
|
||||
|
||||
file f; // The file we are writing to
|
||||
byte gIpNets[long]; // A list of nets
|
||||
struct device gIpsSorted[long]; // The final array with the devices
|
||||
dword gScanFirst, gScanLast; // The first and last IP address as dword
|
||||
word ADi, ADn, ADl; // Some variables for "AnalyzeDevices"
|
||||
dword gScanCurr, gScanLast; // The first and last IP address as dword
|
||||
word ADi, ADn, ADl; // Some variables for AnalyzeDevices() (event driven, so global)
|
||||
|
||||
byte ggMaxTransmissionCount;
|
||||
byte useThirdIpByteForNames; // Whether the third byte of the IP address shall be used in the node name
|
||||
byte skip255; // Whether the IP address .255 (broadcast in /24) shall be skipped
|
||||
byte ggMaxTransmissionCount; // temp var for gMaxTransmissionCount
|
||||
|
||||
enum eNodeName {WholeIP, LastByte, TwoLastBytes, ThreeLastBytes}
|
||||
enum eNodeName NodeNameStyle; // The style of the node name
|
||||
}
|
||||
|
||||
on preStart
|
||||
|
@ -35,25 +35,23 @@ on preStart
|
|||
// List of IPs of devices goes here
|
||||
///strncpy(gIps[i++], "192.168.1.100", elCount(gIps));
|
||||
///strncpy(gIps[i++], "192.168.1.101", elCount(gIps));
|
||||
///strncpy(gIps[i++], "192.168.100.2", elCount(gIps));
|
||||
///strncpy(gIps[i++], "192.168.1.8", elCount(gIps));
|
||||
|
||||
// Scan a range of IPs for devices (if nothing was set above). Start and Stop go here
|
||||
// Please note: Currently .255 will be skipped! Don't use this address for devices
|
||||
strncpy(gScanFirstIp, "192.168.1.2", elCount(gScanFirstIp));
|
||||
strncpy(gScanLastIp, "192.168.1.255", elCount(gScanLastIp));
|
||||
|
||||
// Whether the third byte of the IP address shall be used in the node name
|
||||
useThirdIpByteForNames = 0;
|
||||
// How the Node name shall be formatted
|
||||
// LastByte: 192.168.12.34 --> Client_34
|
||||
// TwoLastBytes: 192.168.12.34 --> Client_12_34
|
||||
// ThreeLastBytes: 192.168.12.34 --> Client_168_12_34
|
||||
// WholeIp: 192.168.12.34 --> Client_192_168_12_34
|
||||
NodeNameStyle = LastByte;
|
||||
// Whether the IP address .255 (broadcast in /24) shall be skipped
|
||||
skip255 = 1;
|
||||
|
||||
// Name of the project
|
||||
strncpy(name, "Modbus", elCount(name));
|
||||
|
||||
// Paths to the generated files relative to MakeConfig.cfg
|
||||
strncpy(fnSysvar, "include/SysVars/generated.vsysvar", elCount(fnSysvar));
|
||||
strncpy(fnDbc, "include/DBC/generated.dbc", elCount(fnDbc));
|
||||
strncpy(fnSysvar, "include/SysVars/Modbus.vsysvar", elCount(fnSysvar));
|
||||
strncpy(fnDbc, "include/DBC/Modbus.dbc", elCount(fnDbc));
|
||||
|
||||
OutputDebugLevel = Error;
|
||||
}
|
||||
|
@ -96,10 +94,10 @@ void DetectDevices()
|
|||
{
|
||||
writeLineEx(0, 1, "Scanning from %s to %s with timeout of %d ms", gScanFirstIp, gScanLastIp, @sysvar::Config::Modbus::RequestTimeout);
|
||||
|
||||
gScanFirst = ipGetAddressAsNumber(gScanFirstIp); // We have to use big endian here
|
||||
gScanCurr = ipGetAddressAsNumber(gScanFirstIp); // We have to use big endian here
|
||||
gScanLast = swapDWord(ipGetAddressAsNumber(gScanLastIp)); // But not here :)
|
||||
|
||||
writeLineEx(0, 0, "%d.%d.%d.%d ", gScanFirst & 0xFF, (gScanFirst >> 8) & 0xFF, (gScanFirst >> 16) & 0xFF, gScanFirst >> 24);
|
||||
writeLineEx(0, 0, "%d.%d.%d.%d ", gScanCurr & 0xFF, (gScanCurr >> 8) & 0xFF, (gScanCurr >> 16) & 0xFF, gScanCurr >> 24);
|
||||
ModbusInit(gScanFirstIp, @sysvar::Config::Modbus::Port, @sysvar::Config::Modbus::RequestTimeout, 1); // Open socket and set variables
|
||||
ModbusReadBits(0, 1); // Start device detection
|
||||
}
|
||||
|
@ -107,46 +105,43 @@ void DetectDevices()
|
|||
/// <Step1>
|
||||
void DetectDevicesNext()
|
||||
{
|
||||
gScanFirst = swapDWord(gScanFirst);
|
||||
gScanFirst++;
|
||||
if (skip255 && (gScanFirst & 0xFF) == 0xFF) // skip .255
|
||||
gScanCurr = swapDWord(gScanCurr); // Swap to increment
|
||||
gScanCurr++; // Increment
|
||||
if ((gScanCurr & 0xFF) == 0xFF) // If .255
|
||||
{
|
||||
gScanFirst++;
|
||||
writeLineEx(0, 0, "%d.%d.%d.%d ", gScanFirst >> 24, (gScanFirst >> 16) & 0xFF, (gScanFirst >> 8) & 0xFF, gScanFirst & 0xFF);
|
||||
}
|
||||
else if (!skip255 && (gScanFirst & 0xFF) == 0x00)
|
||||
{
|
||||
writeLineEx(0, 0, "%d.%d.%d.%d ", gScanFirst >> 24, (gScanFirst >> 16) & 0xFF, (gScanFirst >> 8) & 0xFF, gScanFirst & 0xFF);
|
||||
if (skip255) // If we shall skip .255
|
||||
gScanCurr++;
|
||||
writeLineEx(0, 0, "%d.%d.%d.%d ", gScanCurr >> 24, (gScanCurr >> 16) & 0xFF, (gScanCurr >> 8) & 0xFF, gScanCurr & 0xFF);
|
||||
}
|
||||
|
||||
if (gScanFirst > gScanLast)
|
||||
if (gScanCurr > gScanLast) // If we are beyond the last ip address
|
||||
{
|
||||
@sysvar::Config::Modbus::MaxTransmissionCount = ggMaxTransmissionCount;
|
||||
MakeIpNets();
|
||||
@sysvar::Config::Modbus::MaxTransmissionCount = ggMaxTransmissionCount; // reset
|
||||
MakeIpNets(); // Continue with Step 2
|
||||
return;
|
||||
}
|
||||
|
||||
gScanFirst = swapDWord(gScanFirst);
|
||||
gScanCurr = swapDWord(gScanCurr); // Swap back
|
||||
|
||||
writeEx(0, 0, "."); // Write something so the user knows something is happening
|
||||
gRemoteIP = gScanFirst; // Don't open new socket, it takes too much time. This means we should use UDP here!
|
||||
gRemoteIP = gScanCurr; // Don't open new socket, it takes too much time. This means we should use UDP or EIL here!
|
||||
ModbusReadBits(0, 1); // Scan the next device
|
||||
}
|
||||
/// <Step1>
|
||||
void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
|
||||
{
|
||||
DetectDevicesNext(); // Timeout, NotSent, Exception! We will go to the next device
|
||||
DetectDevicesNext(); // Timeout, NotSent or Exception! We will go to the next device
|
||||
}
|
||||
/// <Step1>
|
||||
void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq)
|
||||
{
|
||||
ipGetAddressAsString(gScanFirst, gIps[gScanFirst], 16); // store the detected device's IP address
|
||||
ipGetAddressAsString(gScanCurr, gIps[gScanCurr], 16); // store the detected device's IP address
|
||||
DetectDevicesNext(); // and continue
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
/// <Step2>
|
||||
void MakeIpNets()
|
||||
{
|
||||
|
@ -159,16 +154,17 @@ void MakeIpNets()
|
|||
return;
|
||||
}
|
||||
|
||||
for (long i : gIps) // Go through all devices
|
||||
for (long i : gIps) // Iterate all devices
|
||||
{
|
||||
ipNum = ipGetAddressAsNumber(gIps[i]); // convert IP to dword
|
||||
|
||||
gIpNets[(ipNum >> 16) & 0xFF] = 1; // register subnet
|
||||
ips[gIpsSorted.size()] = ipNum; // add ip address to normal array
|
||||
// fill the device structure array:
|
||||
strncpy(gIpsSorted[ipNum].IP, gIps[i], 16); // set .IP
|
||||
ltoa((ipNum >> 16) & 0xFF, gIpsSorted[ipNum].IpNet, 10); // set .IpNet
|
||||
ltoa((ipNum >> 24) & 0xFF, gIpsSorted[ipNum].IpLsb, 10); // set .IpLsb
|
||||
ltoa((ipNum ) & 0xFF, gIpsSorted[ipNum].Ip1, 10); // set .Ip1
|
||||
ltoa((ipNum >> 8) & 0xFF, gIpsSorted[ipNum].Ip2, 10); // set .Ip2
|
||||
ltoa((ipNum >> 16) & 0xFF, gIpsSorted[ipNum].Ip3, 10); // set .Ip3
|
||||
ltoa((ipNum >> 24) & 0xFF, gIpsSorted[ipNum].Ip4, 10); // set .Ip4
|
||||
|
||||
gIps.Remove(i);
|
||||
}
|
||||
|
@ -182,7 +178,7 @@ void MakeIpNets()
|
|||
void AnalyzeDevices()
|
||||
{
|
||||
// Init counters
|
||||
ADn = 1; // expect 10 responses
|
||||
ADn = 1; // expect 1 response
|
||||
ADi = 0; // First IP address
|
||||
ADl = gIpsSorted.Size();
|
||||
|
||||
|
@ -203,17 +199,19 @@ void AnalyzeDevices()
|
|||
/// <Step3>
|
||||
void AnalyzeDevicesNext()
|
||||
{
|
||||
if (strlen(gIpsSorted[ips[ADi]].DeviceIOs.Modules) > 0)
|
||||
gIpsSorted[ips[ADi]].DeviceIOs.Modules[strlen(gIpsSorted[ips[ADi]].DeviceIOs.Modules)-1] = 0;
|
||||
// clean up the string of the previous devices
|
||||
if (strlen(gIpsSorted[ips[ADi]].DeviceIOs.Modules) > 0) // If we do have some Modules in this string
|
||||
gIpsSorted[ips[ADi]].DeviceIOs.Modules[strlen(gIpsSorted[ips[ADi]].DeviceIOs.Modules)-1] = 0; // Remove the last comma (set the char to NUL)
|
||||
// print the result
|
||||
writeEx(0, 1, ": AOs: %d, AIs: %d, DOs: %d, DIs: %d --> %s", gIpsSorted[ips[ADi]].DeviceIOs.OutputRegisters, gIpsSorted[ips[ADi]].DeviceIOs.InputRegisters, gIpsSorted[ips[ADi]].DeviceIOs.OutputBits, gIpsSorted[ips[ADi]].DeviceIOs.InputBits, gIpsSorted[ips[ADi]].DeviceIOs.Modules);
|
||||
|
||||
if (++ADi >= ADl) // we have analyzed all devices
|
||||
if (++ADi >= ADl) // continue with the next device. If we have analyzed all devices
|
||||
{
|
||||
MakeFiles(); // go to Step4
|
||||
return;
|
||||
}
|
||||
|
||||
ADn = 1; // expect 10 responses
|
||||
ADn = 1; // expect 1 response again
|
||||
gRemoteIP = ips[ADi]; // Next IP address
|
||||
writeLineEx(0, 1, "Analyzing %s", gIpsSorted[ips[ADi]].Ip);
|
||||
// request something special to get the vendor
|
||||
|
@ -226,12 +224,10 @@ void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusExcep
|
|||
|
||||
switch (error)
|
||||
{
|
||||
case Timeout:
|
||||
return;
|
||||
case Exception:
|
||||
memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer);
|
||||
|
||||
if (mbreq.Address == 0x1000 && ex == IllegalDataAddress) // We requested Wago SerialCode and it didn't work --> Not Wago --> B&R. Not future proof
|
||||
if (mbreq.Address == 0x1000 && ex == IllegalDataAddress) // We requested B&R MAC and it didn't work --> Not B&R --> Wago. Not future proof :(
|
||||
{
|
||||
gIpsSorted[ips[ADi]].Vendor = Wago;
|
||||
// request information
|
||||
|
@ -241,6 +237,8 @@ void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusExcep
|
|||
|
||||
writeLineEx(0, 3, "Error while analyzing %s! The device respond with exception code %d! Ignoring...", gIpsSorted[ips[ADi]].IP, ex);
|
||||
break;
|
||||
case Timeout:
|
||||
return; // Timeout is unimportant, it means the request will be resent
|
||||
case FinalTimeout:
|
||||
writeLineEx(0, 3, "Error while analyzing %s! The device did not respond! Ignoring...", gIpsSorted[ips[ADi]].IP);
|
||||
break;
|
||||
|
@ -261,7 +259,7 @@ void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusExcep
|
|||
/// <Step3>
|
||||
void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq)
|
||||
{
|
||||
if (mbreq.Address == 0x1000) // We detected a B&R device
|
||||
if (mbreq.Address == 0x1000) // We detected a B&R device (from MAC address)
|
||||
{
|
||||
gIpsSorted[ips[ADi]].Vendor = BuR;
|
||||
|
||||
|
@ -270,10 +268,11 @@ void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct
|
|||
return;
|
||||
}
|
||||
|
||||
// else parse the received data
|
||||
_DeviceParseRegister(gIpsSorted[ips[ADi]], mbreq.Address, mbres.Data, mbreq.Count);
|
||||
|
||||
if (--ADn == 0) // If we received all registers
|
||||
AnalyzeDevicesNext();
|
||||
if (--ADn == 0) // If we received all registers
|
||||
AnalyzeDevicesNext(); // Continue with the next device
|
||||
}
|
||||
|
||||
// Step 4: Create the files with the queried data
|
||||
|
@ -313,123 +312,126 @@ void GenSysvars()
|
|||
PutString(" </namespace>\n");
|
||||
PutString(" </namespace>\n");
|
||||
|
||||
for (long net : gIpNets)
|
||||
PutString(" <namespace name=\"Ethernet\" comment=\"\">\n");
|
||||
|
||||
for (long ipN : gIpsSorted)
|
||||
{
|
||||
byte nett;
|
||||
nett = net;
|
||||
PutString(" <namespace name=\"Ethernet");
|
||||
PutString(nett);
|
||||
PutString("\" comment=\"Subnet: 192.168.");
|
||||
PutString(nett);
|
||||
PutString(".\">\n");
|
||||
if ((ipN >> 16) & 0xFF != net) // This IP does not belong to the current net
|
||||
continue;
|
||||
DeviceInit(gIpsSorted[ipN].Vendor);
|
||||
|
||||
for (long ipN : gIpsSorted)
|
||||
{
|
||||
if (((ipN >> 16) & 0xFF) != net)
|
||||
continue;
|
||||
DeviceInit(gIpsSorted[ipN].Vendor);
|
||||
|
||||
PutString(" <namespace name=\"Client_");
|
||||
if (useThirdIpByteForNames)
|
||||
{
|
||||
PutString(gIpsSorted[ipN].IpNet);
|
||||
PutString(" <namespace name=\"Client_");
|
||||
switch (NodeNameStyle) // Add the IP bytes depending on the style. Don't break anywhere.
|
||||
{
|
||||
case WholeIp:
|
||||
PutString(gIpsSorted[ipN].Ip1);
|
||||
PutString("_");
|
||||
}
|
||||
PutString(gIpsSorted[ipN].IpLsb);
|
||||
PutString("\" comment=\"Server with ip address '");
|
||||
PutString(gIpsSorted[ipN].Ip);
|
||||
PutString("'\">\n");
|
||||
case ThreeLastBytes:
|
||||
PutString(gIpsSorted[ipN].Ip2);
|
||||
PutString("_");
|
||||
case TwoLastBytes:
|
||||
PutString(gIpsSorted[ipN].Ip3);
|
||||
PutString("_");
|
||||
case LastByte:
|
||||
PutString(gIpsSorted[ipN].Ip4);
|
||||
return;
|
||||
default:
|
||||
writeDbg(MbError, "The NodeNameStyle %d is unknown, please use a value of the enum!", NodeNameStyle);
|
||||
runError(1001, 0);
|
||||
break;
|
||||
}
|
||||
PutString("\" comment=\"Server with ip address '");
|
||||
PutString(gIpsSorted[ipN].Ip);
|
||||
PutString("'\">\n");
|
||||
|
||||
// Namespace Config
|
||||
PutString(" <namespace name=\"Config\" comment=\"Configuration section for this server\">\n");
|
||||
// IP
|
||||
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(gIpsSorted[ipN].Ip);
|
||||
PutString("\" />\n");
|
||||
// Intveral
|
||||
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(" </namespace>\n");
|
||||
// Namespace Config
|
||||
PutString(" <namespace name=\"Config\" comment=\"Configuration section for this server\">\n");
|
||||
// IP
|
||||
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(gIpsSorted[ipN].Ip);
|
||||
PutString("\" />\n");
|
||||
// Intveral
|
||||
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(" </namespace>\n");
|
||||
|
||||
//Namespace Info
|
||||
PutString(" <namespace name=\"Info\" comment=\"Some information about the device\">\n");
|
||||
// Vendor
|
||||
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((byte)gIpsSorted[ipN].Vendor);
|
||||
PutString("\">\n");
|
||||
PutString(" <valuetable definesMinMax=\"true\">\n");
|
||||
PutString(" <valuetableentry value=\"2\" description=\"BuR\" />\n");
|
||||
PutString(" <valuetableentry value=\"23\" description=\"Wago\" />\n");
|
||||
PutString(" </valuetable>\n");
|
||||
PutString(" </variable>\n");
|
||||
// SerialCode
|
||||
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(gIpsSorted[ipN].SerialCode);
|
||||
PutString("\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10000\" maxValuePhys=\"10000\" />\n");
|
||||
// DeviceCode
|
||||
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(gIpsSorted[ipN].DeviceCode);
|
||||
PutString("\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10000\" maxValuePhys=\"10000\" />\n");
|
||||
// Modules
|
||||
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(gIpsSorted[ipN].DeviceIOs.Modules);
|
||||
PutString("\" />\n");
|
||||
// InputRegisters
|
||||
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(gIpsSorted[ipN].DeviceIOs.InputRegisters);
|
||||
PutString("\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"");
|
||||
PutString((word)thisDev.MaxRegisterCount);
|
||||
PutString("\" maxValuePhys=\"");
|
||||
PutString((word)thisDev.MaxRegisterCount);
|
||||
PutString("\" />\n");
|
||||
// InputBits
|
||||
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(gIpsSorted[ipN].DeviceIOs.InputBits);
|
||||
PutString("\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"");
|
||||
PutString((word)thisDev.MaxBitCount);
|
||||
PutString("\" maxValuePhys=\"");
|
||||
PutString((word)thisDev.MaxBitCount);
|
||||
PutString("\" />\n");
|
||||
// OutputRegisters
|
||||
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(gIpsSorted[ipN].DeviceIOs.OutputRegisters);
|
||||
PutString("\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"");
|
||||
PutString((word)thisDev.MaxRegisterCount);
|
||||
PutString("\" maxValuePhys=\"");
|
||||
PutString((word)thisDev.MaxRegisterCount);
|
||||
PutString("\" />\n");
|
||||
// OutputBits
|
||||
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(gIpsSorted[ipN].DeviceIOs.OutputBits);
|
||||
PutString("\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"");
|
||||
PutString((word)thisDev.MaxBitCount);
|
||||
PutString("\" maxValuePhys=\"");
|
||||
PutString((word)thisDev.MaxBitCount);
|
||||
PutString("\" />\n");
|
||||
PutString(" </namespace>\n");
|
||||
//Namespace Info
|
||||
PutString(" <namespace name=\"Info\" comment=\"Some information about the device\">\n");
|
||||
// Vendor
|
||||
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((byte)gIpsSorted[ipN].Vendor);
|
||||
PutString("\">\n");
|
||||
PutString(" <valuetable definesMinMax=\"true\">\n");
|
||||
PutString(" <valuetableentry value=\"2\" description=\"BuR\" />\n");
|
||||
PutString(" <valuetableentry value=\"23\" description=\"Wago\" />\n");
|
||||
PutString(" </valuetable>\n");
|
||||
PutString(" </variable>\n");
|
||||
// SerialCode
|
||||
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(gIpsSorted[ipN].SerialCode);
|
||||
PutString("\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10000\" maxValuePhys=\"10000\" />\n");
|
||||
// DeviceCode
|
||||
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(gIpsSorted[ipN].DeviceCode);
|
||||
PutString("\" minValue=\"1\" minValuePhys=\"1\" maxValue=\"10000\" maxValuePhys=\"10000\" />\n");
|
||||
// Modules
|
||||
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(gIpsSorted[ipN].DeviceIOs.Modules);
|
||||
PutString("\" />\n");
|
||||
// InputRegisters
|
||||
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(gIpsSorted[ipN].DeviceIOs.InputRegisters);
|
||||
PutString("\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"");
|
||||
PutString((word)thisDev.MaxRegisterCount);
|
||||
PutString("\" maxValuePhys=\"");
|
||||
PutString((word)thisDev.MaxRegisterCount);
|
||||
PutString("\" />\n");
|
||||
// InputBits
|
||||
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(gIpsSorted[ipN].DeviceIOs.InputBits);
|
||||
PutString("\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"");
|
||||
PutString((word)thisDev.MaxBitCount);
|
||||
PutString("\" maxValuePhys=\"");
|
||||
PutString((word)thisDev.MaxBitCount);
|
||||
PutString("\" />\n");
|
||||
// OutputRegisters
|
||||
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(gIpsSorted[ipN].DeviceIOs.OutputRegisters);
|
||||
PutString("\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"");
|
||||
PutString((word)thisDev.MaxRegisterCount);
|
||||
PutString("\" maxValuePhys=\"");
|
||||
PutString((word)thisDev.MaxRegisterCount);
|
||||
PutString("\" />\n");
|
||||
// OutputBits
|
||||
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(gIpsSorted[ipN].DeviceIOs.OutputBits);
|
||||
PutString("\" minValue=\"0\" minValuePhys=\"0\" maxValue=\"");
|
||||
PutString((word)thisDev.MaxBitCount);
|
||||
PutString("\" maxValuePhys=\"");
|
||||
PutString((word)thisDev.MaxBitCount);
|
||||
PutString("\" />\n");
|
||||
PutString(" </namespace>\n");
|
||||
|
||||
// Namespace Data
|
||||
PutString(" <namespace name=\"Data\" comment=\"The actual process image\">\n");
|
||||
// InputRegisters
|
||||
PutString(" <variable anlyzLocal=\"2\" readOnly=\"false\" valueSequence=\"false\" unit=\"\" name=\"InputRegisters\" comment=\"The values of the input registers\" bitcount=\"17\" isSigned=\"true\" encoding=\"65001\" type=\"intarray\" arrayLength=\"");
|
||||
PutString(gIpsSorted[ipN].DeviceIOs.InputRegisters);
|
||||
PutString("\" />\n");
|
||||
// InputBits
|
||||
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(gIpsSorted[ipN].DeviceIOs.InputBits);
|
||||
PutString("\" />\n");
|
||||
// OutputRegisters
|
||||
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=\"17\" isSigned=\"true\" encoding=\"65001\" type=\"intarray\" arrayLength=\"");
|
||||
PutString(gIpsSorted[ipN].DeviceIOs.OutputRegisters);
|
||||
PutString("\" />\n");
|
||||
// OutputBits
|
||||
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(gIpsSorted[ipN].DeviceIOs.OutputBits);
|
||||
PutString("\" />\n");
|
||||
// Namespace Data
|
||||
PutString(" <namespace name=\"Data\" comment=\"The actual process image\">\n");
|
||||
// InputRegisters
|
||||
PutString(" <variable anlyzLocal=\"2\" readOnly=\"false\" valueSequence=\"false\" unit=\"\" name=\"InputRegisters\" comment=\"The values of the input registers\" bitcount=\"17\" isSigned=\"true\" encoding=\"65001\" type=\"intarray\" arrayLength=\"");
|
||||
PutString(gIpsSorted[ipN].DeviceIOs.InputRegisters);
|
||||
PutString("\" />\n");
|
||||
// InputBits
|
||||
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(gIpsSorted[ipN].DeviceIOs.InputBits);
|
||||
PutString("\" />\n");
|
||||
// OutputRegisters
|
||||
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=\"17\" isSigned=\"true\" encoding=\"65001\" type=\"intarray\" arrayLength=\"");
|
||||
PutString(gIpsSorted[ipN].DeviceIOs.OutputRegisters);
|
||||
PutString("\" />\n");
|
||||
// OutputBits
|
||||
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(gIpsSorted[ipN].DeviceIOs.OutputBits);
|
||||
PutString("\" />\n");
|
||||
|
||||
PutString(" </namespace>\n");
|
||||
PutString(" </namespace>\n");
|
||||
}
|
||||
PutString(" </namespace>\n");
|
||||
PutString(" </namespace>\n");
|
||||
PutString(" </namespace>\n");
|
||||
}
|
||||
|
||||
PutString(" </namespace>\n");
|
||||
|
@ -482,12 +484,25 @@ void GenDbc()
|
|||
for (long ipN : gIpsSorted)
|
||||
{
|
||||
PutString(" Client_");
|
||||
if (useThirdIpByteForNames)
|
||||
{
|
||||
PutString(gIpsSorted[ipN].IpNet);
|
||||
PutString("_");
|
||||
}
|
||||
PutString(gIpsSorted[ipN].IpLsb);
|
||||
switch (NodeNameStyle) // Add the IP bytes depending on the style. Don't break anywhere.
|
||||
{
|
||||
case WholeIp:
|
||||
PutString(gIpsSorted[ipN].Ip1);
|
||||
PutString("_");
|
||||
case ThreeLastBytes:
|
||||
PutString(gIpsSorted[ipN].Ip2);
|
||||
PutString("_");
|
||||
case TwoLastBytes:
|
||||
PutString(gIpsSorted[ipN].Ip3);
|
||||
PutString("_");
|
||||
case LastByte:
|
||||
PutString(gIpsSorted[ipN].Ip4);
|
||||
break;
|
||||
default:
|
||||
writeDbg(MbError, "The NodeNameStyle %d is unknown, please use a value of the enum!", NodeNameStyle);
|
||||
runError(1001, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
PutString("\n\n\n\n");
|
||||
PutString("BA_DEF_ BU_ \"NodeLayerModules\" STRING ;\n");
|
||||
|
@ -497,9 +512,7 @@ void GenDbc()
|
|||
PutString("BA_DEF_DEF_ \"DBName\" \"\";\n");
|
||||
PutString("BA_DEF_DEF_ \"BusType\" \"Ethernet\";\n");
|
||||
PutString("BA_ \"BusType\" \"Ethernet\";\n");
|
||||
PutString("BA_ \"DBName\" \"");
|
||||
PutString(name);
|
||||
PutString("\";\n");
|
||||
PutString("BA_ \"DBName\" \"Modbus\";\n");
|
||||
|
||||
f.Close();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*@!Encoding:1252*/
|
||||
|
||||
// This file is the Modbus Client for Airbus CIDS
|
||||
// It automatically and periodically reads all input bits and registers and writes them to SysVars %BUSTYPE%%CHANNEL%::%NODE_NAME%::Data
|
||||
// It automatically and periodically reads all input bits and registers and writes them to SysVars %BUSTYPE%::%NODE_NAME%::Data
|
||||
// It also reacts on changes in the output SysVars and write those to the Modbus device.
|
||||
|
||||
includes
|
||||
|
@ -27,9 +27,9 @@ on preStart
|
|||
on start
|
||||
{
|
||||
char ip[16];
|
||||
sysGetVariableString("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config", "IP", ip, elCount(ip)); // Get IP address of device from sysvars config
|
||||
sysGetVariableString("%BUS_TYPE%::%NODE_NAME%::Config", "IP", ip, elCount(ip)); // Get IP address of device from sysvars config
|
||||
|
||||
DeviceInit(@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::Vendor); // Set all device specific parameters (Wago / B&R)
|
||||
DeviceInit(@sysvar::%BUS_TYPE%::%NODE_NAME%::Info::Vendor); // Set all device specific parameters (Wago / B&R)
|
||||
|
||||
writeDbg(MbInfo, "Connecting to %s:%d", ip, @sysvar::Config::Modbus::Port);
|
||||
ModbusInit(ip, @sysvar::Config::Modbus::Port, @sysvar::Config::Modbus::RequestTimeout, @sysvar::Config::Modbus::MaxTransmissionCount); // Connect to device. Opens socket and connection or what ever
|
||||
|
@ -37,11 +37,11 @@ on start
|
|||
if (gSocketState < CONNECTING) // We are not connecting and not connected
|
||||
return;
|
||||
|
||||
ModbusReadOutBits(thisDev.Addr.Read.OutputBits, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits); // Read the start status of the output bits
|
||||
ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters); // Read the start status of the output registers
|
||||
ModbusReadOutBits(thisDev.Addr.Read.OutputBits, @sysvar::%BUS_TYPE%::%NODE_NAME%::Info::OutputBits); // Read the start status of the output bits
|
||||
ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, @sysvar::%BUS_TYPE%::%NODE_NAME%::Info::OutputRegisters); // Read the start status of the output registers
|
||||
|
||||
if (@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval > 0) // Start the polling timer
|
||||
setTimerCyclic(gtRead, 1, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval);
|
||||
if (@sysvar::%BUS_TYPE%::%NODE_NAME%::Config::Interval > 0) // Start the polling timer
|
||||
setTimerCyclic(gtRead, 1, @sysvar::%BUS_TYPE%::%NODE_NAME%::Config::Interval);
|
||||
}
|
||||
|
||||
// Stop all transactions and close connection
|
||||
|
@ -72,10 +72,10 @@ void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException
|
|||
case NotSent:
|
||||
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");
|
||||
sysBeginVariableStructUpdate("%BUS_TYPE%::%NODE_NAME%::Data", "InputBits");
|
||||
for (i = 0; i < @sysvar::%BUS_TYPE%::%NODE_NAME%::Info::InputBits; i++)
|
||||
@sysvar::%BUS_TYPE%::%NODE_NAME%::Data::InputBits[i] = -1;
|
||||
sysEndVariableStructUpdate("%BUS_TYPE%::%NODE_NAME%::Data", "InputBits");
|
||||
break;
|
||||
default:
|
||||
writeDbg(MbError, "OnModbusReadBitsFailed: Unkown error: %d", error);
|
||||
|
@ -96,10 +96,10 @@ void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusExcep
|
|||
case NotSent:
|
||||
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");
|
||||
sysBeginVariableStructUpdate("%BUS_TYPE%::%NODE_NAME%::Data", "InputRegisters");
|
||||
for (i = 0; i < @sysvar::%BUS_TYPE%::%NODE_NAME%::Info::InputRegisters; i++)
|
||||
@sysvar::%BUS_TYPE%::%NODE_NAME%::Data::InputRegisters[i] = -1;
|
||||
sysEndVariableStructUpdate("%BUS_TYPE%::%NODE_NAME%::Data", "InputRegisters");
|
||||
break;
|
||||
default:
|
||||
writeDbg(MbError, "OnModbusReadBitsFailed: Unkown error: %d", error);
|
||||
|
@ -134,24 +134,24 @@ void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[]
|
|||
switch (mbres.Header.FuncCode) // We assume that we separate between 0x01 and 0x02 even though the address space may be the same
|
||||
{
|
||||
case ReadBitsOut: // Read output bits
|
||||
sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
|
||||
sysBeginVariableStructUpdate("%BUS_TYPE%::%NODE_NAME%::Data", "OutputBits");
|
||||
|
||||
offset = mbreq.Address - thisDev.Addr.Read.OutputBits; // Get the offset to the base output bit address
|
||||
for (i = 0; i < mbreq.Count; i++)
|
||||
@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits[i + offset] = bitStatus[i];
|
||||
@sysvar::%BUS_TYPE%::%NODE_NAME%::Data::OutputBits[i + offset] = bitStatus[i];
|
||||
|
||||
sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits");
|
||||
sysEndVariableStructUpdate("%BUS_TYPE%::%NODE_NAME%::Data", "OutputBits");
|
||||
break;
|
||||
|
||||
|
||||
case ReadBitsIn: // Read input bits
|
||||
sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits");
|
||||
sysBeginVariableStructUpdate("%BUS_TYPE%::%NODE_NAME%::Data", "InputBits");
|
||||
|
||||
offset = mbreq.Address - thisDev.Addr.Read.InputBits; // Get the offset to the base input bit address
|
||||
for (i = 0; i < mbreq.Count; i++)
|
||||
@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputBits[i + offset] = bitStatus[i];
|
||||
@sysvar::%BUS_TYPE%::%NODE_NAME%::Data::InputBits[i + offset] = bitStatus[i];
|
||||
|
||||
sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits");
|
||||
sysEndVariableStructUpdate("%BUS_TYPE%::%NODE_NAME%::Data", "InputBits");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -169,24 +169,24 @@ void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct
|
|||
switch (mbres.Header.FuncCode) // We assume that we separate between 0x03 and 0x04 even though the address space may be the same
|
||||
{
|
||||
case ReadRegistersOut: // Read output registers
|
||||
sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputRegisters");
|
||||
sysBeginVariableStructUpdate("%BUS_TYPE%::%NODE_NAME%::Data", "OutputRegisters");
|
||||
|
||||
offset = mbreq.Address - thisDev.Addr.Read.OutputRegisters; // Get the offset to the base output register address
|
||||
for (i = 0; i < mbreq.Count; i++)
|
||||
@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters[i + offset] = mbres.Data[i];
|
||||
@sysvar::%BUS_TYPE%::%NODE_NAME%::Data::OutputRegisters[i + offset] = mbres.Data[i];
|
||||
|
||||
sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputRegisters");
|
||||
sysEndVariableStructUpdate("%BUS_TYPE%::%NODE_NAME%::Data", "OutputRegisters");
|
||||
break;
|
||||
|
||||
|
||||
case ReadRegistersIn: // Read input registers
|
||||
sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters");
|
||||
sysBeginVariableStructUpdate("%BUS_TYPE%::%NODE_NAME%::Data", "InputRegisters");
|
||||
|
||||
offset = mbreq.Address - thisDev.Addr.Read.InputRegisters; // Get the offset to the base input bit address
|
||||
for (i = 0; i < mbreq.Count; i++)
|
||||
@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputRegisters[i + offset] = mbres.Data[i];
|
||||
@sysvar::%BUS_TYPE%::%NODE_NAME%::Data::InputRegisters[i + offset] = mbres.Data[i];
|
||||
|
||||
sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters");
|
||||
sysEndVariableStructUpdate("%BUS_TYPE%::%NODE_NAME%::Data", "InputRegisters");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -250,38 +250,38 @@ void OnModbusClientPanics(enum FatalErrors reason)
|
|||
// The timer will continuously poll the input registers and intput bits
|
||||
on timer gtRead
|
||||
{
|
||||
ModbusReadRegisters(thisDev.Addr.Read.InputRegisters, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters);
|
||||
ModbusReadBits(thisDev.Addr.Read.InputBits, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputBits);
|
||||
ModbusReadRegisters(thisDev.Addr.Read.InputRegisters, @sysvar::%BUS_TYPE%::%NODE_NAME%::Info::InputRegisters);
|
||||
ModbusReadBits(thisDev.Addr.Read.InputBits, @sysvar::%BUS_TYPE%::%NODE_NAME%::Info::InputBits);
|
||||
}
|
||||
|
||||
// If Data::OutputBits is changed we will send this update to the device
|
||||
on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits
|
||||
on sysvar %BUS_TYPE%::%NODE_NAME%::Data::OutputBits
|
||||
{
|
||||
word count, i;
|
||||
byte bitStatus[1968];
|
||||
|
||||
count = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits;
|
||||
count = @sysvar::%BUS_TYPE%::%NODE_NAME%::Info::OutputBits;
|
||||
|
||||
for (i = 0; i < count; i++) // Copy the data from SysVars to byte[]
|
||||
bitStatus[i] = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits[i];
|
||||
bitStatus[i] = @sysvar::%BUS_TYPE%::%NODE_NAME%::Data::OutputBits[i];
|
||||
|
||||
ModbusWriteBitsB(0, count, bitStatus); // Send update command
|
||||
}
|
||||
// If Data::OutputRergisters is changed we will send this update to the device
|
||||
on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters
|
||||
on sysvar %BUS_TYPE%::%NODE_NAME%::Data::OutputRegisters
|
||||
{
|
||||
word count, i;
|
||||
word regValues[123];
|
||||
|
||||
count = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters;
|
||||
count = @sysvar::%BUS_TYPE%::%NODE_NAME%::Info::OutputRegisters;
|
||||
|
||||
for (i = 0; i < count; i++) // Copy the data from SysVars to word[]
|
||||
regValues[i] = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters[i];
|
||||
regValues[i] = @sysvar::%BUS_TYPE%::%NODE_NAME%::Data::OutputRegisters[i];
|
||||
|
||||
ModbusWriteRegisters(0, count, regValues); // Send update command
|
||||
}
|
||||
// Config::Interval is changed we will update the timer gtRead accordingly
|
||||
on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval
|
||||
on sysvar %BUS_TYPE%::%NODE_NAME%::Config::Interval
|
||||
{
|
||||
if (@this <= 0)
|
||||
gtRead.Cancel();
|
||||
|
|
|
@ -53,8 +53,10 @@ variables
|
|||
struct device // A structure that contains information about an Modbus device. Used in MakeConfig.
|
||||
{
|
||||
char Ip[16]; // String: The IP address
|
||||
char IpLsb[4]; // String: The last byte of the IP address. Used as index of node name
|
||||
char IpNet[4]; // String: The second last byte of the IP. Used as index of net
|
||||
char Ip4[4]; // String: The last byte of the IP address.
|
||||
char Ip3[4]; // String: The third byte of the IP.
|
||||
char Ip2[4]; // String: The second byte of the IP.
|
||||
char Ip1[4]; // String: Thefirst byte of the IP.
|
||||
enum Vendor Vendor; // The Vendor (Wago / B&R)
|
||||
word SerialCode; // Serial Code
|
||||
word DeviceCode; // Device Code
|
||||
|
|
Loading…
Reference in a new issue