From 6125015cc5b332253fcbffe743644c815fb9db22 Mon Sep 17 00:00:00 2001 From: Jonny007-MKD Date: Tue, 23 Sep 2014 09:48:47 +0000 Subject: [PATCH] Converted tabs to spaces. I still think tabs are better :P --- Modbus-CAPL/include/CAPL/IdleModbusClient.can | 98 +- Modbus-CAPL/include/CAPL/MakeConfig.can | 774 +++++----- .../include/CAPL/PollingModbusClient.can | 312 ++-- Modbus-CAPL/include/CAPL/TestTheStack.can | 1170 +++++++-------- Modbus-CAPL/include/CAPL/include/Common.cin | 382 ++--- .../CAPL/include/DeviceInformation.cin | 568 ++++---- .../include/CAPL/include/ModbusClient.cin | 1286 ++++++++--------- .../include/CAPL/include/ModbusEil.cin | 286 ++-- .../include/CAPL/include/ModbusStructs.cin | 340 ++--- .../include/CAPL/include/ModbusTcp.cin | 310 ++-- .../include/CAPL/include/ModbusUdp.cin | 238 +-- .../include/CAPL/include/TcpUdpEilCommon.cin | 26 +- Modbus-DLL/include/CAPL/MakeConfig.can | 742 +++++----- Modbus-DLL/include/CAPL/ModbusClient.can | 268 ++-- Modbus-DLL/include/CAPL/include/Common.cin | 324 ++--- Modbus-DLL/include/CAPL/include/EilCommon.cin | 220 +-- .../include/CAPL/include/EilDllCommon.cin | 220 +-- .../CAPL/include/ModbusClientCommon.cin | 838 +++++------ .../CAPL/include/ModbusClientCommon.cin_0.brp | 4 - .../CAPL/include/ModbusEilClientCommon.cin | 56 +- .../CAPL/include/ModbusEilDllClientCommon.cin | 50 +- .../include/CAPL/include/ModbusFunctions.cin | 146 +- .../include/CAPL/include/ModbusStructs.cin | 256 ++-- .../include/CAPL/include/TcpUdpCommon.cin | 22 +- 24 files changed, 4466 insertions(+), 4470 deletions(-) delete mode 100644 Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin_0.brp diff --git a/Modbus-CAPL/include/CAPL/IdleModbusClient.can b/Modbus-CAPL/include/CAPL/IdleModbusClient.can index 7949da5..0547653 100644 --- a/Modbus-CAPL/include/CAPL/IdleModbusClient.can +++ b/Modbus-CAPL/include/CAPL/IdleModbusClient.can @@ -4,9 +4,9 @@ includes { - #include "include\ModbusUdp.cin" // Use UDP as Layer 4 - #include "include\ModbusClient.cin" // Use Modbus as Application Layer - #include "include\DeviceInformation.cin" // Handle several vendors differently + #include "include\ModbusUdp.cin" // Use UDP as Layer 4 + #include "include\ModbusClient.cin" // Use Modbus as Application Layer + #include "include\DeviceInformation.cin" // Handle several vendors differently } variables @@ -16,43 +16,43 @@ variables on preStart { - writeClear(0); // Clear write window in CANoe - setStartdelay(10); // Wait for Ethernet device to be ready - OutputDebugLevel = Error; // The debug level (messages in write window) + writeClear(0); // Clear write window in CANoe + setStartdelay(10); // Wait for Ethernet device to be ready + OutputDebugLevel = Error; // The debug level (messages in write window) } // Connect to Modbus server, read the status of output registers and bits and start the cyclic timer on start { - char ip[16]; - sysGetVariableString("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config", "IP", ip, elCount(ip)); // Get IP address of device from sysvars config + char ip[16]; + sysGetVariableString("%BUS_TYPE%%CHANNEL%::%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%%CHANNEL%::%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 + 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 - if (gSocketState < CONNECTING) // We are not connecting and not connected - return; + if (gSocketState < CONNECTING) // We are not connecting and not connected + return; - //ModbusReadRegisters(0x1083, 1); + //ModbusReadRegisters(0x1083, 1); } // Stop all transactions and close connection on preStop { - ModbusEnd(); + ModbusEnd(); } // Modbus events ---------------------------------------------------------------------- -/// All these events will be called by functions out of ModbusClientCommon.cin +/// All these events will be called by functions out of ModbusClientCommon.cin // -- Modbus Failures ----------------------------------------------------------------- -/// Several reasons are possible: -/// error == Timeout: The packet will be resent -/// error == FinalTimeout: The packet will not be resent -/// error == Exception: The client responded with an exception (which again can have several reasons, see enum ModbusException) +/// Several reasons are possible: +/// error == Timeout: The packet will be resent +/// error == FinalTimeout: The packet will not be resent +/// error == Exception: The client responded with an exception (which again can have several reasons, see enum ModbusException) // This method gets called when an error occured while trying to read some bits (ModbusReadBits()) void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap){} @@ -72,8 +72,8 @@ void OnModbusWriteBitsFailed(enum ModbusRequestError error, enum ModbusException void OnModbusWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap){} // -- Modbus Success ------------------------------------------------------------------ -/// These functions get called when a device responds that a request was fulfilled successfully -/// Normally the Reponse as well the Request will be handed over +/// These functions get called when a device responds that a request was fulfilled successfully +/// Normally the Reponse as well the Request will be handed over // This method gets called when some bits were read successfully. See 'bitStatus' for their values and 'mbreq.Address' for their start address @@ -81,7 +81,7 @@ void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[] // This method gets called when some bits were read successfully. See 'mbres.Data' for their values and 'mbreq.Address' for their start address void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq) { - writeLineEx(0, 1, "<%NODE_NAME%> 0x%04X = 0x%04X (%d)", mbreq.Address, mbres.Data[0], mbres.Data[0]); + writeLineEx(0, 1, "<%NODE_NAME%> 0x%04X = 0x%04X (%d)", mbreq.Address, mbres.Data[0], mbres.Data[0]); } // This method gets called when a bit was set successfully. void OnModbusWriteBitSuccess(struct ModbusResConfirmSingle mbres){} @@ -99,30 +99,30 @@ void OnModbusWriteMasksSuccess(struct ModbusResConfirmMasks mbres){} // It will pass as argument what happened. Please see the log (increase debug level in preStart) for more details. void OnModbusClientPanics(enum FatalErrors reason) { - switch(reason) - { - case ParsingBuffer: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error while parsing the received buffer"); - break; - case ModbusPackageWasSplit: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error while parsing the received buffer: The Modbus package was split", reason); - break; - case VendorIdUnknown: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: Vendor ID unknown"); - break; - case FuncCodeIncorrect: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: Function code is incorrect"); - break; - case AddressFailure: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: Start address is incorrect"); - break; - case ConnectionError: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Connection Error"); - break; - case SwitchArgumentInvalid: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: A argument of a switch statement is incorrect"); - break; - } - stop(); - runError(1001, reason); + switch(reason) + { + case ParsingBuffer: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error while parsing the received buffer"); + break; + case ModbusPackageWasSplit: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error while parsing the received buffer: The Modbus package was split", reason); + break; + case VendorIdUnknown: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: Vendor ID unknown"); + break; + case FuncCodeIncorrect: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: Function code is incorrect"); + break; + case AddressFailure: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: Start address is incorrect"); + break; + case ConnectionError: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Connection Error"); + break; + case SwitchArgumentInvalid: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: A argument of a switch statement is incorrect"); + break; + } + stop(); + runError(1001, reason); } \ No newline at end of file diff --git a/Modbus-CAPL/include/CAPL/MakeConfig.can b/Modbus-CAPL/include/CAPL/MakeConfig.can index 84bfa0e..362402f 100644 --- a/Modbus-CAPL/include/CAPL/MakeConfig.can +++ b/Modbus-CAPL/include/CAPL/MakeConfig.can @@ -1,90 +1,90 @@ /*@!Encoding:1252*/ includes { - #include "include/DeviceInformation.cin" - #include "include/ModbusUdp.cin" - #include "include/ModbusClient.cin" + #include "include/DeviceInformation.cin" + #include "include/ModbusUdp.cin" + #include "include/ModbusClient.cin" } variables { - 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 be scanned - byte skip255; // Whether the IP address .255 (broadcast in /24 nets) shall be skipped + 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 be scanned + byte skip255; // Whether the IP address .255 (broadcast in /24 nets) shall be skipped - 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 :( ) + 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 - struct device gIpsSorted[long]; // The final array with the devices - dword gScanCurr, gScanLast; // The first and last IP address as dword - word ADi, ADn, ADl; // Some variables for AnalyzeDevices() (event driven, so global) + file f; // The file we are writing to + struct device gIpsSorted[long]; // The final array with the devices + 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; // temp var for gMaxTransmissionCount + byte ggMaxTransmissionCount; // temp var for gMaxTransmissionCount - enum eNodeName {WholeIp, LastByte, TwoLastBytes, ThreeLastBytes}; - enum eNodeName NodeNameStyle; // The style of the node name + enum eNodeName {WholeIp, LastByte, TwoLastBytes, ThreeLastBytes}; + enum eNodeName NodeNameStyle; // The style of the node name } on preStart { - byte i = 0; - // 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)); + byte i = 0; + // 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)); - // Scan a range of IPs for devices (if nothing was set above). Start and Stop go here - strncpy(gScanFirstIp, "192.168.1.2", elCount(gScanFirstIp)); - strncpy(gScanLastIp, "192.168.1.255", elCount(gScanLastIp)); + // Scan a range of IPs for devices (if nothing was set above). Start and Stop go here + strncpy(gScanFirstIp, "192.168.1.2", elCount(gScanFirstIp)); + strncpy(gScanLastIp, "192.168.1.255", elCount(gScanLastIp)); - // 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; + // 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; - // Paths to the generated files relative to MakeConfig.cfg - strncpy(fnSysvar, "include/SysVars/Modbus.vsysvar", elCount(fnSysvar)); - strncpy(fnDbc, "include/DBC/Modbus.dbc", elCount(fnDbc)); + // Paths to the generated files relative to MakeConfig.cfg + strncpy(fnSysvar, "include/SysVars/Modbus.vsysvar", elCount(fnSysvar)); + strncpy(fnDbc, "include/DBC/Modbus.dbc", elCount(fnDbc)); - OutputDebugLevel = Error; + OutputDebugLevel = Error; } on start { - ggMaxTransmissionCount = @sysvar::Config::Modbus::MaxTransmissionCount; // save the value + ggMaxTransmissionCount = @sysvar::Config::Modbus::MaxTransmissionCount; // save the value - DeviceInit(All); - if (gIps.Size() == 0) // if no IP address were specified - DetectDevices(); // scan network for devices (Step1) - else - MakeIpNets(); // else continue with Step2 + DeviceInit(All); + if (gIps.Size() == 0) // if no IP address were specified + DetectDevices(); // scan network for devices (Step1) + else + MakeIpNets(); // else continue with Step2 } /// void PutString(char str[]) { - f.PutString(str, strlen(str)); + f.PutString(str, strlen(str)); } /// void PutString(word d) { - char str[6]; - ltoa(d, str, 10); - f.PutString(str, strlen(str)); + char str[6]; + ltoa(d, str, 10); + f.PutString(str, strlen(str)); } /// void PutString(byte d) { - char str[4]; - ltoa(d, str, 10); - f.PutString(str, strlen(str)); + char str[4]; + ltoa(d, str, 10); + f.PutString(str, strlen(str)); } // Step 1: Detect active devices and collect IP addresses @@ -92,51 +92,51 @@ void PutString(byte d) /// void DetectDevices() { - writeLineEx(0, 1, "Scanning from %s to %s with timeout of %d ms", gScanFirstIp, gScanLastIp, @sysvar::Config::Modbus::RequestTimeout); + writeLineEx(0, 1, "Scanning from %s to %s with timeout of %d ms", gScanFirstIp, gScanLastIp, @sysvar::Config::Modbus::RequestTimeout); - gScanCurr = ipGetAddressAsNumber(gScanFirstIp); // We have to use big endian here - gScanLast = swapDWord(ipGetAddressAsNumber(gScanLastIp)); // But not 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 ", 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 + 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 } // This function will increment the IP address and continue the detection /// void DetectDevicesNext() { - gScanCurr = swapDWord(gScanCurr); // Swap to increment - gScanCurr++; // Increment - if ((gScanCurr & 0xFF) == 0xFF) // If .255 - { - 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); - } + gScanCurr = swapDWord(gScanCurr); // Swap to increment + gScanCurr++; // Increment + if ((gScanCurr & 0xFF) == 0xFF) // If .255 + { + 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 (gScanCurr > gScanLast) // If we are beyond the last ip address - { - @sysvar::Config::Modbus::MaxTransmissionCount = ggMaxTransmissionCount; // reset - MakeIpNets(); // Continue with Step 2 - return; - } + if (gScanCurr > gScanLast) // If we are beyond the last ip address + { + @sysvar::Config::Modbus::MaxTransmissionCount = ggMaxTransmissionCount; // reset + MakeIpNets(); // Continue with Step 2 + return; + } - gScanCurr = swapDWord(gScanCurr); // Swap back + gScanCurr = swapDWord(gScanCurr); // Swap back - writeEx(0, 0, "."); // Write something so the user knows something is happening - 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 + writeEx(0, 0, "."); // Write something so the user knows something is happening + 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 } /// void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - DetectDevicesNext(); // Timeout, NotSent or Exception! We will go to the next device + DetectDevicesNext(); // Timeout, NotSent or Exception! We will go to the next device } /// void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq) { - ipGetAddressAsString(gScanCurr, gIps[gScanCurr], 16); // store the detected device's IP address - DetectDevicesNext(); // and continue + ipGetAddressAsString(gScanCurr, gIps[gScanCurr], 16); // store the detected device's IP address + DetectDevicesNext(); // and continue } @@ -145,31 +145,31 @@ void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[] /// void MakeIpNets() { - long ipNum; + long ipNum; - if (gIps.Size() == 0) // If no devices were specified and detected - { - writeDbg(MbError, "No devices found!"); - stop(); // Don't do anything - return; - } + if (gIps.Size() == 0) // If no devices were specified and detected + { + writeDbg(MbError, "No devices found!"); + stop(); // Don't do anything + return; + } - for (long i : gIps) // Iterate all devices - { - ipNum = ipGetAddressAsNumber(gIps[i]); // convert IP to dword + for (long i : gIps) // Iterate all devices + { + ipNum = ipGetAddressAsNumber(gIps[i]); // convert IP to dword - 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 ) & 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 + 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 ) & 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); - } + gIps.Remove(i); + } - AnalyzeDevices(); // Continue with step 3 + AnalyzeDevices(); // Continue with step 3 } @@ -177,341 +177,341 @@ void MakeIpNets() /// void AnalyzeDevices() { - // Init counters - ADn = 1; // expect 1 response - ADi = 0; // First IP address - ADl = gIpsSorted.Size(); + // Init counters + ADn = 1; // expect 1 response + ADi = 0; // First IP address + ADl = gIpsSorted.Size(); - writeLineEx(0, 1, "Analyzing %s", gIpsSorted[ips[ADi]].Ip); + writeLineEx(0, 1, "Analyzing %s", gIpsSorted[ips[ADi]].Ip); - if (gRemoteIP != INVALID_IP) // If we already do have a socket - gRemoteIP = ips[ADi]; // use it - else // else create a new one - _ModbusConnectTo(ips[ADi], @sysvar::Config::Modbus::Port); + if (gRemoteIP != INVALID_IP) // If we already do have a socket + gRemoteIP = ips[ADi]; // use it + else // else create a new one + _ModbusConnectTo(ips[ADi], @sysvar::Config::Modbus::Port); - // request something special to get the vendor - // since there is no common register that holds the vendor - // we have to send a request that only one device responds correctly. - // At 0x1000-0x1002 B&R devices return the MAC address, whereas Wago holds the WatchdogTime. - // As the watchdog time only consists of 1 word Wago will return a IllegalDataAddress exception (0x02) - ModbusReadRegisters(0x1000, 3); // Request B&R MAC address + // request something special to get the vendor + // since there is no common register that holds the vendor + // we have to send a request that only one device responds correctly. + // At 0x1000-0x1002 B&R devices return the MAC address, whereas Wago holds the WatchdogTime. + // As the watchdog time only consists of 1 word Wago will return a IllegalDataAddress exception (0x02) + ModbusReadRegisters(0x1000, 3); // Request B&R MAC address } /// void AnalyzeDevicesNext() { - // 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); + // 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) // continue with the next device. If we have analyzed all devices - { - MakeFiles(); // go to Step4 - return; - } + if (++ADi >= ADl) // continue with the next device. If we have analyzed all devices + { + MakeFiles(); // go to Step4 + return; + } - 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 - ModbusReadRegisters(0x1000, 3); // Request B&R MAC address + 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 + ModbusReadRegisters(0x1000, 3); // Request B&R MAC address } /// void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - struct ModbusReqRead mbreq; + struct ModbusReqRead mbreq; - switch (error) - { - case Exception: - memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); + switch (error) + { + case Exception: + memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); - 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 - ADn = _DeviceGetInformation(Wago); - return; - } + 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 + ADn = _DeviceGetInformation(Wago); + return; + } - 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; - case NotSent: - writeLineEx(0, 3, "Error while analyzing %s! The device was not available! Ignoring...", gIpsSorted[ips[ADi]].IP); - break; - default: - writeLineEx(0, 3, "OnModbusReadRegistersFailed: Unknown error: %d", error); - OnModbusClientPanics(SwitchArgumentInvalid); - return; - } - gQueueAck.Clear(); // Clear all queues - gQueuePending.Clear(); - gQueueSent.Clear(); - gIpsSorted.Remove(ips[ADi]); // Remove the IP - AnalyzeDevicesNext(); // And go to the next device + 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; + case NotSent: + writeLineEx(0, 3, "Error while analyzing %s! The device was not available! Ignoring...", gIpsSorted[ips[ADi]].IP); + break; + default: + writeLineEx(0, 3, "OnModbusReadRegistersFailed: Unknown error: %d", error); + OnModbusClientPanics(SwitchArgumentInvalid); + return; + } + gQueueAck.Clear(); // Clear all queues + gQueuePending.Clear(); + gQueueSent.Clear(); + gIpsSorted.Remove(ips[ADi]); // Remove the IP + AnalyzeDevicesNext(); // And go to the next device } /// void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq) { - if (mbreq.Address == 0x1000) // We detected a B&R device (from MAC address) - { - gIpsSorted[ips[ADi]].Vendor = BuR; + if (mbreq.Address == 0x1000) // We detected a B&R device (from MAC address) + { + gIpsSorted[ips[ADi]].Vendor = BuR; - // request further information - ADn = _DeviceGetInformation(BuR); - return; - } + // request further information + ADn = _DeviceGetInformation(BuR); + return; + } - // else parse the received data - _DeviceParseRegister(gIpsSorted[ips[ADi]], mbreq.Address, mbres.Data, mbreq.Count); + // else parse the received data + _DeviceParseRegister(gIpsSorted[ips[ADi]], mbreq.Address, mbres.Data, mbreq.Count); - if (--ADn == 0) // If we received all registers - AnalyzeDevicesNext(); // Continue with the next device + if (--ADn == 0) // If we received all registers + AnalyzeDevicesNext(); // Continue with the next device } // Step 4: Create the files with the queried data /// void MakeFiles() { - GenSysvars(); - GenDbc(); - stop(); + GenSysvars(); + GenDbc(); + stop(); } // Generate the SysVars XML /// void GenSysvars() { - writeLineEx(0, 1, "GenSysvars() -> %s", fnSysvar); - f.Open(fnSysvar, 0, 0); // rewrite file in ASCII + writeLineEx(0, 1, "GenSysvars() -> %s", fnSysvar); + f.Open(fnSysvar, 0, 0); // rewrite file in ASCII - PutString("\n"); - PutString("\n"); + PutString("\n"); + PutString("\n"); - PutString(" \n"); - PutString(" \n"); - PutString(" \n"); - PutString(" \n"); - PutString(" \n"); - PutString(" \n"); - PutString(" \n"); - PutString(" \n"); - PutString(" \n"); - PutString(" \n"); + PutString(" \n"); + PutString(" \n"); + PutString(" \n"); + PutString(" \n"); + PutString(" \n"); + PutString(" \n"); + PutString(" \n"); + PutString(" \n"); + PutString(" \n"); + PutString(" \n"); - PutString(" \n"); + PutString(" \n"); - for (long ipN : gIpsSorted) - { - DeviceInit(gIpsSorted[ipN].Vendor); + for (long ipN : gIpsSorted) + { + DeviceInit(gIpsSorted[ipN].Vendor); - PutString(" \n"); + PutString(" \n"); - // Namespace Config - PutString(" \n"); - // IP - PutString(" \n"); - // Intveral - PutString(" \n"); - PutString(" \n"); + // Namespace Config + PutString(" \n"); + // IP + PutString(" \n"); + // Intveral + PutString(" \n"); + PutString(" \n"); - //Namespace Info - PutString(" \n"); - // Vendor - PutString(" \n"); - PutString(" \n"); - PutString(" \n"); - PutString(" \n"); - PutString(" \n"); - PutString(" \n"); - // SerialCode - PutString(" \n"); - // DeviceCode - PutString(" \n"); - // Modules - PutString(" \n"); - // InputRegisters - PutString(" \n"); - // InputBits - PutString(" \n"); - // OutputRegisters - PutString(" \n"); - // OutputBits - PutString(" \n"); - PutString(" \n"); + //Namespace Info + PutString(" \n"); + // Vendor + PutString(" \n"); + PutString(" \n"); + PutString(" \n"); + PutString(" \n"); + PutString(" \n"); + PutString(" \n"); + // SerialCode + PutString(" \n"); + // DeviceCode + PutString(" \n"); + // Modules + PutString(" \n"); + // InputRegisters + PutString(" \n"); + // InputBits + PutString(" \n"); + // OutputRegisters + PutString(" \n"); + // OutputBits + PutString(" \n"); + PutString(" \n"); - // Namespace Data - PutString(" \n"); - // InputRegisters - PutString(" \n"); - // InputBits - PutString(" \n"); - // OutputRegisters - PutString(" \n"); - // OutputBits - PutString(" \n"); + // Namespace Data + PutString(" \n"); + // InputRegisters + PutString(" \n"); + // InputBits + PutString(" \n"); + // OutputRegisters + PutString(" \n"); + // OutputBits + PutString(" \n"); - PutString(" \n"); - PutString(" \n"); - } + PutString(" \n"); + PutString(" \n"); + } - PutString(" \n"); - PutString("\n"); - - f.Close(); + PutString(" \n"); + PutString("\n"); + + f.Close(); } // Generate the Database /// void GenDbc() { - writeLineEx(0, 1, "GenDbc() -> %s", fnDbc); - f.Open(fnDbc, 0, 0); // rewrite file in ASCII + writeLineEx(0, 1, "GenDbc() -> %s", fnDbc); + f.Open(fnDbc, 0, 0); // rewrite file in ASCII - PutString("VERSION \"\"\n\n\n"); - PutString("NS_ :\n"); - PutString(" NS_DESC_\n"); - PutString(" CM_\n"); - PutString(" BA_DEF_\n"); - PutString(" BA_\n"); - PutString(" VAL_\n"); - PutString(" CAT_DEF_\n"); - PutString(" CAT_\n"); - PutString(" FILTER\n"); - PutString(" BA_DEF_DEF_\n"); - PutString(" EV_DATA_\n"); - PutString(" ENVVAR_DATA_\n"); - PutString(" SGTYPE_\n"); - PutString(" SGTYPE_VAL_\n"); - PutString(" BA_DEF_SGTYPE_\n"); - PutString(" BA_SGTYPE_\n"); - PutString(" SIG_TYPE_REF_\n"); - PutString(" VAL_TABLE_\n"); - PutString(" SIG_GROUP_\n"); - PutString(" SIG_VALTYPE_\n"); - PutString(" SIGTYPE_VALTYPE_\n"); - PutString(" BO_TX_BU_\n"); - PutString(" BA_DEF_REL_\n"); - PutString(" BA_REL_\n"); - PutString(" BA_DEF_DEF_REL_\n"); - PutString(" BU_SG_REL_\n"); - PutString(" BU_EV_REL_\n"); - PutString(" BU_BO_REL_\n"); - PutString(" SG_MUL_VAL_\n"); - PutString("\n"); - PutString("BS_:\n"); - PutString("\nBU_:"); + PutString("VERSION \"\"\n\n\n"); + PutString("NS_ :\n"); + PutString(" NS_DESC_\n"); + PutString(" CM_\n"); + PutString(" BA_DEF_\n"); + PutString(" BA_\n"); + PutString(" VAL_\n"); + PutString(" CAT_DEF_\n"); + PutString(" CAT_\n"); + PutString(" FILTER\n"); + PutString(" BA_DEF_DEF_\n"); + PutString(" EV_DATA_\n"); + PutString(" ENVVAR_DATA_\n"); + PutString(" SGTYPE_\n"); + PutString(" SGTYPE_VAL_\n"); + PutString(" BA_DEF_SGTYPE_\n"); + PutString(" BA_SGTYPE_\n"); + PutString(" SIG_TYPE_REF_\n"); + PutString(" VAL_TABLE_\n"); + PutString(" SIG_GROUP_\n"); + PutString(" SIG_VALTYPE_\n"); + PutString(" SIGTYPE_VALTYPE_\n"); + PutString(" BO_TX_BU_\n"); + PutString(" BA_DEF_REL_\n"); + PutString(" BA_REL_\n"); + PutString(" BA_DEF_DEF_REL_\n"); + PutString(" BU_SG_REL_\n"); + PutString(" BU_EV_REL_\n"); + PutString(" BU_BO_REL_\n"); + PutString(" SG_MUL_VAL_\n"); + PutString("\n"); + PutString("BS_:\n"); + PutString("\nBU_:"); - for (long ipN : gIpsSorted) - { - PutString(" Client_"); - 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"); - PutString("BA_DEF_ \"DBName\" STRING ;\n"); - PutString("BA_DEF_ \"BusType\" STRING ;\n"); - PutString("BA_DEF_DEF_ \"NodeLayerModules\" \"Ethernet_IL.DLL\";\n"); - PutString("BA_DEF_DEF_ \"DBName\" \"\";\n"); - PutString("BA_DEF_DEF_ \"BusType\" \"Ethernet\";\n"); - PutString("BA_ \"BusType\" \"Ethernet\";\n"); - PutString("BA_ \"DBName\" \"Modbus\";\n"); + for (long ipN : gIpsSorted) + { + PutString(" Client_"); + 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"); + PutString("BA_DEF_ \"DBName\" STRING ;\n"); + PutString("BA_DEF_ \"BusType\" STRING ;\n"); + PutString("BA_DEF_DEF_ \"NodeLayerModules\" \"Ethernet_IL.DLL\";\n"); + PutString("BA_DEF_DEF_ \"DBName\" \"\";\n"); + PutString("BA_DEF_DEF_ \"BusType\" \"Ethernet\";\n"); + PutString("BA_ \"BusType\" \"Ethernet\";\n"); + PutString("BA_ \"DBName\" \"Modbus\";\n"); - f.Close(); + f.Close(); } @@ -525,16 +525,16 @@ void GenDbc() /// 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; - } + writeLineEx(0, 4, "<%NODE_NAME%> FATAL! %d", reason); +/* switch(reason) + { + case ParsingBuffer: + case ModbusPackageWasSplit: + case DeviceCodeUnknown: + case VendorIdUnknown: + case ConnectionError: + break; + } */ } /// diff --git a/Modbus-CAPL/include/CAPL/PollingModbusClient.can b/Modbus-CAPL/include/CAPL/PollingModbusClient.can index 9ceeae8..dffc5e7 100644 --- a/Modbus-CAPL/include/CAPL/PollingModbusClient.can +++ b/Modbus-CAPL/include/CAPL/PollingModbusClient.can @@ -6,106 +6,106 @@ includes { - #include "include\ModbusUdp.cin" // Use UDP as Layer 4 - #include "include\ModbusClient.cin" // Use Modbus as Application Layer - #include "include\DeviceInformation.cin" // Handle several vendors differently + #include "include\ModbusUdp.cin" // Use UDP as Layer 4 + #include "include\ModbusClient.cin" // Use Modbus as Application Layer + #include "include\DeviceInformation.cin" // Handle several vendors differently } variables { - msTimer gtRead; // The timer that keeps on polling all the time + msTimer gtRead; // The timer that keeps on polling all the time } on preStart { - writeClear(0); // Clear write window in CANoe - setStartdelay(10); // Wait for Ethernet device to be ready - OutputDebugLevel = Warning; // The debug level (messages in write window) + writeClear(0); // Clear write window in CANoe + setStartdelay(10); // Wait for Ethernet device to be ready + OutputDebugLevel = Warning; // The debug level (messages in write window) } // Connect to Modbus server, read the status of output registers and bits and start the cyclic timer on start { - char ip[16]; - sysGetVariableString("Modbus::%NODE_NAME%::Config", "IP", ip, elCount(ip)); // Get IP address of device from sysvars config + char ip[16]; + sysGetVariableString("Modbus::%NODE_NAME%::Config", "IP", ip, elCount(ip)); // Get IP address of device from sysvars config - DeviceInit(@sysvar::Modbus::%NODE_NAME%::Info::Vendor); // Set all device specific parameters (Wago / B&R) + DeviceInit(@sysvar::Modbus::%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 + 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 - if (gSocketState < CONNECTING) // We are not connecting and not connected - return; + if (gSocketState < CONNECTING) // We are not connecting and not connected + return; - ModbusReadOutBits(thisDev.Addr.Read.OutputBits, @sysvar::Modbus::%NODE_NAME%::Info::OutputBits); // Read the start status of the output bits - ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, @sysvar::Modbus::%NODE_NAME%::Info::OutputRegisters); // Read the start status of the output registers + ModbusReadOutBits(thisDev.Addr.Read.OutputBits, @sysvar::Modbus::%NODE_NAME%::Info::OutputBits); // Read the start status of the output bits + ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, @sysvar::Modbus::%NODE_NAME%::Info::OutputRegisters); // Read the start status of the output registers - if (@sysvar::Modbus::%NODE_NAME%::Config::Interval > 0) // Start the polling timer - setTimerCyclic(gtRead, 1, @sysvar::Modbus::%NODE_NAME%::Config::Interval); + if (@sysvar::Modbus::%NODE_NAME%::Config::Interval > 0) // Start the polling timer + setTimerCyclic(gtRead, 1, @sysvar::Modbus::%NODE_NAME%::Config::Interval); } // Stop all transactions and close connection on preStop { - ModbusEnd(); + ModbusEnd(); } // Modbus events ---------------------------------------------------------------------- -/// All these events will be called by functions out of ModbusClientCommon.cin +/// All these events will be called by functions out of ModbusClientCommon.cin // -- Modbus Failures ----------------------------------------------------------------- -/// Several reasons are possible: -/// error == Timeout: The packet will be resent -/// error == FinalTimeout: The packet will not be resent -/// error == Exception: The client responded with an exception (which again can have several reasons, see enum ModbusException) +/// Several reasons are possible: +/// error == Timeout: The packet will be resent +/// error == FinalTimeout: The packet will not be resent +/// error == Exception: The client responded with an exception (which again can have several reasons, see enum ModbusException) // This method gets called when an error occured while trying to read some bits (ModbusReadBits()) void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - word i; + word i; - switch (error) - { - case Exception: - case Timeout: - case NotSent: - break; - case FinalTimeout: - sysBeginVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputBits"); - for (i = 0; i < @sysvar::Modbus::%NODE_NAME%::Info::InputBits; i++) - @sysvar::Modbus::%NODE_NAME%::Data::InputBits[i] = -1; - sysEndVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputBits"); - break; - default: - writeDbg(MbError, "OnModbusReadBitsFailed: Unkown error: %d", error); - OnModbusClientPanics(SwitchArgumentInvalid); - return; - } + switch (error) + { + case Exception: + case Timeout: + case NotSent: + break; + case FinalTimeout: + sysBeginVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputBits"); + for (i = 0; i < @sysvar::Modbus::%NODE_NAME%::Info::InputBits; i++) + @sysvar::Modbus::%NODE_NAME%::Data::InputBits[i] = -1; + sysEndVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputBits"); + break; + default: + writeDbg(MbError, "OnModbusReadBitsFailed: Unkown error: %d", error); + OnModbusClientPanics(SwitchArgumentInvalid); + return; + } } // This method gets called when an error occured while trying to read some registers (ModbusReadRegisters()) void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - byte i; + byte i; - switch (error) - { - case Exception: - case Timeout: - case NotSent: - break; - case FinalTimeout: - sysBeginVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputRegisters"); - for (i = 0; i < @sysvar::Modbus::%NODE_NAME%::Info::InputRegisters; i++) - @sysvar::Modbus::%NODE_NAME%::Data::InputRegisters[i] = -1; - sysEndVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputRegisters"); - break; - default: - writeDbg(MbError, "OnModbusReadBitsFailed: Unkown error: %d", error); - OnModbusClientPanics(SwitchArgumentInvalid); - return; - } + switch (error) + { + case Exception: + case Timeout: + case NotSent: + break; + case FinalTimeout: + sysBeginVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputRegisters"); + for (i = 0; i < @sysvar::Modbus::%NODE_NAME%::Info::InputRegisters; i++) + @sysvar::Modbus::%NODE_NAME%::Data::InputRegisters[i] = -1; + sysEndVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputRegisters"); + break; + default: + writeDbg(MbError, "OnModbusReadBitsFailed: Unkown error: %d", error); + OnModbusClientPanics(SwitchArgumentInvalid); + return; + } } // This method gets called when an error occured while trying to set a bit (ModbusWriteBit()) @@ -122,78 +122,78 @@ void OnModbusWriteBitsFailed(enum ModbusRequestError error, enum ModbusException void OnModbusWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap){} // -- Modbus Success ------------------------------------------------------------------ -/// These functions get called when a device responds that a request was fulfilled successfully -/// Normally the Reponse as well the Request will be handed over +/// These functions get called when a device responds that a request was fulfilled successfully +/// Normally the Reponse as well the Request will be handed over // This method gets called when some bits were read successfully. See 'bitStatus' for their values and 'mbreq.Address' for their start address void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq) { - word i, offset; + word i, offset; - 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("Modbus::%NODE_NAME%::Data", "OutputBits"); + 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("Modbus::%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::Modbus::%NODE_NAME%::Data::OutputBits[i + offset] = bitStatus[i]; + offset = mbreq.Address - thisDev.Addr.Read.OutputBits; // Get the offset to the base output bit address + for (i = 0; i < mbreq.Count; i++) + @sysvar::Modbus::%NODE_NAME%::Data::OutputBits[i + offset] = bitStatus[i]; - sysEndVariableStructUpdate("Modbus::%NODE_NAME%::Data", "OutputBits"); - break; + sysEndVariableStructUpdate("Modbus::%NODE_NAME%::Data", "OutputBits"); + break; - case ReadBitsIn: // Read input bits - sysBeginVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputBits"); + case ReadBitsIn: // Read input bits + sysBeginVariableStructUpdate("Modbus::%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::Modbus::%NODE_NAME%::Data::InputBits[i + offset] = bitStatus[i]; + offset = mbreq.Address - thisDev.Addr.Read.InputBits; // Get the offset to the base input bit address + for (i = 0; i < mbreq.Count; i++) + @sysvar::Modbus::%NODE_NAME%::Data::InputBits[i + offset] = bitStatus[i]; - sysEndVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputBits"); - break; + sysEndVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputBits"); + break; - default: - writeDbg(MbError, "OnModbusReadBitsSuccess: Unexpected function code: 0x%02X", mbreq.Header.FuncCode); - OnModbusClientPanics(FuncCodeIncorrect); - return; - } + default: + writeDbg(MbError, "OnModbusReadBitsSuccess: Unexpected function code: 0x%02X", mbreq.Header.FuncCode); + OnModbusClientPanics(FuncCodeIncorrect); + return; + } } // This method gets called when some bits were read successfully. See 'mbres.Data' for their values and 'mbreq.Address' for their start address void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq) { - word i, offset; + word i, offset; - 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("Modbus::%NODE_NAME%::Data", "OutputRegisters"); + 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("Modbus::%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::Modbus::%NODE_NAME%::Data::OutputRegisters[i + offset] = mbres.Data[i]; + offset = mbreq.Address - thisDev.Addr.Read.OutputRegisters; // Get the offset to the base output register address + for (i = 0; i < mbreq.Count; i++) + @sysvar::Modbus::%NODE_NAME%::Data::OutputRegisters[i + offset] = mbres.Data[i]; - sysEndVariableStructUpdate("Modbus::%NODE_NAME%::Data", "OutputRegisters"); - break; + sysEndVariableStructUpdate("Modbus::%NODE_NAME%::Data", "OutputRegisters"); + break; - case ReadRegistersIn: // Read input registers - sysBeginVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputRegisters"); + case ReadRegistersIn: // Read input registers + sysBeginVariableStructUpdate("Modbus::%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::Modbus::%NODE_NAME%::Data::InputRegisters[i + offset] = mbres.Data[i]; + offset = mbreq.Address - thisDev.Addr.Read.InputRegisters; // Get the offset to the base input bit address + for (i = 0; i < mbreq.Count; i++) + @sysvar::Modbus::%NODE_NAME%::Data::InputRegisters[i + offset] = mbres.Data[i]; - sysEndVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputRegisters"); - break; + sysEndVariableStructUpdate("Modbus::%NODE_NAME%::Data", "InputRegisters"); + break; - default: - writeDbg(MbError, "OnModbusReadBitsSuccess: Unexpected function code: 0x%02X", mbreq.Header.FuncCode); - OnModbusClientPanics(FuncCodeIncorrect); - return; - } + default: + writeDbg(MbError, "OnModbusReadBitsSuccess: Unexpected function code: 0x%02X", mbreq.Header.FuncCode); + OnModbusClientPanics(FuncCodeIncorrect); + return; + } } // This method gets called when a bit was set successfully. @@ -212,79 +212,79 @@ void OnModbusWriteMasksSuccess(struct ModbusResConfirmMasks mbres){} // It will pass as argument what happened. Please see the log (increase debug level in preStart) for more details. void OnModbusClientPanics(enum FatalErrors reason) { - switch(reason) - { - case ParsingBuffer: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error while parsing the received buffer"); - runError(1001, reason); - break; - case ModbusPackageWasSplit: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error while parsing the received buffer: The Modbus package was split", reason); - runError(1001, reason); - break; - case VendorIdUnknown: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: Vendor ID unknown"); - runError(1001, reason); - break; - case FuncCodeIncorrect: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: Function code is incorrect"); - runError(1001, reason); - break; - case AddressFailure: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: Start address is incorrect"); - runError(1001, reason); - break; - case ConnectionError: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Connection Error"); - gtRead.Cancel(); - break; - case SwitchArgumentInvalid: - writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: A argument of a switch statement is incorrect"); - runError(1001, reason); - break; - } - stop(); + switch(reason) + { + case ParsingBuffer: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error while parsing the received buffer"); + runError(1001, reason); + break; + case ModbusPackageWasSplit: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error while parsing the received buffer: The Modbus package was split", reason); + runError(1001, reason); + break; + case VendorIdUnknown: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: Vendor ID unknown"); + runError(1001, reason); + break; + case FuncCodeIncorrect: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: Function code is incorrect"); + runError(1001, reason); + break; + case AddressFailure: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: Start address is incorrect"); + runError(1001, reason); + break; + case ConnectionError: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Connection Error"); + gtRead.Cancel(); + break; + case SwitchArgumentInvalid: + writeLineEx(0, 4, "<%NODE_NAME%> Fatal Error: A argument of a switch statement is incorrect"); + runError(1001, reason); + break; + } + stop(); } // ------------------------------------------------------------------------- // The timer will continuously poll the input registers and intput bits on timer gtRead { - ModbusReadRegisters(thisDev.Addr.Read.InputRegisters, @sysvar::Modbus::%NODE_NAME%::Info::InputRegisters); - ModbusReadBits(thisDev.Addr.Read.InputBits, @sysvar::Modbus::%NODE_NAME%::Info::InputBits); + ModbusReadRegisters(thisDev.Addr.Read.InputRegisters, @sysvar::Modbus::%NODE_NAME%::Info::InputRegisters); + ModbusReadBits(thisDev.Addr.Read.InputBits, @sysvar::Modbus::%NODE_NAME%::Info::InputBits); } // If Data::OutputBits is changed we will send this update to the device on sysvar Modbus::%NODE_NAME%::Data::OutputBits { - word count, i; - byte bitStatus[1968]; + word count, i; + byte bitStatus[1968]; - count = @sysvar::Modbus::%NODE_NAME%::Info::OutputBits; + count = @sysvar::Modbus::%NODE_NAME%::Info::OutputBits; - for (i = 0; i < count; i++) // Copy the data from SysVars to byte[] - bitStatus[i] = @sysvar::Modbus::%NODE_NAME%::Data::OutputBits[i]; + for (i = 0; i < count; i++) // Copy the data from SysVars to byte[] + bitStatus[i] = @sysvar::Modbus::%NODE_NAME%::Data::OutputBits[i]; - ModbusWriteBitsB(0, count, bitStatus); // Send update command + ModbusWriteBitsB(0, count, bitStatus); // Send update command } // If Data::OutputRergisters is changed we will send this update to the device on sysvar Modbus::%NODE_NAME%::Data::OutputRegisters { - word count, i; - word regValues[123]; + word count, i; + word regValues[123]; - count = @sysvar::Modbus::%NODE_NAME%::Info::OutputRegisters; + count = @sysvar::Modbus::%NODE_NAME%::Info::OutputRegisters; - for (i = 0; i < count; i++) // Copy the data from SysVars to word[] - regValues[i] = @sysvar::Modbus::%NODE_NAME%::Data::OutputRegisters[i]; + for (i = 0; i < count; i++) // Copy the data from SysVars to word[] + regValues[i] = @sysvar::Modbus::%NODE_NAME%::Data::OutputRegisters[i]; - ModbusWriteRegisters(0, count, regValues); // Send update command + ModbusWriteRegisters(0, count, regValues); // Send update command } // Config::Interval is changed we will update the timer gtRead accordingly on sysvar Modbus::%NODE_NAME%::Config::Interval { - if (@this <= 0) - gtRead.Cancel(); - else - setTimerCyclic(gtRead, @this); + if (@this <= 0) + gtRead.Cancel(); + else + setTimerCyclic(gtRead, @this); } \ No newline at end of file diff --git a/Modbus-CAPL/include/CAPL/TestTheStack.can b/Modbus-CAPL/include/CAPL/TestTheStack.can index 5f96e10..c6eed0a 100644 --- a/Modbus-CAPL/include/CAPL/TestTheStack.can +++ b/Modbus-CAPL/include/CAPL/TestTheStack.can @@ -49,159 +49,159 @@ includes { - #include "include/DeviceInformation.cin" - #include "include/ModbusUdp.cin" - #include "include/ModbusClient.cin" + #include "include/DeviceInformation.cin" + #include "include/ModbusUdp.cin" + #include "include/ModbusClient.cin" } variables { - word state = 0; - byte s0i = 0; - struct device s0dev; - byte s90i = 1; - msTimer timr; - byte skipOutput = 1; + word state = 0; + byte s0i = 0; + struct device s0dev; + byte s90i = 1; + msTimer timr; + byte skipOutput = 1; } on preStart { - setStartdelay(100); - OutputDebugLevel = Debug; + setStartdelay(100); + OutputDebugLevel = Debug; } on start { - char ip[16]; - sysGetVariableString("Device::Config", "IP", ip, 16); + char ip[16]; + sysGetVariableString("Device::Config", "IP", ip, 16); - DeviceInit(@sysvar::Device::Config::Vendor); - ModbusInit(ip, @sysvar::Config::Modbus::Port, @sysvar::Config::Modbus::RequestTimeout, 1/*retry*/); + DeviceInit(@sysvar::Device::Config::Vendor); + ModbusInit(ip, @sysvar::Config::Modbus::Port, @sysvar::Config::Modbus::RequestTimeout, 1/*retry*/); - if (gSocketState < CONNECTING) // We are not connecting and not connected - return; + if (gSocketState < CONNECTING) // We are not connecting and not connected + return; - // Start the Test - s0dev.Vendor = (enum Vendor)@sysvar::Device::Config::Vendor; - s0i = _DeviceGetInformation((enum Vendor)@sysvar::Device::Config::Vendor); + // Start the Test + s0dev.Vendor = (enum Vendor)@sysvar::Device::Config::Vendor; + s0i = _DeviceGetInformation((enum Vendor)@sysvar::Device::Config::Vendor); } on preStop { - ModbusEnd(); + ModbusEnd(); } void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - char reason[100]; - struct ModbusReqRead mbreq; + char reason[100]; + struct ModbusReqRead mbreq; - switch (error) - { - case Timeout: - break; - case FinalTimeout: - strncpy(reason, "Timeout", elCount(reason)); - break; - case Exception: - snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); - break; - case NotSent: - strncpy(reason, "Impossible to send", elCount(reason)); - break; - default: - writeDbg(MbError, "OnModbusReadBitsFailed: Unkown error: %d", error); - OnModbusClientPanics(SwitchArgumentInvalid); - return; - } + switch (error) + { + case Timeout: + break; + case FinalTimeout: + strncpy(reason, "Timeout", elCount(reason)); + break; + case Exception: + snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); + break; + case NotSent: + strncpy(reason, "Impossible to send", elCount(reason)); + break; + default: + writeDbg(MbError, "OnModbusReadBitsFailed: Unkown error: %d", error); + OnModbusClientPanics(SwitchArgumentInvalid); + return; + } - memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); + memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); - switch (state) - { - case 0: - writeDbg(MbError, "State %d. Reading %d output bit from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); - break; - case 20: - writeDbg(MbError, "State %d. Reading %d input bit from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); - break; - case 60: - case 120: - case 130: - writeDbg(MbError, "State %d. Reading %d output bits from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); - break; - case 900: - if (error == FinalTimeout) - { - writeDbg(MbInfo, "State %d. Packet timed out! Receive window size: %d", state, s90i-1); - state = 910; - stop(); - return; - } - else - writeDbg(MbError, "State %d. Error while writing bit: %s", state, reason); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusReadBitsFailed()!", state); - break; - } - runError(1001, 0); + switch (state) + { + case 0: + writeDbg(MbError, "State %d. Reading %d output bit from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); + break; + case 20: + writeDbg(MbError, "State %d. Reading %d input bit from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); + break; + case 60: + case 120: + case 130: + writeDbg(MbError, "State %d. Reading %d output bits from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); + break; + case 900: + if (error == FinalTimeout) + { + writeDbg(MbInfo, "State %d. Packet timed out! Receive window size: %d", state, s90i-1); + state = 910; + stop(); + return; + } + else + writeDbg(MbError, "State %d. Error while writing bit: %s", state, reason); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusReadBitsFailed()!", state); + break; + } + runError(1001, 0); } void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq) { - byte i; - word s6[1] = {0x5555}; + byte i; + word s6[1] = {0x5555}; - switch (state) - { - case 5: - writeDbg(MbDebug, "State %d. Successfully read %d output bit from 0x%04X", state, mbreq.Count, mbreq.Address); - ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, 1); - state = 10; - break; - case 20: - writeDbg(MbDebug, "State %d. Successfully read %d input bit from 0x%04X", state, mbreq.Count, mbreq.Address); - ModbusReadInRegisters(thisDev.Addr.Read.InputRegisters, 1); - state = 30; - break; - case 60: - writeDbg(MbDebug, "State %d. Successfully read %d output bits from 0x%04X", state, mbreq.Count, mbreq.Address); - for (i = 0; i < mbreq.Count; i++) - { - writeDbg(MbWarning, "i: %d, Status: %d, Expected: %d", i, bitStatus[i], (i != 2)); - if (bitStatus[i] != (i != 2)) - { - writeDbg(MbError, "State of output bit %d was incorrect: %d (expected %d)", i, bitStatus[i], (i != 2)); - runError(1001, 0); - return; - } - } - // OK. - writeDbg(MbDebug, "State %d. Status of these output bits was correct.", state); - ModbusWriteRegisters(thisDev.Addr.Write.OutputRegisters, 1, s6); - state = 70; - break; - case 120: - state = 130; - break; - case 130: - writeDbg(MbDebug, "State %d. Successfully received the Read-Bits telegrams (as expected)", state); - timr.Set(1); - break; - case 900: - if (gQueueSent.Size() > 0 || gQueuePending.Size() > 0) - break; - ++s90i; - for (i = 0; i < s90i && i < 100; i++) - ModbusReadBits(thisDev.Addr.Read.InputBits, 1); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusReadBitsSuccess()!", state); - runError(1001, 0); - break; - } + switch (state) + { + case 5: + writeDbg(MbDebug, "State %d. Successfully read %d output bit from 0x%04X", state, mbreq.Count, mbreq.Address); + ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, 1); + state = 10; + break; + case 20: + writeDbg(MbDebug, "State %d. Successfully read %d input bit from 0x%04X", state, mbreq.Count, mbreq.Address); + ModbusReadInRegisters(thisDev.Addr.Read.InputRegisters, 1); + state = 30; + break; + case 60: + writeDbg(MbDebug, "State %d. Successfully read %d output bits from 0x%04X", state, mbreq.Count, mbreq.Address); + for (i = 0; i < mbreq.Count; i++) + { + writeDbg(MbWarning, "i: %d, Status: %d, Expected: %d", i, bitStatus[i], (i != 2)); + if (bitStatus[i] != (i != 2)) + { + writeDbg(MbError, "State of output bit %d was incorrect: %d (expected %d)", i, bitStatus[i], (i != 2)); + runError(1001, 0); + return; + } + } + // OK. + writeDbg(MbDebug, "State %d. Status of these output bits was correct.", state); + ModbusWriteRegisters(thisDev.Addr.Write.OutputRegisters, 1, s6); + state = 70; + break; + case 120: + state = 130; + break; + case 130: + writeDbg(MbDebug, "State %d. Successfully received the Read-Bits telegrams (as expected)", state); + timr.Set(1); + break; + case 900: + if (gQueueSent.Size() > 0 || gQueuePending.Size() > 0) + break; + ++s90i; + for (i = 0; i < s90i && i < 100; i++) + ModbusReadBits(thisDev.Addr.Read.InputBits, 1); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusReadBitsSuccess()!", state); + runError(1001, 0); + break; + } } @@ -210,144 +210,144 @@ void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[] void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - char reason[100]; - struct ModbusReqRead mbreq; + char reason[100]; + struct ModbusReqRead mbreq; - switch (error) - { - case Timeout: - break; - case FinalTimeout: - strncpy(reason, "Timeout", elCount(reason)); - break; - case Exception: - snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); - break; - case NotSent: - strncpy(reason, "Impossible to send", elCount(reason)); - break; - default: - writeDbg(MbError, "OnModbusReadRegistersFailed: Unkown error: %d", error); - OnModbusClientPanics(SwitchArgumentInvalid); - return; - } + switch (error) + { + case Timeout: + break; + case FinalTimeout: + strncpy(reason, "Timeout", elCount(reason)); + break; + case Exception: + snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); + break; + case NotSent: + strncpy(reason, "Impossible to send", elCount(reason)); + break; + default: + writeDbg(MbError, "OnModbusReadRegistersFailed: Unkown error: %d", error); + OnModbusClientPanics(SwitchArgumentInvalid); + return; + } - memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); + memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); - switch (state) - { - case 0: - case 10: - case 110: - case 75: - writeDbg(MbError, "State %d. Reading %d output register from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); - break; - case 30: - writeDbg(MbError, "State %d. Reading %d input register from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); - break; - case 90: - case 140: - case 145: - case 150: - writeDbg(MbError, "State %d. Reading %d output registers from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusReadRegistersFailed()!", state); - break; - } - runError(1001, 0); + switch (state) + { + case 0: + case 10: + case 110: + case 75: + writeDbg(MbError, "State %d. Reading %d output register from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); + break; + case 30: + writeDbg(MbError, "State %d. Reading %d input register from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); + break; + case 90: + case 140: + case 145: + case 150: + writeDbg(MbError, "State %d. Reading %d output registers from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusReadRegistersFailed()!", state); + break; + } + runError(1001, 0); } void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq) { - switch (state) - { - case 0: - s0i--; - _DeviceParseRegister(s0dev, mbreq.Address, mbres.Data, 0); + switch (state) + { + case 0: + s0i--; + _DeviceParseRegister(s0dev, mbreq.Address, mbres.Data, 0); - if (s0i == 0) - { - if (s0dev.DeviceIOs.OutputBits / 8 + s0dev.DeviceIOs.OutputRegisters < 2) - { - writeDbg(MbError, "Please connect more output! %d bits and %d registers are not enough, we need at least 1 word (2 bytes). (Input: %d bits, %d regs)", s0dev.DeviceIOs.OutputBits, s0dev.DeviceIOs.OutputRegisters, s0dev.DeviceIOs.InputBits, s0dev.DeviceIOs.InputRegisters); - skipOutput = 1; - //runError(1001, 0); - //return; - } - state = 5; - ModbusReadOutBits(thisDev.Addr.Read.OutputBits, 1); - } - break; - case 10: - writeDbg(MbDebug, "State %d. Successfully read %d output register from 0x%04X", state, mbreq.Count, mbreq.Address); - ModbusReadInBits(thisDev.Addr.Read.InputBits, 1); - state = 20; - break; - case 30: - writeDbg(MbDebug, "State %d. Successfully read %d input register from 0x%04X", state, mbreq.Count, mbreq.Address); - if (skipOutput) - state = 130; - timr.Set(1); - break; - case 75: - writeDbg(MbDebug, "State %d. Successfully read %d input register from 0x%04X", state, mbreq.Count, mbreq.Address); - if (mbres.Data[0] != 0x5555) - { - writeDbg(MbError, "State %d. Value of output register 0 was incorrect: 0x%04X (expected 0x5555). ModbusWriteRegisters failed!", state, mbres.Data[0]); - runError(1001, 0); - return; - } - ModbusWriteRegister(thisDev.Addr.Write.OutputRegisters, 0x9999); - state = 80; - break; - case 90: - writeDbg(MbDebug, "State %d. Successfully read %d output register from 0x%04X", state, mbreq.Count, mbreq.Address); - if (mbres.Data[0] != 0x9999) - { - writeDbg(MbError, "State %d. Value of output register 0 was incorrect: 0x%04X (expected 0x9999). ModbusWriteRegister failed!", state, mbres.Data[0]); - runError(1001, 0); - return; - } - ModbusWriteMasks(thisDev.Addr.Write.OutputRegisters, 0x00F9, 0x0006); - state = 100; - break; - case 110: - writeDbg(MbDebug, "State %d. Successfully read %d output register from 0x%04X", state, mbreq.Count, mbreq.Address); - if (mbres.Data[0] != 0x009F) - { - writeDbg(MbError, "State %d. Value of register at 0x%04X is incorrect: 0x%04X (expected 0x009F). ModbusWriteMasks failed!", state, mbreq.Address, mbres.Data[0]); - runError(1001, 0); - return; - } - writeDbg(MbDebug, "State %d. Successfully applied the masks at 0x%04X", state, mbreq.Address); - ModbusReadInBits(thisDev.Addr.Read.InputBits, 3000); - state = 120; - if (s0dev.Vendor == Wago) // This test does not work with Wago - state = 130; - break; - case 140: - state = 145; - break; - case 145: - state = 150; - break; - case 150: - writeDbg(MbDebug, "State %d. Successfully received three Read-Registers telegrams (as expected)", state); - if (skipOutput) - state = 190; - else - { - state = 160; - if (s0dev.Vendor == Wago) // This test does not work with Wago - state = 170; - } - timr.Set(1); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusReadRegistersSuccess()!", state); - runError(1001, 0); - break; - } + if (s0i == 0) + { + if (s0dev.DeviceIOs.OutputBits / 8 + s0dev.DeviceIOs.OutputRegisters < 2) + { + writeDbg(MbError, "Please connect more output! %d bits and %d registers are not enough, we need at least 1 word (2 bytes). (Input: %d bits, %d regs)", s0dev.DeviceIOs.OutputBits, s0dev.DeviceIOs.OutputRegisters, s0dev.DeviceIOs.InputBits, s0dev.DeviceIOs.InputRegisters); + skipOutput = 1; + //runError(1001, 0); + //return; + } + state = 5; + ModbusReadOutBits(thisDev.Addr.Read.OutputBits, 1); + } + break; + case 10: + writeDbg(MbDebug, "State %d. Successfully read %d output register from 0x%04X", state, mbreq.Count, mbreq.Address); + ModbusReadInBits(thisDev.Addr.Read.InputBits, 1); + state = 20; + break; + case 30: + writeDbg(MbDebug, "State %d. Successfully read %d input register from 0x%04X", state, mbreq.Count, mbreq.Address); + if (skipOutput) + state = 130; + timr.Set(1); + break; + case 75: + writeDbg(MbDebug, "State %d. Successfully read %d input register from 0x%04X", state, mbreq.Count, mbreq.Address); + if (mbres.Data[0] != 0x5555) + { + writeDbg(MbError, "State %d. Value of output register 0 was incorrect: 0x%04X (expected 0x5555). ModbusWriteRegisters failed!", state, mbres.Data[0]); + runError(1001, 0); + return; + } + ModbusWriteRegister(thisDev.Addr.Write.OutputRegisters, 0x9999); + state = 80; + break; + case 90: + writeDbg(MbDebug, "State %d. Successfully read %d output register from 0x%04X", state, mbreq.Count, mbreq.Address); + if (mbres.Data[0] != 0x9999) + { + writeDbg(MbError, "State %d. Value of output register 0 was incorrect: 0x%04X (expected 0x9999). ModbusWriteRegister failed!", state, mbres.Data[0]); + runError(1001, 0); + return; + } + ModbusWriteMasks(thisDev.Addr.Write.OutputRegisters, 0x00F9, 0x0006); + state = 100; + break; + case 110: + writeDbg(MbDebug, "State %d. Successfully read %d output register from 0x%04X", state, mbreq.Count, mbreq.Address); + if (mbres.Data[0] != 0x009F) + { + writeDbg(MbError, "State %d. Value of register at 0x%04X is incorrect: 0x%04X (expected 0x009F). ModbusWriteMasks failed!", state, mbreq.Address, mbres.Data[0]); + runError(1001, 0); + return; + } + writeDbg(MbDebug, "State %d. Successfully applied the masks at 0x%04X", state, mbreq.Address); + ModbusReadInBits(thisDev.Addr.Read.InputBits, 3000); + state = 120; + if (s0dev.Vendor == Wago) // This test does not work with Wago + state = 130; + break; + case 140: + state = 145; + break; + case 145: + state = 150; + break; + case 150: + writeDbg(MbDebug, "State %d. Successfully received three Read-Registers telegrams (as expected)", state); + if (skipOutput) + state = 190; + else + { + state = 160; + if (s0dev.Vendor == Wago) // This test does not work with Wago + state = 170; + } + timr.Set(1); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusReadRegistersSuccess()!", state); + runError(1001, 0); + break; + } } @@ -357,56 +357,56 @@ void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct void OnModbusWriteBitFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - char reason[100]; - struct ModbusReqWriteSingle mbreq; + char reason[100]; + struct ModbusReqWriteSingle mbreq; - switch (error) - { - case Timeout: - break; - case FinalTimeout: - strncpy(reason, "Timeout", elCount(reason)); - break; - case Exception: - snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); - break; - case NotSent: - strncpy(reason, "Impossible to send", elCount(reason)); - break; - default: - writeDbg(MbError, "OnModbusWriteBitFailed: Unkown error: %d", error); - OnModbusClientPanics(SwitchArgumentInvalid); - return; - } + switch (error) + { + case Timeout: + break; + case FinalTimeout: + strncpy(reason, "Timeout", elCount(reason)); + break; + case Exception: + snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); + break; + case NotSent: + strncpy(reason, "Impossible to send", elCount(reason)); + break; + default: + writeDbg(MbError, "OnModbusWriteBitFailed: Unkown error: %d", error); + OnModbusClientPanics(SwitchArgumentInvalid); + return; + } - memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); + memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); - switch (state) - { - case 50: - writeDbg(MbError, "State %d. Setting bit at 0x%04X did not work! Reason: %s", state, mbreq.Address, reason); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusWriteBitFailed()!", state); - break; - } - runError(1001, 0); + switch (state) + { + case 50: + writeDbg(MbError, "State %d. Setting bit at 0x%04X did not work! Reason: %s", state, mbreq.Address, reason); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusWriteBitFailed()!", state); + break; + } + runError(1001, 0); } void OnModbusWriteBitSuccess(struct ModbusResConfirmSingle mbres) { - byte i; - switch (state) - { - case 50: - writeDbg(MbDebug, "State %d. Successfully set bit at 0x%04X", state, mbres.Address); - timr.Set(1); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusWriteBitSuccess()!", state); - runError(1001, 0); - break; - } + byte i; + switch (state) + { + case 50: + writeDbg(MbDebug, "State %d. Successfully set bit at 0x%04X", state, mbres.Address); + timr.Set(1); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusWriteBitSuccess()!", state); + runError(1001, 0); + break; + } } @@ -417,54 +417,54 @@ void OnModbusWriteBitSuccess(struct ModbusResConfirmSingle mbres) void OnModbusWriteRegisterFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - char reason[100]; - struct ModbusReqWriteSingle mbreq; + char reason[100]; + struct ModbusReqWriteSingle mbreq; - switch (error) - { - case Timeout: - break; - case FinalTimeout: - strncpy(reason, "Timeout", elCount(reason)); - break; - case Exception: - snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); - break; - case NotSent: - strncpy(reason, "Impossible to send", elCount(reason)); - break; - default: - writeDbg(MbError, "OnModbusWriteRegisterFailed: Unkown error: %d", error); - OnModbusClientPanics(SwitchArgumentInvalid); - return; - } + switch (error) + { + case Timeout: + break; + case FinalTimeout: + strncpy(reason, "Timeout", elCount(reason)); + break; + case Exception: + snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); + break; + case NotSent: + strncpy(reason, "Impossible to send", elCount(reason)); + break; + default: + writeDbg(MbError, "OnModbusWriteRegisterFailed: Unkown error: %d", error); + OnModbusClientPanics(SwitchArgumentInvalid); + return; + } - memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); + memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); - switch (state) - { - case 80: - writeDbg(MbError, "State %d. Writing output register at 0x%04X did not work! Reason: %s", state, mbreq.Address, reason); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusWriteRegisterFailed()!", state); - break; - } - runError(1001, 0); + switch (state) + { + case 80: + writeDbg(MbError, "State %d. Writing output register at 0x%04X did not work! Reason: %s", state, mbreq.Address, reason); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusWriteRegisterFailed()!", state); + break; + } + runError(1001, 0); } void OnModbusWriteRegisterSuccess(struct ModbusResConfirmSingle mbres) { - switch (state) - { - case 80: - writeDbg(MbDebug, "State %d. Successfully set output register at 0x%04X to 0x%04X", state, mbres.Address, mbres.Value); - timr.Set(1); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusWriteRegisterSuccess()!", state); - runError(1001, 0); - break; - } + switch (state) + { + case 80: + writeDbg(MbDebug, "State %d. Successfully set output register at 0x%04X to 0x%04X", state, mbres.Address, mbres.Value); + timr.Set(1); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusWriteRegisterSuccess()!", state); + runError(1001, 0); + break; + } } @@ -475,54 +475,54 @@ void OnModbusWriteRegisterSuccess(struct ModbusResConfirmSingle mbres) void OnModbusWriteMasksFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - char reason[100]; - struct ModbusReqWriteMasks mbreq; + char reason[100]; + struct ModbusReqWriteMasks mbreq; - switch (error) - { - case Timeout: - break; - case FinalTimeout: - strncpy(reason, "Timeout", elCount(reason)); - break; - case Exception: - snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); - break; - case NotSent: - strncpy(reason, "Impossible to send", elCount(reason)); - break; - default: - writeDbg(MbError, "OnModbusWriteMasksFailed: Unkown error: %d", error); - OnModbusClientPanics(SwitchArgumentInvalid); - return; - } + switch (error) + { + case Timeout: + break; + case FinalTimeout: + strncpy(reason, "Timeout", elCount(reason)); + break; + case Exception: + snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); + break; + case NotSent: + strncpy(reason, "Impossible to send", elCount(reason)); + break; + default: + writeDbg(MbError, "OnModbusWriteMasksFailed: Unkown error: %d", error); + OnModbusClientPanics(SwitchArgumentInvalid); + return; + } - memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); + memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); - switch (state) - { - case 100: - writeDbg(MbError, "State %d. Applying masks &0x%04X |0x%04X at 0x%04X did not work! Reason: %s", state, mbreq.And, mbreq.Or, mbreq.Address); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusWriteMasksFailed()!", state); - break; - } - runError(1001, 0); + switch (state) + { + case 100: + writeDbg(MbError, "State %d. Applying masks &0x%04X |0x%04X at 0x%04X did not work! Reason: %s", state, mbreq.And, mbreq.Or, mbreq.Address); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusWriteMasksFailed()!", state); + break; + } + runError(1001, 0); } void OnModbusWriteMasksSuccess(struct ModbusResConfirmMasks mbres) { - switch (state) - { - case 100: - writeDbg(MbDebug, "State %d. Successfully applied masks &0x%04X |0x%04X at 0x%04X", state, mbres.And, mbres.Or, mbres.Address); - timr.Set(1); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusWriteMasksSuccess()!", state); - runError(1001, 0); - break; - } + switch (state) + { + case 100: + writeDbg(MbDebug, "State %d. Successfully applied masks &0x%04X |0x%04X at 0x%04X", state, mbres.And, mbres.Or, mbres.Address); + timr.Set(1); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusWriteMasksSuccess()!", state); + runError(1001, 0); + break; + } } @@ -533,37 +533,37 @@ void OnModbusWriteMasksSuccess(struct ModbusResConfirmMasks mbres) void OnModbusReadWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - char reason[100]; - struct ModbusReqReadWriteRegisters mbreq; + char reason[100]; + struct ModbusReqReadWriteRegisters mbreq; - switch (error) - { - case Timeout: - break; - case FinalTimeout: - strncpy(reason, "Timeout", elCount(reason)); - break; - case Exception: - snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); - break; - case NotSent: - strncpy(reason, "Impossible to send", elCount(reason)); - break; - default: - writeDbg(MbError, "OnModbusReadWriteRegistersFailed: Unkown error: %d", error); - OnModbusClientPanics(SwitchArgumentInvalid); - return; - } + switch (error) + { + case Timeout: + break; + case FinalTimeout: + strncpy(reason, "Timeout", elCount(reason)); + break; + case Exception: + snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); + break; + case NotSent: + strncpy(reason, "Impossible to send", elCount(reason)); + break; + default: + writeDbg(MbError, "OnModbusReadWriteRegistersFailed: Unkown error: %d", error); + OnModbusClientPanics(SwitchArgumentInvalid); + return; + } - memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); + memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); - switch (state) - { - default: - writeDbg(MbError, "I did not expect state %d in OnModbusReadWriteRegistersFailed()!", state); - break; - } - runError(1001, 0); + switch (state) + { + default: + writeDbg(MbError, "I did not expect state %d in OnModbusReadWriteRegistersFailed()!", state); + break; + } + runError(1001, 0); } @@ -574,67 +574,67 @@ void OnModbusReadWriteRegistersFailed(enum ModbusRequestError error, enum Modbus void OnModbusWriteBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - char reason[100]; - struct ModbusReqWriteBits mbreq; + char reason[100]; + struct ModbusReqWriteBits mbreq; - switch (error) - { - case Timeout: - break; - case FinalTimeout: - strncpy(reason, "Timeout", elCount(reason)); - break; - case Exception: - snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); - break; - case NotSent: - strncpy(reason, "Impossible to send", elCount(reason)); - break; - default: - writeDbg(MbError, "OnModbusWriteBitsFailed: Unkown error: %d", error); - OnModbusClientPanics(SwitchArgumentInvalid); - return; - } + switch (error) + { + case Timeout: + break; + case FinalTimeout: + strncpy(reason, "Timeout", elCount(reason)); + break; + case Exception: + snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); + break; + case NotSent: + strncpy(reason, "Impossible to send", elCount(reason)); + break; + default: + writeDbg(MbError, "OnModbusWriteBitsFailed: Unkown error: %d", error); + OnModbusClientPanics(SwitchArgumentInvalid); + return; + } - memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); + memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); - switch (state) - { - case 40: - case 160: - case 170: - writeDbg(MbError, "State %d. Writing %d bits at 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusWriteBitsFailed()!", state); - break; - } - runError(1001, 0); + switch (state) + { + case 40: + case 160: + case 170: + writeDbg(MbError, "State %d. Writing %d bits at 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusWriteBitsFailed()!", state); + break; + } + runError(1001, 0); } void OnModbusWriteBitsSuccess(struct ModbusResConfirmMultiple mbres) { - word s17[200]; + word s17[200]; - switch (state) - { - case 40: - writeDbg(MbDebug, "State %d. Successfully set %d bits at 0x%04X", state, mbres.Count, mbres.Address); - ModbusWriteBit(thisDev.Addr.Write.OutputBits+2, 0); - state = 50; - break; - case 160: - state = 170; - break; - case 170: - writeDbg(MbDebug, "State %d. Successfully received two(?) Write-Bits telegrams (as expected)", state); - ModbusWriteRegisters(thisDev.Addr.Write.OutputRegisters, 200, s17); - state = 180; - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusWriteBitsSuccess()!", state); - runError(1001, 0); - break; - } + switch (state) + { + case 40: + writeDbg(MbDebug, "State %d. Successfully set %d bits at 0x%04X", state, mbres.Count, mbres.Address); + ModbusWriteBit(thisDev.Addr.Write.OutputBits+2, 0); + state = 50; + break; + case 160: + state = 170; + break; + case 170: + writeDbg(MbDebug, "State %d. Successfully received two(?) Write-Bits telegrams (as expected)", state); + ModbusWriteRegisters(thisDev.Addr.Write.OutputRegisters, 200, s17); + state = 180; + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusWriteBitsSuccess()!", state); + runError(1001, 0); + break; + } } @@ -648,63 +648,63 @@ void OnModbusWriteBitsSuccess(struct ModbusResConfirmMultiple mbres) void OnModbusWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - char reason[100]; - struct ModbusReqWriteRegisters mbreq; + char reason[100]; + struct ModbusReqWriteRegisters mbreq; - switch (error) - { - case Timeout: - break; - case FinalTimeout: - strncpy(reason, "Timeout", elCount(reason)); - break; - case Exception: - snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); - break; - case NotSent: - strncpy(reason, "Impossible to send", elCount(reason)); - break; - default: - writeDbg(MbError, "OnModbusWriteRegistersFailed: Unkown error: %d", error); - OnModbusClientPanics(SwitchArgumentInvalid); - return; - } + switch (error) + { + case Timeout: + break; + case FinalTimeout: + strncpy(reason, "Timeout", elCount(reason)); + break; + case Exception: + snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]); + break; + case NotSent: + strncpy(reason, "Impossible to send", elCount(reason)); + break; + default: + writeDbg(MbError, "OnModbusWriteRegistersFailed: Unkown error: %d", error); + OnModbusClientPanics(SwitchArgumentInvalid); + return; + } - memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); + memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); - switch (state) - { - case 70: - case 180: - case 190: - writeDbg(MbError, "State %d. Writing %d registers at 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusWriteRegistersFailed()!", state); - break; - } - runError(1001, 0); + switch (state) + { + case 70: + case 180: + case 190: + writeDbg(MbError, "State %d. Writing %d registers at 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusWriteRegistersFailed()!", state); + break; + } + runError(1001, 0); } void OnModbusWriteRegistersSuccess(struct ModbusResConfirmMultiple mbres) { - switch (state) - { - case 70: - writeDbg(MbDebug, "State %d. Successfully set %d output registers at 0x%04X", state, mbres.Count, mbres.Address); - timr.Set(1); - break; - case 180: - state = 190; - break; - case 190: - writeDbg(MbDebug, "State %d. Successfully received two Write-Registers telegrams (as expected)", state); - timr.Set(1); - break; - default: - writeDbg(MbError, "I did not expect state %d in OnModbusWriteRegistersSuccess()!", state); - runError(1001, 0); - break; - } + switch (state) + { + case 70: + writeDbg(MbDebug, "State %d. Successfully set %d output registers at 0x%04X", state, mbres.Count, mbres.Address); + timr.Set(1); + break; + case 180: + state = 190; + break; + case 190: + writeDbg(MbDebug, "State %d. Successfully received two Write-Registers telegrams (as expected)", state); + timr.Set(1); + break; + default: + writeDbg(MbError, "I did not expect state %d in OnModbusWriteRegistersSuccess()!", state); + runError(1001, 0); + break; + } } @@ -713,83 +713,83 @@ void OnModbusWriteRegistersSuccess(struct ModbusResConfirmMultiple mbres) void OnModbusClientPanics(enum FatalErrors reason) { - switch (reason) - { - case ParsingBuffer: - writeDbg(MbError, "State %d. FATAL ERROR while parsing received buffer", state); - break; - case ModbusPackageWasSplit: - writeDbg(MbError, "State %d. FATAL ERROR: Modbus package was split", state); - break; - case DeviceCodeUnknown: - writeDbg(MbError, "State %d. FATAL ERROR: Device code unknown", state); - break; - case VendorIdUnknown: - writeDbg(MbError, "State %d. FATAL ERROR: Vendor Id unknown", state); - break; - case ConnectionError: - writeDbg(MbError, "State %d. FATAL ERROR: Connection Error", state); - break; - case FuncCodeIncorrect: - writeDbg(MbError, "State %d. FATAL ERROR: FuncCode Incorrect", state); - break; - case AddressFailure: - writeDbg(MbError, "State %d. FATAL ERROR: Some Modbus Address Failure", state); - break; - case SwitchArgumentInvalid: - writeDbg(MbError, "State %d. FATAL ERROR: A argument of a switch statement is incorrect"); - break; - } - - stop(); - runError(1001, 0); + switch (reason) + { + case ParsingBuffer: + writeDbg(MbError, "State %d. FATAL ERROR while parsing received buffer", state); + break; + case ModbusPackageWasSplit: + writeDbg(MbError, "State %d. FATAL ERROR: Modbus package was split", state); + break; + case DeviceCodeUnknown: + writeDbg(MbError, "State %d. FATAL ERROR: Device code unknown", state); + break; + case VendorIdUnknown: + writeDbg(MbError, "State %d. FATAL ERROR: Vendor Id unknown", state); + break; + case ConnectionError: + writeDbg(MbError, "State %d. FATAL ERROR: Connection Error", state); + break; + case FuncCodeIncorrect: + writeDbg(MbError, "State %d. FATAL ERROR: FuncCode Incorrect", state); + break; + case AddressFailure: + writeDbg(MbError, "State %d. FATAL ERROR: Some Modbus Address Failure", state); + break; + case SwitchArgumentInvalid: + writeDbg(MbError, "State %d. FATAL ERROR: A argument of a switch statement is incorrect"); + break; + } + + stop(); + runError(1001, 0); } on timer timr { - byte s3[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - byte s15[3000]; + byte s3[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + byte s15[3000]; - switch(state) - { - case 30: - ModbusWriteBitsB(thisDev.Addr.Write.OutputBits, 10, s3); - state = 40; - break; - case 50: - ModbusReadOutBits(thisDev.Addr.Read.OutputBits, 10); - state = 60; - break; - case 70: - ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, 1); - state = 75; - break; - case 80: - ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, 1); - state = 90; - break; - case 100: - ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, 1); - state = 110; - break; - case 130: - ModbusReadRegisters(thisDev.Addr.Read.InputRegisters, 300); - state = 140; - break; - case 160: - ModbusWriteBitsB(thisDev.Addr.Write.OutputBits, 3000, s15); - break; - case 170: - ModbusWriteBitsB(thisDev.Addr.Write.OutputBits, 1000, s15); - break; - case 190: - ModbusReadBits(thisDev.Addr.Read.InputBits, 1); - thisDev.ReceiveWindow = 0xFF; // Set receive window to maximum to test the limit - state = 900; - break; - default: - writeDbg(MbError, "I did not expect state %d in timer timr!", state); - break; - } + switch(state) + { + case 30: + ModbusWriteBitsB(thisDev.Addr.Write.OutputBits, 10, s3); + state = 40; + break; + case 50: + ModbusReadOutBits(thisDev.Addr.Read.OutputBits, 10); + state = 60; + break; + case 70: + ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, 1); + state = 75; + break; + case 80: + ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, 1); + state = 90; + break; + case 100: + ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, 1); + state = 110; + break; + case 130: + ModbusReadRegisters(thisDev.Addr.Read.InputRegisters, 300); + state = 140; + break; + case 160: + ModbusWriteBitsB(thisDev.Addr.Write.OutputBits, 3000, s15); + break; + case 170: + ModbusWriteBitsB(thisDev.Addr.Write.OutputBits, 1000, s15); + break; + case 190: + ModbusReadBits(thisDev.Addr.Read.InputBits, 1); + thisDev.ReceiveWindow = 0xFF; // Set receive window to maximum to test the limit + state = 900; + break; + default: + writeDbg(MbError, "I did not expect state %d in timer timr!", state); + break; + } } \ No newline at end of file diff --git a/Modbus-CAPL/include/CAPL/include/Common.cin b/Modbus-CAPL/include/CAPL/include/Common.cin index 667050e..94945d0 100644 --- a/Modbus-CAPL/include/CAPL/include/Common.cin +++ b/Modbus-CAPL/include/CAPL/include/Common.cin @@ -8,31 +8,31 @@ variables { - enum DebugLvl { - Debug = 0x00, - AlgoDebug = 0x02, - ConnDebug = 0x04, - MbDebug = 0x07, + enum DebugLvl { + Debug = 0x00, + AlgoDebug = 0x02, + ConnDebug = 0x04, + MbDebug = 0x07, - Info = 0x10, - AlgoInfo = 0x12, - ConnInfo = 0x14, - MbInfo = 0x17, + Info = 0x10, + AlgoInfo = 0x12, + ConnInfo = 0x14, + MbInfo = 0x17, - Warning = 0x20, - AlgoWarning = 0x22, - ConnWarning = 0x24, - MbWarning = 0x27, + Warning = 0x20, + AlgoWarning = 0x22, + ConnWarning = 0x24, + MbWarning = 0x27, - Error = 0x30, - AlgoError = 0x32, - ConnError = 0x34, - MbError = 0x37, + Error = 0x30, + AlgoError = 0x32, + ConnError = 0x34, + MbError = 0x37, - Mute = 0xFF + Mute = 0xFF }; - char DebugLvlStr[4][8] = {"Debug", "Info", "Warning", "Error"}; - enum DebugLvl OutputDebugLevel = Debug; + char DebugLvlStr[4][8] = {"Debug", "Info", "Warning", "Error"}; + enum DebugLvl OutputDebugLevel = Debug; } // This method creates a format string in 'msg' which can then be passed to writeLineEx(). @@ -40,221 +40,221 @@ variables /// 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)); + strncpy(msg, "<%NODE_NAME%> ", elCount(msg)); + strncat(msg, DebugLvlStr[lVl], elCount(msg)); + strncat(msg, ": ", elCount(msg)); + strncat(msg, format, elCount(msg)-strlen(msg)); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[]) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], char string[]) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, string); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, string); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], char string1[], char string2[]) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, string1, string2); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, string1, string2); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], char string1[], char string2[], long num1, long num2) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, string1, string2, num1, num2); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, string1, string2, num1, num2); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], char string1[], char string2[], long num1) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, string1, string2, num1); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, string1, string2, num1); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], long num, char string[]) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num, string); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num, string); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], char string[], long num) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, string, num); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, string, num); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], char string[], long num, float fl) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, string, num, fl); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, string, num, fl); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], long num1) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, char string[]) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1, num2, string); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1, num2, string); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1, num2); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1, num2); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, long num3) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1, num2, num3); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1, num2, num3); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, long num3, char str[]) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1, num2, num3, str); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1, num2, num3, str); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, long num3, long num4) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1, num2, num3, num4); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1, num2, num3, num4); } // This method prints the specified arguments to CAPL/Write Window if the debug level is high enough /// void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, long num3, long num4, long num5, long num6) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1, num2, num3, num4, num5, num6); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1, num2, num3, num4, num5, num6); } @@ -263,84 +263,84 @@ void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, long num3, // You have to allocate 60 bytes for 'result' 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; + 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] = ' '; - } + 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; + if (elCount(bin) > 20) // trailing "..." + { + result[56] = '.'; + result[57] = '.'; + result[58] = '.'; + } + result[binsz * 3 - 1] = 0; } // This method converts the lower nibbles of the bytes in 'bin' to a readable string in hex format ("X X X X") // You have to allocate 40 bytes for 'result' 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; + 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] = ' '; - } + 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; + if (elCount(bin) > 20) // trailing "..." + { + result[36] = '.'; + result[37] = '.'; + result[38] = '.'; + } + result[binsz * 2 - 1] = 0; } // This method converts the words in 'bin' to a readable string in hex format ("XXXX XXXX XXXX XXXX") // You have to allocate 100 bytes for 'result' 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; + 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] = ' '; - } + 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; + if (elCount(bin) > 20) // trailing "..." + { + result[96] = '.'; + result[97] = '.'; + result[98] = '.'; + } + result[(byte)(binsz * 2.5) - 1] = 0; } \ No newline at end of file diff --git a/Modbus-CAPL/include/CAPL/include/DeviceInformation.cin b/Modbus-CAPL/include/CAPL/include/DeviceInformation.cin index 7b9777d..1c97635 100644 --- a/Modbus-CAPL/include/CAPL/include/DeviceInformation.cin +++ b/Modbus-CAPL/include/CAPL/include/DeviceInformation.cin @@ -13,55 +13,55 @@ /// This file is used at two positions: The majority of the functions are used to analyze devices when making the config. The minority has to be called when initiating a Modbus client so it knows about the addresses and window size. variables { - // This structure is used by the Modbus Client. It describes the device - struct - { - struct // Start addresses - { - struct // Start addresses Read - { - word OutputBits; - word OutputRegisters; - word InputBits; - word InputRegisters; - } Read; - struct // Start addresses Write - { - word OutputBits; - word OutputRegisters; - } Write; - } Addr; - word MaxBitCount; // Max number of bits - word MaxRegisterCount; // Max number of registers - byte ReceiveWindow; - } thisDev; + // This structure is used by the Modbus Client. It describes the device + struct + { + struct // Start addresses + { + struct // Start addresses Read + { + word OutputBits; + word OutputRegisters; + word InputBits; + word InputRegisters; + } Read; + struct // Start addresses Write + { + word OutputBits; + word OutputRegisters; + } Write; + } Addr; + word MaxBitCount; // Max number of bits + word MaxRegisterCount; // Max number of registers + byte ReceiveWindow; + } thisDev; - enum Vendor // The Vendor enum. All Vendors have to listed here and all listed vendors have to be implemented in this file - { - All = 0xFF, - Wago = 23, // Wago - BuR = 2 // B&R - }; - struct deviceIOs // A structure which contains quantity information about connected IO. Used in MakeConfig. These info will be written into the SysVars - { - byte InputRegisters; // Count of AI - word InputBits; // Count of DI - byte OutputRegisters; // Count of AO - word OutputBits; // Count of DO - char Modules[1024]; // A string representing the connected modules - }; - struct device // A structure that contains information about an Modbus device. Used in MakeConfig. - { - char Ip[16]; // String: The IP address - 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 - struct deviceIOs DeviceIOs; // A structure with more information about IOs - }; + enum Vendor // The Vendor enum. All Vendors have to listed here and all listed vendors have to be implemented in this file + { + All = 0xFF, + Wago = 23, // Wago + BuR = 2 // B&R + }; + struct deviceIOs // A structure which contains quantity information about connected IO. Used in MakeConfig. These info will be written into the SysVars + { + byte InputRegisters; // Count of AI + word InputBits; // Count of DI + byte OutputRegisters; // Count of AO + word OutputBits; // Count of DO + char Modules[1024]; // A string representing the connected modules + }; + struct device // A structure that contains information about an Modbus device. Used in MakeConfig. + { + char Ip[16]; // String: The IP address + 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 + struct deviceIOs DeviceIOs; // A structure with more information about IOs + }; } // This is for both the normal client and for making the sysvars. @@ -69,39 +69,39 @@ variables /// void DeviceInit(byte vendor) { - switch ((enum Vendor) vendor) - { - case All: // information that may apply to all devices - thisDev.MaxBitCount = 0x0100; - thisDev.MaxRegisterCount = 0x0100; - thisDev.ReceiveWindow = 1; - break; - case Wago: - thisDev.Addr.Read.InputBits = 0x0000; // Wago inputs start at 0x000 - thisDev.Addr.Read.InputRegisters = 0x0000; - thisDev.Addr.Read.OutputBits = 0x0200; // Wago reading outputs start at 0x200 - thisDev.Addr.Read.OutputRegisters = 0x0200; - thisDev.Addr.Write.OutputBits = 0x0000; // Wago writing outputs start at 0x000 - thisDev.Addr.Write.OutputRegisters = 0x0000; - thisDev.MaxBitCount = 0x0200; // Wago allows up to 512 digital inputs (trial & error) - thisDev.MaxRegisterCount = 0x0100; // Wago allows up to 256 analog inputs (trial & error) - thisDev.ReceiveWindow = 5; // Wago can handle 5 requests simultaneously - break; - case BuR: - thisDev.Addr.Read.InputBits = 0x0000; // B&R inputs start at 0x000 - thisDev.Addr.Read.InputRegisters = 0x0000; - thisDev.Addr.Read.OutputBits = 0x0000; // B&R reading digital outputs start at 0x000 - thisDev.Addr.Read.OutputRegisters = 0x0800; // B&R reading analog outputs start at 0x800 - thisDev.Addr.Write.OutputBits = 0x0000; // B&R writing outputs start at 0x000 - thisDev.Addr.Write.OutputRegisters = 0x0000; - thisDev.MaxBitCount = 0x4000; // B&R allows up to 16384 digital inputs - thisDev.MaxRegisterCount = 0x0800; // B&R allows up to 2048 analog inputs - thisDev.ReceiveWindow = 8; // B&R can handle 8 requests at a time - break; - default: - OnModbusClientPanics(VendorIdUnknown); - break; - } + switch ((enum Vendor) vendor) + { + case All: // information that may apply to all devices + thisDev.MaxBitCount = 0x0100; + thisDev.MaxRegisterCount = 0x0100; + thisDev.ReceiveWindow = 1; + break; + case Wago: + thisDev.Addr.Read.InputBits = 0x0000; // Wago inputs start at 0x000 + thisDev.Addr.Read.InputRegisters = 0x0000; + thisDev.Addr.Read.OutputBits = 0x0200; // Wago reading outputs start at 0x200 + thisDev.Addr.Read.OutputRegisters = 0x0200; + thisDev.Addr.Write.OutputBits = 0x0000; // Wago writing outputs start at 0x000 + thisDev.Addr.Write.OutputRegisters = 0x0000; + thisDev.MaxBitCount = 0x0200; // Wago allows up to 512 digital inputs (trial & error) + thisDev.MaxRegisterCount = 0x0100; // Wago allows up to 256 analog inputs (trial & error) + thisDev.ReceiveWindow = 5; // Wago can handle 5 requests simultaneously + break; + case BuR: + thisDev.Addr.Read.InputBits = 0x0000; // B&R inputs start at 0x000 + thisDev.Addr.Read.InputRegisters = 0x0000; + thisDev.Addr.Read.OutputBits = 0x0000; // B&R reading digital outputs start at 0x000 + thisDev.Addr.Read.OutputRegisters = 0x0800; // B&R reading analog outputs start at 0x800 + thisDev.Addr.Write.OutputBits = 0x0000; // B&R writing outputs start at 0x000 + thisDev.Addr.Write.OutputRegisters = 0x0000; + thisDev.MaxBitCount = 0x4000; // B&R allows up to 16384 digital inputs + thisDev.MaxRegisterCount = 0x0800; // B&R allows up to 2048 analog inputs + thisDev.ReceiveWindow = 8; // B&R can handle 8 requests at a time + break; + default: + OnModbusClientPanics(VendorIdUnknown); + break; + } } @@ -113,120 +113,120 @@ void DeviceInit(byte vendor) /// void _DeviceParseCode(word dev, enum Vendor vendor, struct deviceIOs dios) { - byte input; // Yes: INPUT module; No: OUTPUT module - byte numChannels; // Quantity of channels - char module[10]; - strncpy(module, "..%d,", elCount(module)); + byte input; // Yes: INPUT module; No: OUTPUT module + byte numChannels; // Quantity of channels + char module[10]; + strncpy(module, "..%d,", elCount(module)); - switch(vendor) - { - case Wago: // if this is a Wago device - if (dev & 0x8000) // Digital Module - { - module[0] = 'D'; - numChannels = (dev >> 8) & 0x007F; + switch(vendor) + { + case Wago: // if this is a Wago device + if (dev & 0x8000) // Digital Module + { + module[0] = 'D'; + numChannels = (dev >> 8) & 0x007F; - if (dev & 0x0001) // Input Module - input = 1; - else if (dev & 0x0002) // Output Module - input = 0; - else // mhm... What is it? Input and Output? - writeDbg(AlgoError, "DeviceParseCode: Device code 0x%X cannot be decoded", dev); - } - else // Analog (=Complex) module - { - module[0] = 'A'; - // List of available 750 modules: - // AI: http://www.wago.com/wagoweb/documentation/navigate/nm0dx__d.htm - // AO: http://www.wago.com/wagoweb/documentation/navigate/nm0dy__d.htm - switch (dev) - { - case 881: // devices that have no inputs/outputs - return; - case 491: // devices that have 1 inputs - input = 1; - numChannels = 1; - break; - case 452: // devices that have 2 inputs - case 465: - case 470: - case 472: - case 480: - case 454: - case 473: - case 474: - case 466: - case 484: - case 485: - case 492: - case 482: - case 475: - case 467: - case 477: - case 478: - case 456: - case 479: - case 476: - case 483: - case 461: - case 481: - case 462: - case 469: - case 487: - input = 1; - numChannels = 2; - break; - case 493: // devices that have 3 inputs - case 494: - case 495: - input = 1; - numChannels = 3; - break; - case 459: // devices that have 4 inputs - case 453: - case 455: - case 468: - case 457: - case 464: - case 460: - case 463: - input = 1; - numChannels = 4; - break; - case 552: // devices that have 2 outputs - case 585: - case 563: - case 554: - case 550: - case 560: - case 562: - case 556: - input = 0; - numChannels = 2; - break; - case 555: // devices that have 4 outputs - case 553: - case 557: - case 559: - input = 0; - numChannels = 4; - break; - default: // unknown device - writeDbg(AlgoInfo, "Connected device: 750-%d", dev); - return; - } - } - break; // switch(vendor) - default: - writeDbg(AlgoError, "ParseDeviceCode: Unknown vendor id: %d", vendor); - OnModbusClientPanics(VendorIdUnknown); - return; - } - - module[1] = input ? 'I' : 'O'; // Set input/output char + if (dev & 0x0001) // Input Module + input = 1; + else if (dev & 0x0002) // Output Module + input = 0; + else // mhm... What is it? Input and Output? + writeDbg(AlgoError, "DeviceParseCode: Device code 0x%X cannot be decoded", dev); + } + else // Analog (=Complex) module + { + module[0] = 'A'; + // List of available 750 modules: + // AI: http://www.wago.com/wagoweb/documentation/navigate/nm0dx__d.htm + // AO: http://www.wago.com/wagoweb/documentation/navigate/nm0dy__d.htm + switch (dev) + { + case 881: // devices that have no inputs/outputs + return; + case 491: // devices that have 1 inputs + input = 1; + numChannels = 1; + break; + case 452: // devices that have 2 inputs + case 465: + case 470: + case 472: + case 480: + case 454: + case 473: + case 474: + case 466: + case 484: + case 485: + case 492: + case 482: + case 475: + case 467: + case 477: + case 478: + case 456: + case 479: + case 476: + case 483: + case 461: + case 481: + case 462: + case 469: + case 487: + input = 1; + numChannels = 2; + break; + case 493: // devices that have 3 inputs + case 494: + case 495: + input = 1; + numChannels = 3; + break; + case 459: // devices that have 4 inputs + case 453: + case 455: + case 468: + case 457: + case 464: + case 460: + case 463: + input = 1; + numChannels = 4; + break; + case 552: // devices that have 2 outputs + case 585: + case 563: + case 554: + case 550: + case 560: + case 562: + case 556: + input = 0; + numChannels = 2; + break; + case 555: // devices that have 4 outputs + case 553: + case 557: + case 559: + input = 0; + numChannels = 4; + break; + default: // unknown device + writeDbg(AlgoInfo, "Connected device: 750-%d", dev); + return; + } + } + break; // switch(vendor) + default: + writeDbg(AlgoError, "ParseDeviceCode: Unknown vendor id: %d", vendor); + OnModbusClientPanics(VendorIdUnknown); + return; + } + + module[1] = input ? 'I' : 'O'; // Set input/output char - snprintf(module, elCount(module), module, numChannels); // --> DO%d, AO%d, DI%d, AI%d - strncat(dios.Modules, module, elCount(dios.Modules)); // Append new module to existing module string + snprintf(module, elCount(module), module, numChannels); // --> DO%d, AO%d, DI%d, AI%d + strncat(dios.Modules, module, elCount(dios.Modules)); // Append new module to existing module string } // This function requests more information from the device and returns the count of expected responses (Modbus telegrams). It is called by AnalyzeDevices() in MakeConfig @@ -235,32 +235,32 @@ void _DeviceParseCode(word dev, enum Vendor vendor, struct deviceIOs dios) /// byte _DeviceGetInformation(enum Vendor vendor) { - switch (vendor) - { - case Wago: - ModbusReadRegisters(0x2011, 1); // Serial Code - ModbusReadRegisters(0x2012, 1); // Device Code - ModbusReadRegisters(0x1022, 1); // Number of AOs (= size in bits) - ModbusReadRegisters(0x1023, 1); // Number of AIs (= size in bits) - ModbusReadRegisters(0x1024, 1); // Number of DOs - ModbusReadRegisters(0x1025, 1); // Number of DIs - ModbusReadRegisters(0x2030, 65); // Connected IO 1 - ModbusReadRegisters(0x2031, 64); // Connected IO 2 - ModbusReadRegisters(0x2032, 64); // Connected IO 3 - ModbusReadRegisters(0x2033, 63); // Connected IO 4 - return 10; // 10 is the number of lines above (number of responses that we expect) - case BuR: - ModbusReadRegisters(0x1083, 1); // Product Code - ModbusReadRegisters(0x1101, 1); // Number of AIs - ModbusReadRegisters(0x1103, 1); // Number of AOs - ModbusReadRegisters(0x1105, 1); // Number of DIs - ModbusReadRegisters(0x1107, 1); // Number of DOs - return 5; // 5 is the number of lines above (number of responses that we expect) - default: - writeDbg(AlgoError, "DeviceGetInformation: Unknown vendor id: %d", vendor); - OnModbusClientPanics(VendorIdUnknown); - } - return 0; + switch (vendor) + { + case Wago: + ModbusReadRegisters(0x2011, 1); // Serial Code + ModbusReadRegisters(0x2012, 1); // Device Code + ModbusReadRegisters(0x1022, 1); // Number of AOs (= size in bits) + ModbusReadRegisters(0x1023, 1); // Number of AIs (= size in bits) + ModbusReadRegisters(0x1024, 1); // Number of DOs + ModbusReadRegisters(0x1025, 1); // Number of DIs + ModbusReadRegisters(0x2030, 65); // Connected IO 1 + ModbusReadRegisters(0x2031, 64); // Connected IO 2 + ModbusReadRegisters(0x2032, 64); // Connected IO 3 + ModbusReadRegisters(0x2033, 63); // Connected IO 4 + return 10; // 10 is the number of lines above (number of responses that we expect) + case BuR: + ModbusReadRegisters(0x1083, 1); // Product Code + ModbusReadRegisters(0x1101, 1); // Number of AIs + ModbusReadRegisters(0x1103, 1); // Number of AOs + ModbusReadRegisters(0x1105, 1); // Number of DIs + ModbusReadRegisters(0x1107, 1); // Number of DOs + return 5; // 5 is the number of lines above (number of responses that we expect) + default: + writeDbg(AlgoError, "DeviceGetInformation: Unknown vendor id: %d", vendor); + OnModbusClientPanics(VendorIdUnknown); + } + return 0; } // This function parses the received registers (requested by DeviceGetInformation()) @@ -268,71 +268,71 @@ byte _DeviceGetInformation(enum Vendor vendor) /// void _DeviceParseRegister(struct device device, word address, word data[], word count) { - byte i; + byte i; - //writeDbg(Debug, "_DeviceParseRegister: Address: 0x%04X, Data[0]: %d", address, data[0]); - switch (device.Vendor) - { - case Wago: - // Parse the received data - switch (address) - { - case 0x2011: // Serial Code - device.serialCode = data[0]; - break; - case 0x2012: // Device Code - device.deviceCode = data[0]; - break; - case 0x1022: // Number of output registers (AO) - device.DeviceIOs.OutputRegisters = data[0] / 16; // Wago returns the allocated bits. - break; - case 0x1023: // Number of input registers (AI) - device.DeviceIOs.InputRegisters = data[0] / 16; - break; - case 0x1024: // Number of output bits (DO) - device.DeviceIOs.OutputBits = data[0]; - break; - case 0x1025: // Number of input bits (DI) - device.DeviceIOs.InputBits = data[0]; - break; - case 0x2030: // Codes of connected modules. Pass to DeviceParseCode() - case 0x2031: - case 0x2032: - case 0x2033: - for (i = 0; i < count; i++) - { - if (data[i] == 0x0000) // No more devices --> end - break; - _DeviceParseCode(data[i], device.Vendor, device.DeviceIOs); - } - break; - } - break; - case BuR: - // Parse the received data - switch (address) - { - case 0x1083: // Product Code - device.serialCode = data[0]; - break; - case 0x1101: // Number of input registers (AI) - device.DeviceIOs.InputRegisters = data[0]; - break; - case 0x1103: // Number of output registers (AO) - device.DeviceIOs.OutputRegisters = data[0]; - break; - case 0x1105: // Number of input bits (DI) - device.DeviceIOs.InputBits = data[0] * 8; // Unfortunately this is quite imprecise: in the process image one module will always fill a whole number of bytes. - // So 2 DI4 modules not allocate not 2*4 bit = 1 byte, but 2*8 bit = 16 bit = 2 byte - // See Modbus X20BC0087 documentation v1.11 p. 22 - break; - case 0x1107: // Number of output bits (DO) - device.DeviceIOs.OutputBits = data[0] * 8; - break; - } - break; - default: - writeDbg(AlgoError, "DeviceGetInformation: Unknown vendor id: %d", device.Vendor); - OnModbusClientPanics(VendorIdUnknown); - } + //writeDbg(Debug, "_DeviceParseRegister: Address: 0x%04X, Data[0]: %d", address, data[0]); + switch (device.Vendor) + { + case Wago: + // Parse the received data + switch (address) + { + case 0x2011: // Serial Code + device.serialCode = data[0]; + break; + case 0x2012: // Device Code + device.deviceCode = data[0]; + break; + case 0x1022: // Number of output registers (AO) + device.DeviceIOs.OutputRegisters = data[0] / 16; // Wago returns the allocated bits. + break; + case 0x1023: // Number of input registers (AI) + device.DeviceIOs.InputRegisters = data[0] / 16; + break; + case 0x1024: // Number of output bits (DO) + device.DeviceIOs.OutputBits = data[0]; + break; + case 0x1025: // Number of input bits (DI) + device.DeviceIOs.InputBits = data[0]; + break; + case 0x2030: // Codes of connected modules. Pass to DeviceParseCode() + case 0x2031: + case 0x2032: + case 0x2033: + for (i = 0; i < count; i++) + { + if (data[i] == 0x0000) // No more devices --> end + break; + _DeviceParseCode(data[i], device.Vendor, device.DeviceIOs); + } + break; + } + break; + case BuR: + // Parse the received data + switch (address) + { + case 0x1083: // Product Code + device.serialCode = data[0]; + break; + case 0x1101: // Number of input registers (AI) + device.DeviceIOs.InputRegisters = data[0]; + break; + case 0x1103: // Number of output registers (AO) + device.DeviceIOs.OutputRegisters = data[0]; + break; + case 0x1105: // Number of input bits (DI) + device.DeviceIOs.InputBits = data[0] * 8; // Unfortunately this is quite imprecise: in the process image one module will always fill a whole number of bytes. + // So 2 DI4 modules not allocate not 2*4 bit = 1 byte, but 2*8 bit = 16 bit = 2 byte + // See Modbus X20BC0087 documentation v1.11 p. 22 + break; + case 0x1107: // Number of output bits (DO) + device.DeviceIOs.OutputBits = data[0] * 8; + break; + } + break; + default: + writeDbg(AlgoError, "DeviceGetInformation: Unknown vendor id: %d", device.Vendor); + OnModbusClientPanics(VendorIdUnknown); + } } \ No newline at end of file diff --git a/Modbus-CAPL/include/CAPL/include/ModbusClient.cin b/Modbus-CAPL/include/CAPL/include/ModbusClient.cin index 96290ed..2b36696 100644 --- a/Modbus-CAPL/include/CAPL/include/ModbusClient.cin +++ b/Modbus-CAPL/include/CAPL/include/ModbusClient.cin @@ -8,32 +8,32 @@ /// The Modbus telegrams are distinguished in the queues by their TxID /// This Modbus Client file provides following methods -/// - ModbusInit() Prepare anything that Modbus works (open connection etc.) -/// - ModbusEnd() Clean up everything (close connection etc.) +/// - ModbusInit() Prepare anything that Modbus works (open connection etc.) +/// - ModbusEnd() Clean up everything (close connection etc.) -/// - ModbusReadOutBits() Modbus Function Code: 0x01 (Read Discrete inputs) -/// - ModbusReadInBits() Modbus Function Code: 0x02 (Read Coils) +/// - ModbusReadOutBits() Modbus Function Code: 0x01 (Read Discrete inputs) +/// - ModbusReadInBits() Modbus Function Code: 0x02 (Read Coils) /// --> results in OnModbusReadBitsSuccess() or OnModbusReadBitsFailed() (have to be implemented by the higher layer) -/// - ModbusReadOutRegisters() Modbus Function Code: 0x03 (Read Input registers) -/// - ModbusReadInRegisters() Modbus Function Code: 0x04 (Read Holding registers) +/// - ModbusReadOutRegisters() Modbus Function Code: 0x03 (Read Input registers) +/// - ModbusReadInRegisters() Modbus Function Code: 0x04 (Read Holding registers) /// --> results in OnModbusReadRegistersSuccess() or OnModbusReadRegistersFailed() (have to be implemented by the higher layer) -/// - ModbusWriteBit() Modbus Function Code: 0x05 (Write Coil) +/// - ModbusWriteBit() Modbus Function Code: 0x05 (Write Coil) /// --> results in OnModbusWriteBitSuccess() or OnModbusWriteBitFailed() (have to be implemented by the higher layer) -/// - ModbusWriteRegister() Modbus Function Code: 0x06 (Write Holding register) +/// - ModbusWriteRegister() Modbus Function Code: 0x06 (Write Holding register) /// --> results in OnModbusWriteRegisterSuccess() or OnModbusWriteRegisterFailed() (have to be implemented by the higher layer) -/// - ModbusWriteBits() Modbus Function Code: 0x0F (Write multiple Coils) -/// - ModbusWriteBitsB() Wrapper for ModbusWriteBits: Encodes a bit array with size N to an array with size N/8 +/// - ModbusWriteBits() Modbus Function Code: 0x0F (Write multiple Coils) +/// - ModbusWriteBitsB() Wrapper for ModbusWriteBits: Encodes a bit array with size N to an array with size N/8 /// --> results in OnModbusWriteBitsSuccess() or OnModbusWriteBitsFailed() (have to be implemented by the higher layer) -/// - ModbusWriteRegisters() Modbus Function Code: 0x10 (Write multiple Holding registers) -/// - ModbusReadWriteRegisters() Modbus Function Code: 0x17 (Read/Write multiple Holding registers) +/// - ModbusWriteRegisters() Modbus Function Code: 0x10 (Write multiple Holding registers) +/// - ModbusReadWriteRegisters() Modbus Function Code: 0x17 (Read/Write multiple Holding registers) /// --> results in OnModbusWriteRegistersSuccess() or OnModbusWriteRegistersFailed() (have to be implemented by the higher layer) -/// - ModbusWriteMasks() Modbus Function Code: 0x10 (Mask Write Holding registers) +/// - ModbusWriteMasks() Modbus Function Code: 0x10 (Mask Write Holding registers) /// --> results in OnModbusWriteMasksSuccess() or OnModbusWriteMasksFailed() (have to be implemented by the higher layer) /// Additionally the highest layer have to implement OnModbusClientPanics() which all layers will call and pass errors. The highest layer may decide what to do with this error. @@ -78,30 +78,30 @@ includes { - #include "ModbusStructs.cin" // We only depend on the structures - // The network layer will be included by the higher layer + #include "ModbusStructs.cin" // We only depend on the structures + // The network layer will be included by the higher layer } variables { - msTimer gtModbusRobin; // Timer that sends the packets and watches for timeouts - word gTxID = 0x0000; // Transaction Identifier for the next Modbus packet. Used as index for gQueue - word gRequestTimeout; // Timeout of a packet [ms] - byte gMaxTransmissionCount; // Maximum number of transmissions (after timeouts) + msTimer gtModbusRobin; // Timer that sends the packets and watches for timeouts + word gTxID = 0x0000; // Transaction Identifier for the next Modbus packet. Used as index for gQueue + word gRequestTimeout; // Timeout of a packet [ms] + byte gMaxTransmissionCount; // Maximum number of transmissions (after timeouts) - // Storage element for pending, sent and acknowledge requests, associated by TxID - struct QueueElement - { - word TimeoutTicks; // Time counter [ms]. Used to watch for timeouts (see gRequestTimeout) - byte Timeouts; - byte SendTries; - word Length; - byte Buffer[gModbusMaxTelegramSize]; - }; - // Storages with these requests - struct QueueElement gQueuePending[long, 2]; - struct QueueElement gQueueSent[long, 2]; - struct QueueElement gQueueAck[long, 2]; + // Storage element for pending, sent and acknowledge requests, associated by TxID + struct QueueElement + { + word TimeoutTicks; // Time counter [ms]. Used to watch for timeouts (see gRequestTimeout) + byte Timeouts; + byte SendTries; + word Length; + byte Buffer[gModbusMaxTelegramSize]; + }; + // Storages with these requests + struct QueueElement gQueuePending[long, 2]; + struct QueueElement gQueueSent[long, 2]; + struct QueueElement gQueueAck[long, 2]; } // This method prepares anything that sending Modbus requests works. Currently this is only the connection. @@ -109,30 +109,30 @@ variables // the timeout value and the number of retries that shall be performed after a timeout void ModbusInit(char Remote_IP[], word remotePort, word requestTimeout, byte maxTransmissions) { - _ModbusConnectTo(Remote_IP, remotePort); - gRequestTimeout = requestTimeout; - gMaxTransmissionCount = maxTransmissions; + _ModbusConnectTo(Remote_IP, remotePort); + gRequestTimeout = requestTimeout; + gMaxTransmissionCount = maxTransmissions; } // This method cleans up everything: Closes the connection, clears the queues and stops the timer // It has to be called by the user/modbus client at the end of the measurement void ModbusEnd() { - _ModbusDisconnect(); - gQueuePending.Clear(); - gQueueSent.Clear(); - gtModbusRobin.Cancel(); + _ModbusDisconnect(); + gQueuePending.Clear(); + gQueueSent.Clear(); + gtModbusRobin.Cancel(); } // This method fills the ModbusApHeader structure 'mbap'. // It gets called by the Modbus request methods void _ModbusMakeHeader(struct ModbusApHeader mbap, word length, enum ModbusFuncCode funcCode) { - 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 - mbap.FuncCode = funcCode; // [1] Function Code + 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 + mbap.FuncCode = funcCode; // [1] Function Code } @@ -142,107 +142,107 @@ void _ModbusMakeHeader(struct ModbusApHeader mbap, word length, enum ModbusFuncC // This method will submit a request to the Modbus server to read discrete inputs void ModbusReadInBits(word address, long count) { - _ModbusReadBits(ReadBitsIn, address, count); + _ModbusReadBits(ReadBitsIn, address, count); } /// // This method will submit a request to the Modbus server to read discrete inputs void ModbusReadBits(word address, long count) { - _ModbusReadBits(ReadBitsIn, address, count); + _ModbusReadBits(ReadBitsIn, address, count); } /// // This method will submit a request to the Modbus server to read coils void ModbusReadOutBits(word address, long count) { - _ModbusReadBits(ReadBitsOut, address, count); + _ModbusReadBits(ReadBitsOut, address, count); } /// // This method will submit a request to the Modbus server to read discrete inputs or coils void _ModbusReadBits(enum ModbusFuncCode funcCode, word address, long count) { - const byte length = __size_of(struct ModbusReqRead); - byte buffer[length]; - word curCount; - struct ModbusReqRead mbreq; - word devStartAddr, devEndAddr; + const byte length = __size_of(struct ModbusReqRead); + byte buffer[length]; + word curCount; + struct ModbusReqRead mbreq; + word devStartAddr, devEndAddr; - // Check the function code. If this method was private we would not need this - switch (funcCode) - { - case ReadBitsOut: - case ReadBitsIn: - break; - default: - writeDbg(MbError, "_ModbusReadBits: Got incorrect function code 0x%02X!", funcCode); - OnModbusClientPanics(FuncCodeIncorrect); - return; - } + // Check the function code. If this method was private we would not need this + switch (funcCode) + { + case ReadBitsOut: + case ReadBitsIn: + break; + default: + writeDbg(MbError, "_ModbusReadBits: Got incorrect function code 0x%02X!", funcCode); + OnModbusClientPanics(FuncCodeIncorrect); + return; + } - devStartAddr = funcCode == ReadBitsOut ? thisDev.Addr.Read.OutputBits : thisDev.Addr.Read.InputBits; // The start address of the bits - devEndAddr = devStartAddr + thisDev.MaxBitCount; // The address behind the last bit - if (address < devStartAddr) // Oh, reading at the wrong address? - { - writeDbg(MbError, "_ModbusReadBits: The given start address 0x%04X is smaller than the obligatory start address 0x%04X", address, devStartAddr); - OnModbusClientPanics(AddressFailure); - return; - } + devStartAddr = funcCode == ReadBitsOut ? thisDev.Addr.Read.OutputBits : thisDev.Addr.Read.InputBits; // The start address of the bits + devEndAddr = devStartAddr + thisDev.MaxBitCount; // The address behind the last bit + if (address < devStartAddr) // Oh, reading at the wrong address? + { + writeDbg(MbError, "_ModbusReadBits: The given start address 0x%04X is smaller than the obligatory start address 0x%04X", address, devStartAddr); + OnModbusClientPanics(AddressFailure); + return; + } - // FC 0x01: Read Coils (DO), FC 0x02: Read Discret Inputs (DI) - while (count > 0 && address < devEndAddr) - { - curCount = count > gMaxBitsPerRead ? gMaxBitsPerRead : count; // divide packets that are too large - if (address + curCount > devEndAddr) // upper bound in process image - { - writeDbg(MbWarning, "_ModbusReadBits: Impossible to read %d bits at 0x%04X. Changed count to %d.", curCount, address, devEndAddr - address); - curCount = devEndAddr - address; - } + // FC 0x01: Read Coils (DO), FC 0x02: Read Discret Inputs (DI) + while (count > 0 && address < devEndAddr) + { + curCount = count > gMaxBitsPerRead ? gMaxBitsPerRead : count; // divide packets that are too large + if (address + curCount > devEndAddr) // upper bound in process image + { + writeDbg(MbWarning, "_ModbusReadBits: Impossible to read %d bits at 0x%04X. Changed count to %d.", curCount, address, devEndAddr - address); + curCount = devEndAddr - address; + } - _ModbusMakeHeader(mbreq.Header, length, funcCode); + _ModbusMakeHeader(mbreq.Header, length, funcCode); - mbreq.Address = address; // [2] Start address - mbreq.Count = curCount; // [2] Number of items; 1:max 2000=0x7D0 + mbreq.Address = address; // [2] Start address + mbreq.Count = curCount; // [2] Number of items; 1:max 2000=0x7D0 - writeDbg(MbDebug, "Sending 'Read Bits' (0x01) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, address, curCount); + writeDbg(MbDebug, "Sending 'Read Bits' (0x01) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, address, curCount); - memcpy_h2n(buffer, mbreq); - _ModbusSend(buffer, length, mbreq.Header.TxID); + memcpy_h2n(buffer, mbreq); + _ModbusSend(buffer, length, mbreq.Header.TxID); - count -= gMaxBitsPerRead; - address += gMaxBitsPerRead; - } + count -= gMaxBitsPerRead; + address += gMaxBitsPerRead; + } } /// // This method will be called by _OnModbusReceive2OnePacket() when receiving data void _OnModbusReceiveBits(byte buffer[]) { - struct ModbusResReceiveBits mbres; - struct ModbusReqRead mbreq; - byte bitStatus[gMaxBitsPerRead]; - word numBits; - byte i, j; + struct ModbusResReceiveBits mbres; + struct ModbusReqRead mbreq; + byte bitStatus[gMaxBitsPerRead]; + word numBits; + byte i, j; - memcpy_n2h(mbres, buffer); - memcpy_n2h(mbreq, gQueueAck[mbres.Header.TxID].Buffer); + memcpy_n2h(mbres, buffer); + memcpy_n2h(mbreq, gQueueAck[mbres.Header.TxID].Buffer); - writeDbg(MbInfo, "Received %d bits from 0x%04X", mbreq.Count, mbreq.Address); - for (i = 0; i < mbres.ByteCount; i++) // decode the received data - { - for (j = 0; j < 8; j++) - { - bitStatus[8*i+j] = (mbres.Data[i] >> j) & 0x01; - } - } + writeDbg(MbInfo, "Received %d bits from 0x%04X", mbreq.Count, mbreq.Address); + for (i = 0; i < mbres.ByteCount; i++) // decode the received data + { + for (j = 0; j < 8; j++) + { + bitStatus[8*i+j] = (mbres.Data[i] >> j) & 0x01; + } + } - OnModbusReadBitsSuccess(mbres, bitStatus, mbreq); + OnModbusReadBitsSuccess(mbres, bitStatus, mbreq); } /// // This method will be called by _OnModbusReceive2Exceptions() when an exception occured void _OnModbusReceiveBitsException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while reading bits: %s", ModbusExceptions[ex-1]); - OnModbusReadBitsFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while reading bits: %s", ModbusExceptions[ex-1]); + OnModbusReadBitsFailed(Exception, ex, mbap); } @@ -254,98 +254,98 @@ void _OnModbusReceiveBitsException(struct ModbusApHeader mbap, enum ModbusExcept // This method will submit a request to the Modbus server to read input registers void ModbusReadInRegisters(word address, long count) { - _ModbusReadRegisters(ReadRegistersIn, address, count); + _ModbusReadRegisters(ReadRegistersIn, address, count); } /// // This method will submit a request to the Modbus server to read holding registers void ModbusReadRegisters(word address, long count) { - _ModbusReadRegisters(ReadRegistersIn, address, count); + _ModbusReadRegisters(ReadRegistersIn, address, count); } /// // This method will submit a request to the Modbus server to read holding registers void ModbusReadOutRegisters(word address, long count) { - _ModbusReadRegisters(ReadRegistersOut, address, count); + _ModbusReadRegisters(ReadRegistersOut, address, count); } /// // This method will submit a request to the Modbus server to read input or holding registers void _ModbusReadRegisters(enum ModbusFuncCode funcCode, word address, long count) { - const byte length = __size_of(struct ModbusReqRead); - byte buffer[length]; - word curCount; - struct ModbusReqRead mbreq; - word devStartAddr, devEndAddr; // Check the function code. If this method was private we would not need this + const byte length = __size_of(struct ModbusReqRead); + byte buffer[length]; + word curCount; + struct ModbusReqRead mbreq; + word devStartAddr, devEndAddr; // Check the function code. If this method was private we would not need this - switch (funcCode) - { - case ReadRegistersOut: - case ReadRegistersIn: - break; - default: - writeDbg(MbError, "_ModbusReadRegisters: Got incorrect function code 0x%02X!", funcCode); - OnModbusClientPanics(FuncCodeIncorrect); - return; - } + switch (funcCode) + { + case ReadRegistersOut: + case ReadRegistersIn: + break; + default: + writeDbg(MbError, "_ModbusReadRegisters: Got incorrect function code 0x%02X!", funcCode); + OnModbusClientPanics(FuncCodeIncorrect); + return; + } - devStartAddr = funcCode == ReadRegistersOut ? thisDev.Addr.Read.OutputRegisters : thisDev.Addr.Read.InputRegisters; // The start address of the registers - devEndAddr = devStartAddr + thisDev.MaxRegisterCount; // The address behind the last register - if (address >= devEndAddr) - devEndAddr = 0xFFFF; // Some other address. We might be reading extra registers (no input) + devStartAddr = funcCode == ReadRegistersOut ? thisDev.Addr.Read.OutputRegisters : thisDev.Addr.Read.InputRegisters; // The start address of the registers + devEndAddr = devStartAddr + thisDev.MaxRegisterCount; // The address behind the last register + if (address >= devEndAddr) + devEndAddr = 0xFFFF; // Some other address. We might be reading extra registers (no input) - if (address < devStartAddr) // Oh, reading at the wrong address? - { - writeDbg(MbError, "_ModbusReadRegisters: The given start address 0x%04X is smaller than the obligatory start address 0x%04X", address, devStartAddr); - OnModbusClientPanics(AddressFailure); - return; - } - // FC 0x03: Read Holding Registers (AO), FC 0x04: Read Input Registers (AI) - while (count > 0 && address < devEndAddr) - { - curCount = count > gMaxRegsPerRead ? gMaxRegsPerRead : count; // divide packets that are too large - if (address + curCount > devEndAddr) // upper bound in process image - { - writeDbg(MbWarning, "_ModbusReadBits: Impossible to read %d bits at 0x%04X. Changed count to %d.", curCount, address, devEndAddr - address); - curCount = devEndAddr - address; - } + if (address < devStartAddr) // Oh, reading at the wrong address? + { + writeDbg(MbError, "_ModbusReadRegisters: The given start address 0x%04X is smaller than the obligatory start address 0x%04X", address, devStartAddr); + OnModbusClientPanics(AddressFailure); + return; + } + // FC 0x03: Read Holding Registers (AO), FC 0x04: Read Input Registers (AI) + while (count > 0 && address < devEndAddr) + { + curCount = count > gMaxRegsPerRead ? gMaxRegsPerRead : count; // divide packets that are too large + if (address + curCount > devEndAddr) // upper bound in process image + { + writeDbg(MbWarning, "_ModbusReadBits: Impossible to read %d bits at 0x%04X. Changed count to %d.", curCount, address, devEndAddr - address); + curCount = devEndAddr - address; + } - _ModbusMakeHeader(mbreq.Header, length, funcCode); + _ModbusMakeHeader(mbreq.Header, length, funcCode); - mbreq.Address = address; // [2] Start address - mbreq.Count = curCount; // [2] Number of items; 1:max 125=0x7D + mbreq.Address = address; // [2] Start address + mbreq.Count = curCount; // [2] Number of items; 1:max 125=0x7D - writeDbg(MbDebug, "Sending 'Read Registers' (0x03) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, address, curCount); + writeDbg(MbDebug, "Sending 'Read Registers' (0x03) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, address, curCount); - memcpy_h2n(buffer, mbreq); - _ModbusSend(buffer, length, mbreq.Header.TxID); + memcpy_h2n(buffer, mbreq); + _ModbusSend(buffer, length, mbreq.Header.TxID); - count -= gMaxRegsPerRead; - address += gMaxRegsPerRead; - } + count -= gMaxRegsPerRead; + address += gMaxRegsPerRead; + } } /// // This method will be called by _OnModbusReceive2OnePacket() when receiving data void _OnModbusReceiveRegisters(byte buffer[]) { - struct ModbusResReceiveRegisters mbres; - struct ModbusReqRead mbreq; + struct ModbusResReceiveRegisters mbres; + struct ModbusReqRead mbreq; - memcpy_n2h(mbres, buffer); - memcpy_n2h(mbreq, gQueueAck[mbres.Header.TxID].Buffer); + memcpy_n2h(mbres, buffer); + memcpy_n2h(mbreq, gQueueAck[mbres.Header.TxID].Buffer); - writeDbg(MbInfo, "Received %d registers from 0x%04X", mbreq.Count, mbreq.Address); + writeDbg(MbInfo, "Received %d registers from 0x%04X", mbreq.Count, mbreq.Address); - OnModbusReadRegistersSuccess(mbres, mbreq); + OnModbusReadRegistersSuccess(mbres, mbreq); } /// // This method will be called by _OnModbusReceive2Exceptions() when an exception occured void _OnModbusReceiveRegistersException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while reading registers: %s", ModbusExceptions[ex-1]); - OnModbusReadRegistersFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while reading registers: %s", ModbusExceptions[ex-1]); + OnModbusReadRegistersFailed(Exception, ex, mbap); } @@ -357,45 +357,45 @@ void _OnModbusReceiveRegistersException(struct ModbusApHeader mbap, enum ModbusE // This method will submit a request to the Modbus server to set a coil void ModbusWriteBit(word address, byte value) { - const byte length = __size_of(struct ModbusReqWriteSingle); - enum ModbusFuncCode funcCode = WriteBit; - byte buffer[length]; - struct ModbusReqWriteSingle mbreq; + const byte length = __size_of(struct ModbusReqWriteSingle); + enum ModbusFuncCode funcCode = WriteBit; + byte buffer[length]; + struct ModbusReqWriteSingle mbreq; - if (value >= 1) - value = 0xFF; + if (value >= 1) + value = 0xFF; - // FC 0x05: Write Single Coil (DO) - _ModbusMakeHeader(mbreq.Header, length, funcCode); + // FC 0x05: Write Single Coil (DO) + _ModbusMakeHeader(mbreq.Header, length, funcCode); - mbreq.Address = address; // [2] Output address - mbreq.Value = value << 8; // [2] Output value (0x0000: Off, 0xFF00: On) + mbreq.Address = address; // [2] Output address + mbreq.Value = value << 8; // [2] Output value (0x0000: Off, 0xFF00: On) - writeDbg(Debug, "Sending 'Write Bit' (0x05) command. TxID: 0x%04X, Addr: 0x%04X, Value: %d", mbreq.Header.TxID, address, value); - - memcpy_h2n(buffer, mbreq); - _ModbusSend(buffer, length, mbreq.Header.TxID); + writeDbg(Debug, "Sending 'Write Bit' (0x05) command. TxID: 0x%04X, Addr: 0x%04X, Value: %d", mbreq.Header.TxID, address, value); + + memcpy_h2n(buffer, mbreq); + _ModbusSend(buffer, length, mbreq.Header.TxID); } /// // This method will be called by _OnModbusReceive2OnePacket() when confirming the request void _OnModbusConfirmBit(byte buffer[]) { - struct ModbusResConfirmSingle mbc; + struct ModbusResConfirmSingle mbc; - memcpy_n2h(mbc, buffer); + memcpy_n2h(mbc, buffer); - writeDbg(MbInfo, "Set bit at 0x%04X to %d", mbc.Address, mbc.Value); + writeDbg(MbInfo, "Set bit at 0x%04X to %d", mbc.Address, mbc.Value); - OnModbusWriteBitSuccess(mbc); + OnModbusWriteBitSuccess(mbc); } /// // This method will be called by _OnModbusReceive2Exceptions() when an exception occured void _OnModbusConfirmBitException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while writing bit: %s", ModbusExceptions[ex-1]); - OnModbusWriteBitFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while writing bit: %s", ModbusExceptions[ex-1]); + OnModbusWriteBitFailed(Exception, ex, mbap); } @@ -408,42 +408,42 @@ void _OnModbusConfirmBitException(struct ModbusApHeader mbap, enum ModbusExcepti // This method will submit a request to the Modbus server to a holding register void ModbusWriteRegister(word address, word value) { - const byte length = __size_of(struct ModbusReqWriteSingle); - enum ModbusFuncCode funcCode = WriteRegister; - byte buffer[length]; - struct ModbusReqWriteSingle mbreq; + const byte length = __size_of(struct ModbusReqWriteSingle); + enum ModbusFuncCode funcCode = WriteRegister; + byte buffer[length]; + struct ModbusReqWriteSingle mbreq; - // FC 0x06: Write Single Register (AO) - _ModbusMakeHeader(mbreq.Header, length, funcCode); + // FC 0x06: Write Single Register (AO) + _ModbusMakeHeader(mbreq.Header, length, funcCode); - mbreq.Address = address; // [2] Output address - mbreq.Value = value; // [2] Output value + mbreq.Address = address; // [2] Output address + mbreq.Value = value; // [2] Output value - writeDbg(MbDebug, "Sending 'Write Register' (0x06) command. TxID: 0x%04X, Addr: 0x%04X, Value: %d", mbreq.Header.TxID, address, value); + writeDbg(MbDebug, "Sending 'Write Register' (0x06) command. TxID: 0x%04X, Addr: 0x%04X, Value: %d", mbreq.Header.TxID, address, value); - memcpy_h2n(buffer, mbreq); - _ModbusSend(buffer, length, mbreq.Header.TxID); + memcpy_h2n(buffer, mbreq); + _ModbusSend(buffer, length, mbreq.Header.TxID); } /// // This method will be called by _OnModbusReceive2OnePacket() when confirming the request void _OnModbusConfirmRegister(byte buffer[]) { - struct ModbusResConfirmSingle mbc; + struct ModbusResConfirmSingle mbc; - memcpy_n2h(mbc, buffer); + memcpy_n2h(mbc, buffer); - writeDbg(MbInfo, "Set register at 0x%04X to %d", mbc.Address, mbc.Value); + writeDbg(MbInfo, "Set register at 0x%04X to %d", mbc.Address, mbc.Value); - OnModbusWriteRegisterSuccess(mbc); + OnModbusWriteRegisterSuccess(mbc); } /// // This method will be called by _OnModbusReceive2Exceptions() when an exception occured void _OnModbusConfirmRegisterException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while writing register: %s", ModbusExceptions[ex-1]); - OnModbusWriteRegisterFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while writing register: %s", ModbusExceptions[ex-1]); + OnModbusWriteRegisterFailed(Exception, ex, mbap); } @@ -458,66 +458,66 @@ void _OnModbusConfirmRegisterException(struct ModbusApHeader mbap, enum ModbusEx // It will not encode the 'values' void ModbusWriteBits(word address, long count, byte values[]) { - const word maxLength = __size_of(struct ModbusReqWriteBits); - enum ModbusFuncCode funcCode = WriteBits; - byte buffer[maxLength]; - struct ModbusReqWriteBits mbreq; - word overallLength, curCount, addressO; - byte dataLength; - word i; - long offset; - word devStartAddr, devEndAddr; + const word maxLength = __size_of(struct ModbusReqWriteBits); + enum ModbusFuncCode funcCode = WriteBits; + byte buffer[maxLength]; + struct ModbusReqWriteBits mbreq; + word overallLength, curCount, addressO; + byte dataLength; + word i; + long offset; + word devStartAddr, devEndAddr; - devStartAddr = thisDev.Addr.Write.OutputBits; // The start address of the bits - devEndAddr = devStartAddr + thisDev.MaxBitCount; // The address behind the last bit - if (address < devStartAddr) // Oh, reading at the wrong address? - { - writeDbg(MbError, "ModbusWriteBits: The given start address 0x%04X is smaller than the obligatory start address 0x%04X", address, devStartAddr); - OnModbusClientPanics(AddressFailure); - return; - } + devStartAddr = thisDev.Addr.Write.OutputBits; // The start address of the bits + devEndAddr = devStartAddr + thisDev.MaxBitCount; // The address behind the last bit + if (address < devStartAddr) // Oh, reading at the wrong address? + { + writeDbg(MbError, "ModbusWriteBits: The given start address 0x%04X is smaller than the obligatory start address 0x%04X", address, devStartAddr); + OnModbusClientPanics(AddressFailure); + return; + } - // FC 0x0F: Write Multiple Bits (DOs) - offset = 0; - while (count > 0 && (address + offset) < devEndAddr) - { - addressO = address + offset; - if (count > gMaxBitsPerWrite) // divide packets that are too large - { - curCount = gMaxBitsPerWrite; - dataLength = gMaxBitsPerWrite/8; - overallLength = maxLength; - } - else // Bits fit in one packet - { - curCount = count; - dataLength = _ceil(curCount / 8.0); - overallLength = maxLength - gMaxBitsPerWrite/8 + dataLength; - } - if (addressO + curCount > devEndAddr) // upper bound in process image - { - writeDbg(MbWarning, "ModbusWriteBits: Impossible to write %d bits at 0x%04X. Changed count to %d.", curCount, addressO, devEndAddr - addressO); - curCount = devEndAddr - addressO; - dataLength = _ceil(curCount / 8.0); - overallLength = maxLength - gMaxBitsPerWrite/8 + dataLength; - } + // FC 0x0F: Write Multiple Bits (DOs) + offset = 0; + while (count > 0 && (address + offset) < devEndAddr) + { + addressO = address + offset; + if (count > gMaxBitsPerWrite) // divide packets that are too large + { + curCount = gMaxBitsPerWrite; + dataLength = gMaxBitsPerWrite/8; + overallLength = maxLength; + } + else // Bits fit in one packet + { + curCount = count; + dataLength = _ceil(curCount / 8.0); + overallLength = maxLength - gMaxBitsPerWrite/8 + dataLength; + } + if (addressO + curCount > devEndAddr) // upper bound in process image + { + writeDbg(MbWarning, "ModbusWriteBits: Impossible to write %d bits at 0x%04X. Changed count to %d.", curCount, addressO, devEndAddr - addressO); + curCount = devEndAddr - addressO; + dataLength = _ceil(curCount / 8.0); + overallLength = maxLength - gMaxBitsPerWrite/8 + dataLength; + } - _ModbusMakeHeader(mbreq.Header, overallLength, funcCode); + _ModbusMakeHeader(mbreq.Header, overallLength, funcCode); - mbreq.Address = addressO; // [2] Output address - mbreq.Count = curCount; // [2] Number of items; 1:max 1968=0x7B0 - mbreq.ByteCount = dataLength; // [1] Number of bytes; = ceil(count/8) - for (i = 0; i < dataLength; i++) // [264] Byte status, 8 per byte - mbreq.Data[i] = values[i + offset/8]; + mbreq.Address = addressO; // [2] Output address + mbreq.Count = curCount; // [2] Number of items; 1:max 1968=0x7B0 + mbreq.ByteCount = dataLength; // [1] Number of bytes; = ceil(count/8) + for (i = 0; i < dataLength; i++) // [264] Byte status, 8 per byte + mbreq.Data[i] = values[i + offset/8]; - writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, addressO, curCount); + writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, addressO, curCount); - memcpy_h2n(buffer, mbreq); - _ModbusSend(buffer, overallLength, mbreq.Header.TxID); + memcpy_h2n(buffer, mbreq); + _ModbusSend(buffer, overallLength, mbreq.Header.TxID); - count -= gMaxBitsPerWrite; - offset += gMaxBitsPerWrite; - } + count -= gMaxBitsPerWrite; + offset += gMaxBitsPerWrite; + } } /// @@ -526,58 +526,58 @@ void ModbusWriteBits(word address, long count, byte values[]) // Use this when you simply have 1s and 0s void ModbusWriteBitsB(word address, long count, byte values[]) { - byte buffer[0x4000/8]; // Maximum value from B&R devices. *sigh* - long length; - dword ellCount; - dword i; - byte j; - char str1[20*2], str2[20*3]; + byte buffer[0x4000/8]; // Maximum value from B&R devices. *sigh* + long length; + dword ellCount; + dword i; + byte j; + char str1[20*2], str2[20*3]; - length = (long)_floor(count / 8.0); - writeDbg(AlgoDebug, "ModbusWriteBitsB: count: %d; length: %d", count, length+1); + length = (long)_floor(count / 8.0); + writeDbg(AlgoDebug, "ModbusWriteBitsB: count: %d; length: %d", count, length+1); - 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: Byte %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, i*8 + j, values[i*8 + j], (0x01 << j)); - buffer[i] |= (values[(i)*8 + j] & 0x01) << j; - } - writeDbg(AlgoDebug, "ModbusWriteBitsB: Byte %d = %X", i, buffer[i]); + 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: Byte %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, i*8 + j, values[i*8 + j], (0x01 << j)); + buffer[i] |= (values[(i)*8 + j] & 0x01) << j; + } + writeDbg(AlgoDebug, "ModbusWriteBitsB: Byte %d = %X", i, buffer[i]); - hbin_to_strhex(values, str1); - bin_to_strhex(buffer, str2); - writeDbg(AlgoDebug, "ModbusWriteBitsB: Encoded %s to %s (%d -> %d)", str1, str2, count, length); - ModbusWriteBits(address, count, buffer); + hbin_to_strhex(values, str1); + bin_to_strhex(buffer, str2); + writeDbg(AlgoDebug, "ModbusWriteBitsB: Encoded %s to %s (%d -> %d)", str1, str2, count, length); + ModbusWriteBits(address, count, buffer); } /// // This method will be called by _OnModbusReceive2OnePacket() when confirming the request void _OnModbusConfirmBits(byte buffer[]) { - struct ModbusResConfirmMultiple mbc; + struct ModbusResConfirmMultiple mbc; - memcpy_n2h(mbc, buffer); + memcpy_n2h(mbc, buffer); - writeDbg(MbInfo, "Updated %d bits at 0x%04X", mbc.Count, mbc.Address); + writeDbg(MbInfo, "Updated %d bits at 0x%04X", mbc.Count, mbc.Address); - OnModbusWriteBitsSuccess(mbc); + OnModbusWriteBitsSuccess(mbc); } /// // This method will be called by _OnModbusReceive2Exceptions() when an exception occured void _OnModbusConfirmBitsException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while writing bits: %s", ModbusExceptions[ex-1]); - OnModbusWriteBitsFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while writing bits: %s", ModbusExceptions[ex-1]); + OnModbusWriteBitsFailed(Exception, ex, mbap); } @@ -590,81 +590,81 @@ void _OnModbusConfirmBitsException(struct ModbusApHeader mbap, enum ModbusExcept // This method will submit a request to the Modbus server to set several holding registers void ModbusWriteRegisters(word address, long count, word values[]) { - const word maxLength = __size_of(struct ModbusReqWriteRegisters); - enum ModbusFuncCode funcCode = WriteRegisters; - byte buffer[maxLength]; - struct ModbusReqWriteRegisters mbreq; - word overallLength, curCount, addressO; - byte dataLength; - word i; - long offset; - word devStartAddr, devEndAddr; + const word maxLength = __size_of(struct ModbusReqWriteRegisters); + enum ModbusFuncCode funcCode = WriteRegisters; + byte buffer[maxLength]; + struct ModbusReqWriteRegisters mbreq; + word overallLength, curCount, addressO; + byte dataLength; + word i; + long offset; + word devStartAddr, devEndAddr; - devStartAddr = thisDev.Addr.Write.OutputRegisters; // The start address of the bits - devEndAddr = devStartAddr + thisDev.MaxRegisterCount; // The address behind the last bit - if (address >= devEndAddr) - devEndAddr = 0xFFFF; - if (address < devStartAddr) // Oh, reading at the wrong address? - { - writeDbg(MbError, "ModbusWriteRegisters: The given start address 0x%04X is smaller than the obligatory start address 0x%04X", address, devStartAddr); - OnModbusClientPanics(AddressFailure); - return; - } + devStartAddr = thisDev.Addr.Write.OutputRegisters; // The start address of the bits + devEndAddr = devStartAddr + thisDev.MaxRegisterCount; // The address behind the last bit + if (address >= devEndAddr) + devEndAddr = 0xFFFF; + if (address < devStartAddr) // Oh, reading at the wrong address? + { + writeDbg(MbError, "ModbusWriteRegisters: The given start address 0x%04X is smaller than the obligatory start address 0x%04X", address, devStartAddr); + OnModbusClientPanics(AddressFailure); + return; + } - // FC 0x10: Write Multiple Registers (AOs) - offset = 0; - while (count > 0 && (address + offset) > devEndAddr) - { - addressO = address + offset; - curCount = count > gMaxRegsPerWrite ? gMaxRegsPerWrite : count; + // FC 0x10: Write Multiple Registers (AOs) + offset = 0; + while (count > 0 && (address + offset) > devEndAddr) + { + addressO = address + offset; + curCount = count > gMaxRegsPerWrite ? gMaxRegsPerWrite : count; - if (addressO + curCount > devEndAddr) // upper bound in process image - { - writeDbg(MbWarning, "ModbusWriteRegisters: Impossible to write %d bits at 0x%04X. Changed count to %d.", curCount, addressO, devEndAddr - addressO); - curCount = devEndAddr - addressO; - } + if (addressO + curCount > devEndAddr) // upper bound in process image + { + writeDbg(MbWarning, "ModbusWriteRegisters: Impossible to write %d bits at 0x%04X. Changed count to %d.", curCount, addressO, devEndAddr - addressO); + curCount = devEndAddr - addressO; + } - dataLength = 2 * curCount; - overallLength = maxLength - 2*gMaxRegsPerWrite + dataLength; + dataLength = 2 * curCount; + overallLength = maxLength - 2*gMaxRegsPerWrite + dataLength; - _ModbusMakeHeader(mbreq.Header, overallLength, funcCode); + _ModbusMakeHeader(mbreq.Header, overallLength, funcCode); - mbreq.Address = addressO; // [2] Output address - mbreq.Count = curCount; // [2] Number of items; 1:max 123=0x7B - mbreq.ByteCount = dataLength; // [1] Number of bytes; = 2 * count + mbreq.Address = addressO; // [2] Output address + mbreq.Count = curCount; // [2] Number of items; 1:max 123=0x7B + mbreq.ByteCount = dataLength; // [1] Number of bytes; = 2 * count - for (i = 0; i < curCount; i++) - mbreq.Data[i] = values[i+offset]; - //for ( ; i < gMaxRegsPerWrite; i++) // do we need this? - // mbreq.Data[i] = 0; // I'd say that the Modbus server will stop when it has read curCount values + for (i = 0; i < curCount; i++) + mbreq.Data[i] = values[i+offset]; + //for ( ; i < gMaxRegsPerWrite; i++) // do we need this? + // mbreq.Data[i] = 0; // I'd say that the Modbus server will stop when it has read curCount values - memcpy_h2n(buffer, mbreq); - _ModbusSend(buffer, overallLength, mbreq.Header.TxID); + memcpy_h2n(buffer, mbreq); + _ModbusSend(buffer, overallLength, mbreq.Header.TxID); - count -= gMaxRegsPerWrite; - offset += gMaxRegsPerWrite; - } + count -= gMaxRegsPerWrite; + offset += gMaxRegsPerWrite; + } } /// // This method will be called by _OnModbusReceive2OnePacket() when confirming the request void _OnModbusConfirmRegisters(byte buffer[]) { - struct ModbusResConfirmMultiple mbc; + struct ModbusResConfirmMultiple mbc; - memcpy_n2h(mbc, buffer); + memcpy_n2h(mbc, buffer); - writeDbg(MbInfo, "Updated %d registers at 0x%04X", mbc.Count, mbc.Address); + writeDbg(MbInfo, "Updated %d registers at 0x%04X", mbc.Count, mbc.Address); - OnModbusWriteRegistersSuccess(mbc); + OnModbusWriteRegistersSuccess(mbc); } /// // This method will be called by _OnModbusReceive2Exceptions() when an exception occured void _OnModbusConfirmRegistersException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while writing registers: %s", ModbusExceptions[ex-1]); - OnModbusWriteRegistersFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while writing registers: %s", ModbusExceptions[ex-1]); + OnModbusWriteRegistersFailed(Exception, ex, mbap); } @@ -681,41 +681,41 @@ void _OnModbusConfirmRegistersException(struct ModbusApHeader mbap, enum ModbusE /// Example: You want to OR the 4th bit --> AND = 0xFFFB, OR = 0x0004 void ModbusWriteMasks(word address, word and, word or) { - const word length = __size_of(struct ModbusReqWriteMasks); - enum ModbusFuncCode funcCode = MaskRegister; - byte buffer[length]; - struct ModbusReqWriteMasks mbreq; + const word length = __size_of(struct ModbusReqWriteMasks); + enum ModbusFuncCode funcCode = MaskRegister; + byte buffer[length]; + struct ModbusReqWriteMasks mbreq; - // FC 0x16: Mask Write Registers (AO) - _ModbusMakeHeader(mbreq.Header, length, funcCode); + // FC 0x16: Mask Write Registers (AO) + _ModbusMakeHeader(mbreq.Header, length, funcCode); - mbreq.Address = address; // [2] Output address - mbreq.And = and; // [2] AND mask - mbreq.Or = or; // [2] OR mask + mbreq.Address = address; // [2] Output address + mbreq.And = and; // [2] AND mask + mbreq.Or = or; // [2] OR mask - memcpy_h2n(buffer, mbreq); - _ModbusSend(buffer, length, mbreq.Header.TxID); + memcpy_h2n(buffer, mbreq); + _ModbusSend(buffer, length, mbreq.Header.TxID); } /// // This method will be called by _OnModbusReceive2OnePacket() when confirming the request void _OnModbusConfirmMasks(byte buffer[]) { - struct ModbusResConfirmMasks mbc; + struct ModbusResConfirmMasks mbc; - memcpy_n2h(mbc, buffer); + memcpy_n2h(mbc, buffer); - writeDbg(MbInfo, "Applied masks at 0x%04X", mbc.Address); + writeDbg(MbInfo, "Applied masks at 0x%04X", mbc.Address); - OnModbusWriteMasksSuccess(mbc); + OnModbusWriteMasksSuccess(mbc); } /// // This method will be called by _OnModbusReceive2Exceptions() when an exception occured void _OnModbusConfirmMasksException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while applying masks: %s", ModbusExceptions[ex-1]); - OnModbusWriteMasksFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while applying masks: %s", ModbusExceptions[ex-1]); + OnModbusWriteMasksFailed(Exception, ex, mbap); } @@ -727,69 +727,69 @@ void _OnModbusConfirmMasksException(struct ModbusApHeader mbap, enum ModbusExcep // This method will submit a request to the Modbus server to first set several holding registers and afterwards read (different) registers void ModbusReadWriteRegisters(word readAddress, long readCount, word writeAddress, long writeCount, word values[]) { - const word maxLength = __size_of(struct ModbusReqReadWriteRegisters); - enum ModbusFuncCode funcCode = ReadWriteRegisters; - byte buffer[maxLength]; - struct ModbusReqReadWriteRegisters mbreq; - byte dataLength; - word overallLength; - word i, offset; + const word maxLength = __size_of(struct ModbusReqReadWriteRegisters); + enum ModbusFuncCode funcCode = ReadWriteRegisters; + byte buffer[maxLength]; + struct ModbusReqReadWriteRegisters mbreq; + byte dataLength; + word overallLength; + word i, offset; - offset = 0; - if (readCount > gMaxRegsPerRead - 2) // if we have to split the read request. count = n*max + y - { - ModbusReadRegisters(readAddress, readCount - readCount % gMaxRegsPerRead); // let this function read the main part: n*max - readAddress += readCount - readCount % gMaxRegsPerRead; // increment address by n*max - readCount %= gMaxRegsPerRead; // only read y elements in this function - } - if (writeCount > gMaxRegsPerWrite - 2) // if we have to split the write request. count = n*max + y - { - ModbusWriteRegisters(writeAddress, writeCount - writeCount % gMaxRegsPerWrite, values); // let this function read the main part: n*max - offset = writeCount - writeCount % gMaxRegsPerWrite; // start reading values at n*max - writeAddress += offset; // increment address by n*max - writeCount %= gMaxRegsPerWrite; // only read y elements in this function - } + offset = 0; + if (readCount > gMaxRegsPerRead - 2) // if we have to split the read request. count = n*max + y + { + ModbusReadRegisters(readAddress, readCount - readCount % gMaxRegsPerRead); // let this function read the main part: n*max + readAddress += readCount - readCount % gMaxRegsPerRead; // increment address by n*max + readCount %= gMaxRegsPerRead; // only read y elements in this function + } + if (writeCount > gMaxRegsPerWrite - 2) // if we have to split the write request. count = n*max + y + { + ModbusWriteRegisters(writeAddress, writeCount - writeCount % gMaxRegsPerWrite, values); // let this function read the main part: n*max + offset = writeCount - writeCount % gMaxRegsPerWrite; // start reading values at n*max + writeAddress += offset; // increment address by n*max + writeCount %= gMaxRegsPerWrite; // only read y elements in this function + } - dataLength = 2 * writeCount; - overallLength = maxLength - 2*(gMaxRegsPerWrite-2) + dataLength; + dataLength = 2 * writeCount; + overallLength = maxLength - 2*(gMaxRegsPerWrite-2) + dataLength; - // FC 0x17: Write Multiple Registers (AOs) - _ModbusMakeHeader(mbreq.Header, overallLength, funcCode); + // FC 0x17: Write Multiple Registers (AOs) + _ModbusMakeHeader(mbreq.Header, overallLength, funcCode); - mbreq.ReadAddress = readAddress; // [2] Input address - mbreq.ReadCount = readCount; // [2] Number of items; 1:max 125=0x7D - mbreq.WriteAddress = writeAddress; // [2] Output address - mbreq.WriteCount = writeCount; // [2] Number of items; 1:max 121=0x79 - mbreq.ByteCount = dataLength; // [1] Number of bytes; = 2 * count + mbreq.ReadAddress = readAddress; // [2] Input address + mbreq.ReadCount = readCount; // [2] Number of items; 1:max 125=0x7D + mbreq.WriteAddress = writeAddress; // [2] Output address + mbreq.WriteCount = writeCount; // [2] Number of items; 1:max 121=0x79 + mbreq.ByteCount = dataLength; // [1] Number of bytes; = 2 * count - for (i = 0; i < writeCount; i++) - mbreq.Data[i] = values[i + offset]; + for (i = 0; i < writeCount; i++) + mbreq.Data[i] = values[i + offset]; - memcpy_h2n(buffer, mbreq); - _ModbusSend(buffer, overallLength, mbreq.Header.TxID); + memcpy_h2n(buffer, mbreq); + _ModbusSend(buffer, overallLength, mbreq.Header.TxID); } /// // This method will be called by _OnModbusReceive2OnePacket() when confirming the request void _OnModbusReceiveConfirmRegisters(byte buffer[]) { - struct ModbusResReceiveRegisters mbres; - struct ModbusReqRead mbreq; + struct ModbusResReceiveRegisters mbres; + struct ModbusReqRead mbreq; - memcpy_n2h(mbres, buffer); - memcpy_n2h(mbreq, gQueueAck[mbres.Header.TxID].Buffer); + memcpy_n2h(mbres, buffer); + memcpy_n2h(mbreq, gQueueAck[mbres.Header.TxID].Buffer); - writeDbg(MbInfo, "Wrote some registers and received %d registers from 0x%04X", mbreq.Count, mbreq.Address); + writeDbg(MbInfo, "Wrote some registers and received %d registers from 0x%04X", mbreq.Count, mbreq.Address); - OnModbusReadRegistersSuccess(mbres, mbreq); + OnModbusReadRegistersSuccess(mbres, mbreq); } /// // This method will be called by _OnModbusReceive2Exceptions() when an exception occured 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); + writeDbg(MbError, "Received an Exception while reading and writing registers: %s", ModbusExceptions[ex-1]); + OnModbusWriteRegistersFailed(Exception, ex, mbap); } @@ -805,38 +805,38 @@ void _OnModbusReceiveConfirmRegistersException(struct ModbusApHeader mbap, enum // It gets called by the network layer (TCP, UDP, EIL) receive function (OnTcpReceive(),...) 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(); + 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(); - // Now we have to move the already sent telegrams back to the pending queue to send them again - for (long TxID : gQueueSent) - { - writeDbg(ConnWarning, "OnModbusReceive: Moving 0x%04X back to pending queue", TxID); - memcpy(gQueuePending[TxID], gQueueSent[TxID]); // Move back to pending queue - gQueueSent.Remove(TxID); - gQueuePending[TxID].Timeouts = 0; - gQueuePending[TxID].TimeoutTicks = 0; - } - } - else - { - // Sucessfully received some bytes over the connection. - _OnModbusReceive2(buffer, size); - } - } - else - { - gIpLastErr = _ModbusGetLastConnectionError(gIpLastErrStr); - writeDbg(ConnError, "OnModbusReceive error (%d): %s", gIpLastErr, gIpLastErrStr); - _ModbusDisconnect(); - } - _ModbusRecv(); // Continue receiving + // Now we have to move the already sent telegrams back to the pending queue to send them again + for (long TxID : gQueueSent) + { + writeDbg(ConnWarning, "OnModbusReceive: Moving 0x%04X back to pending queue", TxID); + memcpy(gQueuePending[TxID], gQueueSent[TxID]); // Move back to pending queue + gQueueSent.Remove(TxID); + gQueuePending[TxID].Timeouts = 0; + gQueuePending[TxID].TimeoutTicks = 0; + } + } + else + { + // Sucessfully received some bytes over the connection. + _OnModbusReceive2(buffer, size); + } + } + else + { + gIpLastErr = _ModbusGetLastConnectionError(gIpLastErrStr); + writeDbg(ConnError, "OnModbusReceive error (%d): %s", gIpLastErr, gIpLastErrStr); + _ModbusDisconnect(); + } + _ModbusRecv(); // Continue receiving } /// <-OnModbusReceive> @@ -844,32 +844,32 @@ void _OnModbusReceive(dword socket, long result, dword address, dword port, byte // It gets called by _OnModbusReceive() void _OnModbusReceive2(byte buffer[], dword size) { - struct ModbusApHeader mbap; - long offset; - char str[3*20]; + struct ModbusApHeader mbap; + long offset; + char str[3*20]; - if (size < __size_of(struct ModbusApHeader)) // No complete Modbus Application Header fits into this data - return; + if (size < __size_of(struct ModbusApHeader)) // No complete Modbus Application Header fits into this data + return; - offset = 0; - do - { - memcpy_n2h(mbap, buffer, offset); // Copy the data into the Modbus Header - writeDbg(ConnDebug, "OnModbusReceive2: Offset pre = %d. TxID = %d", offset, mbap.TxID); - _OnModbusReceive2OnePacket(buffer, offset, mbap); // Parse the resulting telegram + offset = 0; + do + { + memcpy_n2h(mbap, buffer, offset); // Copy the data into the Modbus Header + writeDbg(ConnDebug, "OnModbusReceive2: Offset pre = %d. TxID = %d", offset, mbap.TxID); + _OnModbusReceive2OnePacket(buffer, offset, mbap); // Parse the resulting telegram - offset += __offset_of(struct ModbusApHeader, UnitID) + mbap.Length; // Move to the next telegram - 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"); + offset += __offset_of(struct ModbusApHeader, UnitID) + mbap.Length; // Move to the next telegram + 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) // If the offset is not pointing at the end of the data - { // This is a indicator that the length field in the Modbus Header was incorrect (attempt to spam the connection?) - 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); - } + if (offset != size) // If the offset is not pointing at the end of the data + { // This is a indicator that the length field in the Modbus Header was incorrect (attempt to spam the connection?) + 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> @@ -878,41 +878,41 @@ void _OnModbusReceive2(byte buffer[], dword size) // It gets called by _OnModbusReceive2() void _OnModbusReceive2OnePacket(byte buffer[], int offset, struct ModbusApHeader mbap) { - // Should we test the transaction identifier? - // Should we test the unit/device identifier? - word i; // counter - word length; // length of current packet + // Should we test the transaction identifier? + // Should we test the unit/device identifier? + word i; // counter + word length; // length of current packet - length = __offset_of(struct ModbusApHeader, UnitID) + mbap.Length; // the length of the complete telegram + length = __offset_of(struct ModbusApHeader, UnitID) + mbap.Length; // the length of the complete telegram - 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); - // either the length field is incorrect or the package is fragmented in the buffer - // 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!? Skip it. - return; + 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); + // either the length field is incorrect or the package is fragmented in the buffer + // 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!? Skip it. + return; - //write("Received TxID: %d", mbap.TxID); - memcpy(gQueueAck[mbap.TxID], gQueueSent[mbap.TxID]); // Move to acknowledge queue - gQueueSent.Remove(mbap.TxID); + //write("Received TxID: %d", mbap.TxID); + memcpy(gQueueAck[mbap.TxID], gQueueSent[mbap.TxID]); // Move to acknowledge queue + gQueueSent.Remove(mbap.TxID); - if (mbap.FuncCode > 0x80) // Oh no, we got a exception! - _OnModbusReceive2Exceptions(buffer[offset+08], mbap); - else // Ok, everything is alright - _OnModbusReceive2Success(buffer, mbap, offset, length); + if (mbap.FuncCode > 0x80) // Oh no, we got a exception! + _OnModbusReceive2Exceptions(buffer[offset+08], mbap); + else // Ok, everything is alright + _OnModbusReceive2Success(buffer, mbap, offset, length); - gQueueAck.Remove(mbap.TxID); // Remove from acknowledge queue + gQueueAck.Remove(mbap.TxID); // Remove from acknowledge queue } /// <-OnModbusReceive> @@ -920,44 +920,44 @@ void _OnModbusReceive2OnePacket(byte buffer[], int offset, struct ModbusApHeader // It gets called by _OnModbusReceive2OnePacket() void _OnModbusReceive2Exceptions(byte exCode, struct ModbusApHeader mbap) { - enum ModbusException ex; - ex = (enum ModbusException)exCode; + enum ModbusException ex; + ex = (enum ModbusException)exCode; - if (ex == Acknowledge) // An ACK resets the timeout timer - { - gQueueSent[mbap.TxID].TimeoutTicks = 0; - return; - } - // else report the error to the corresponding function - switch (mbap.FuncCode) - { - case 0x80+ReadBitsOut: - case 0x80+ReadBitsIn: - _OnModbusReceiveBitsException(mbap, ex); - break; - case 0x80+ReadRegistersOut: - case 0x80+ReadRegistersIn: - _OnModbusReceiveRegistersException(mbap, ex); - break; - case 0x80+WriteBit: - _OnModbusConfirmBitException(mbap, ex); - break; - case 0x80+WriteRegister: - _OnModbusConfirmRegisterException(mbap, ex); - break; - case 0x80+WriteBits: - _OnModbusConfirmBitsException(mbap, ex); - break; - case 0x80+WriteRegisters: - _OnModbusConfirmRegistersException(mbap, ex); - break; - case 0x80+MaskRegister: - _OnModbusConfirmMasksException(mbap, ex); - break; - case 0x80+ReadWriteRegisters: - _OnModbusReceiveConfirmRegistersException(mbap, ex); - break; - } + if (ex == Acknowledge) // An ACK resets the timeout timer + { + gQueueSent[mbap.TxID].TimeoutTicks = 0; + return; + } + // else report the error to the corresponding function + switch (mbap.FuncCode) + { + case 0x80+ReadBitsOut: + case 0x80+ReadBitsIn: + _OnModbusReceiveBitsException(mbap, ex); + break; + case 0x80+ReadRegistersOut: + case 0x80+ReadRegistersIn: + _OnModbusReceiveRegistersException(mbap, ex); + break; + case 0x80+WriteBit: + _OnModbusConfirmBitException(mbap, ex); + break; + case 0x80+WriteRegister: + _OnModbusConfirmRegisterException(mbap, ex); + break; + case 0x80+WriteBits: + _OnModbusConfirmBitsException(mbap, ex); + break; + case 0x80+WriteRegisters: + _OnModbusConfirmRegistersException(mbap, ex); + break; + case 0x80+MaskRegister: + _OnModbusConfirmMasksException(mbap, ex); + break; + case 0x80+ReadWriteRegisters: + _OnModbusReceiveConfirmRegistersException(mbap, ex); + break; + } } /// <-OnModbusReceive> @@ -965,42 +965,42 @@ void _OnModbusReceive2Exceptions(byte exCode, struct ModbusApHeader mbap) // It gets called by _OnModbusReceive2OnePacket() void _OnModbusReceive2Success(byte buffer[], struct ModbusApHeader mbap, int offset, word length) { - byte mbuffer[gModbusMaxTelegramSize]; // second buffer where we copy the message. This way the user won't overwrite other packages. - // Copy the message - memcpy_off(mbuffer, 0, buffer, offset, length); + byte mbuffer[gModbusMaxTelegramSize]; // second buffer where we copy the message. This way the user won't overwrite other packages. + // Copy the message + memcpy_off(mbuffer, 0, buffer, offset, length); - // Let's give the PDU to the corresponding function - switch (mbap.FuncCode) - { - case ReadBitsOut: - case ReadBitsIn: - _OnModbusReceiveBits(mbuffer); - break; - case ReadRegistersOut: - case ReadRegistersIn: - _OnModbusReceiveRegisters(mbuffer); - break; - case WriteBit: - _OnModbusConfirmBit(mbuffer); - break; - case WriteRegister: - _OnModbusConfirmRegister(mbuffer); - break; - case WriteBits: - _OnModbusConfirmBits(mbuffer); - break; - case WriteRegisters: - _OnModbusConfirmRegisters(mbuffer); - break; - case MaskRegister: - _OnModbusConfirmMasks(mbuffer); - break; - case ReadWriteRegisters: - _OnModbusReceiveConfirmRegisters(mbuffer); - break; - default: - writeDbg(MbError, "OnModbusReceive2Success: We received funcCode 0x%X!?", mbap.FuncCode); - } + // Let's give the PDU to the corresponding function + switch (mbap.FuncCode) + { + case ReadBitsOut: + case ReadBitsIn: + _OnModbusReceiveBits(mbuffer); + break; + case ReadRegistersOut: + case ReadRegistersIn: + _OnModbusReceiveRegisters(mbuffer); + break; + case WriteBit: + _OnModbusConfirmBit(mbuffer); + break; + case WriteRegister: + _OnModbusConfirmRegister(mbuffer); + break; + case WriteBits: + _OnModbusConfirmBits(mbuffer); + break; + case WriteRegisters: + _OnModbusConfirmRegisters(mbuffer); + break; + case MaskRegister: + _OnModbusConfirmMasks(mbuffer); + break; + case ReadWriteRegisters: + _OnModbusReceiveConfirmRegisters(mbuffer); + break; + default: + writeDbg(MbError, "OnModbusReceive2Success: We received funcCode 0x%X!?", mbap.FuncCode); + } } @@ -1011,15 +1011,15 @@ void _OnModbusReceive2Success(byte buffer[], struct ModbusApHeader mbap, int off // It will get called by the Modbus request functions void _ModbusSend(byte buffer[], word length, word TxID) { - struct QueueElement qe; + struct QueueElement qe; - qe.Length = length; - memcpy(qe.Buffer, buffer, length); + qe.Length = length; + memcpy(qe.Buffer, buffer, length); - memcpy(gQueuePending[TxID], qe); - writeDbg(ConnDebug, "Appended packet 0x%04X to pending queue", TxID); + memcpy(gQueuePending[TxID], qe); + writeDbg(ConnDebug, "Appended packet 0x%04X to pending queue", TxID); - _ModbusStartQueue(); + _ModbusStartQueue(); } // This method will start the timer. Nothing special :) @@ -1027,11 +1027,11 @@ void _ModbusSend(byte buffer[], word length, word TxID) // It gets called by _ModbusSend() and OnEthReceivePacket() in ModbusEil.cin void _ModbusStartQueue() { - if (gSocketState >= CLOSED && (gQueuePending.Size() > 0 || gQueueSent.Size() > 0)) - { - writeDbg(ConnDebug, "Starting Timer gtModbusRobin"); - setTimerCyclic(gtModbusRobin, 1); - } + if (gSocketState >= CLOSED && (gQueuePending.Size() > 0 || gQueueSent.Size() > 0)) + { + writeDbg(ConnDebug, "Starting Timer gtModbusRobin"); + setTimerCyclic(gtModbusRobin, 1); + } } /// <-ModbusSend> @@ -1040,99 +1040,99 @@ void _ModbusStartQueue() // The pending packets may be sent when there is free space in the sending window on timer gtModbusRobin { - enum ModbusRequestError reqError; + enum ModbusRequestError reqError; - writeDbg(ConnDebug, "gtModbusRobin: Queue Sent: %d, Queue Pending: %d, Queue Ack: %d", gQueueSent.Size(), gQueuePending.Size(), gQueueAck.Size()); + writeDbg(ConnDebug, "gtModbusRobin: 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 < gRequestTimeout) // not timed out yet - continue; - // timed out! - if (++gQueueSent[TxID].Timeouts < gMaxTransmissionCount) // if we may resend it - { - writeDbg(ConnInfo, "gtModbusRobin: 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, "gtModbusRobin: Packet 0x%04X timed out! Giving up", TxID); - reqError = FinalTimeout; - } + // First: check timeouts = packets that were sent in previous run and not removed by response + for (long TxID : gQueueSent) + { + if (++gQueueSent[TxID].TimeoutTicks < gRequestTimeout) // not timed out yet + continue; + // timed out! + if (++gQueueSent[TxID].Timeouts < gMaxTransmissionCount) // if we may resend it + { + writeDbg(ConnInfo, "gtModbusRobin: 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, "gtModbusRobin: Packet 0x%04X timed out! Giving up", TxID); + reqError = FinalTimeout; + } - _ModbusSendTimerError(gQueueSent[TxID].Buffer, reqError); // throw an "error" in each case + _ModbusSendTimerError(gQueueSent[TxID].Buffer, reqError); // throw an "error" in each case - if (reqError == FinalTimeout) // remove the packet from queue - gQueueSent.Remove(TxID); // wait until here to let the methods above access the request - } + if (reqError == FinalTimeout) // remove the packet from queue + gQueueSent.Remove(TxID); // wait until here to let the methods above access the request + } - // Second: send new packets - for (long TxID : gQueuePending) - { - if (gQueueSent.Size() >= thisDev.ReceiveWindow) // Device cannot handle that many messages at a time - break; // Wait for the next turn + // Second: send new packets + for (long TxID : gQueuePending) + { + if (gQueueSent.Size() >= thisDev.ReceiveWindow) // Device cannot handle that many messages at a time + break; // Wait for the next turn - // Now send the packet - // if packet was sent or the socket is not currently being opened - if (_ModbusSnd(gQueuePending[TxID].Buffer, gQueuePending[TxID].Length) == 0) - { - memcpy(gQueueSent[TxID], gQueuePending[TxID]); // move packet to sent queue - gQueuePending.Remove(TxID); - _ModbusRecv(); // wait for new packets - } - else if (gQueuePending[TxID].SendTries++ > 10) // We have tried to send this packet too often. Something is wrong!? - { - writeDbg(ConnError, "gtModbusRobin: The packet 0x%04X could not be sent, _ModbusSnd() rejected it several times", TxID); - _ModbusSendTimerError(gQueuePending[TxID].Buffer, NotSent); - gQueuePending.Remove(TxID); - } - } + // Now send the packet + // if packet was sent or the socket is not currently being opened + if (_ModbusSnd(gQueuePending[TxID].Buffer, gQueuePending[TxID].Length) == 0) + { + memcpy(gQueueSent[TxID], gQueuePending[TxID]); // move packet to sent queue + gQueuePending.Remove(TxID); + _ModbusRecv(); // wait for new packets + } + else if (gQueuePending[TxID].SendTries++ > 10) // We have tried to send this packet too often. Something is wrong!? + { + writeDbg(ConnError, "gtModbusRobin: The packet 0x%04X could not be sent, _ModbusSnd() rejected it several times", TxID); + _ModbusSendTimerError(gQueuePending[TxID].Buffer, NotSent); + gQueuePending.Remove(TxID); + } + } - // Stop timer to reduce load and latency of first new packet - if (gSocketState != OK || gQueueSent.Size() == 0 && gQueuePending.Size() == 0) - { - writeDbg(ConnDebug, "gtModbusRobin: Stopping Timer. Queue Sent: %d, Queue Pending: %d", gQueueSent.Size(), gQueuePending.Size()); - this.Cancel(); - } + // Stop timer to reduce load and latency of first new packet + if (gSocketState != OK || gQueueSent.Size() == 0 && gQueuePending.Size() == 0) + { + writeDbg(ConnDebug, "gtModbusRobin: Stopping Timer. Queue Sent: %d, Queue Pending: %d", gQueueSent.Size(), gQueuePending.Size()); + this.Cancel(); + } } /// <-ModbusSend> // This method will give an Error void _ModbusSendTimerError(byte buffer[], enum ModbusRequestError reqError) { - struct ModbusApHeader mbap; - memcpy_n2h(mbap, buffer); - switch(mbap.FuncCode) - { - case ReadBitsOut: - case ReadBitsIn: - OnModbusReadBitsFailed(reqError, None, mbap); - break; - case ReadRegistersOut: - case ReadRegistersIn: - 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; - } + struct ModbusApHeader mbap; + memcpy_n2h(mbap, buffer); + switch(mbap.FuncCode) + { + case ReadBitsOut: + case ReadBitsIn: + OnModbusReadBitsFailed(reqError, None, mbap); + break; + case ReadRegistersOut: + case ReadRegistersIn: + 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; + } } \ No newline at end of file diff --git a/Modbus-CAPL/include/CAPL/include/ModbusEil.cin b/Modbus-CAPL/include/CAPL/include/ModbusEil.cin index 1d8dfd1..d47453c 100644 --- a/Modbus-CAPL/include/CAPL/include/ModbusEil.cin +++ b/Modbus-CAPL/include/CAPL/include/ModbusEil.cin @@ -2,134 +2,134 @@ // This file contains functions that abstract the Ethernet Interaction Layer /// It provides following methods -/// - _ModbusConnectTo() Prepare anything that sending works. Here: Create a new packet -/// - _ModbusDisconnect() Gracefully disconnect from the device. Here: Invalidate the existing packet -/// - _ModbusRecv() Receive data from the device. Here: Does nothing, receiving takes place automatically -/// - _ModbusSnd() Send data to the device. Here: Fills the packet with payload data and sends it +/// - _ModbusConnectTo() Prepare anything that sending works. Here: Create a new packet +/// - _ModbusDisconnect() Gracefully disconnect from the device. Here: Invalidate the existing packet +/// - _ModbusRecv() Receive data from the device. Here: Does nothing, receiving takes place automatically +/// - _ModbusSnd() Send data to the device. Here: Fills the packet with payload data and sends it /// - Some function that receives packets and hands them to _OnModbusReceive() includes { - #include "Common.cin" - #include "TcpUdpEilCommon.cin" + #include "Common.cin" + #include "TcpUdpEilCommon.cin" } variables { - long gPacket; // The packet that will be send - msTimer gtModbusArp; // A timer waiting for the ARP response - - byte gLocalMac[6]; // Storage of the local MAC address - byte gRemoteMac[6]; // Storage of the remote MAC address (the one of the device) - // TODO: The local IP should not have to be specified here. Where can we get it from? - dword gLocalIP = 0xC0A80101; // The local IP address. + long gPacket; // The packet that will be send + msTimer gtModbusArp; // A timer waiting for the ARP response + + byte gLocalMac[6]; // Storage of the local MAC address + byte gRemoteMac[6]; // Storage of the remote MAC address (the one of the device) + // TODO: The local IP should not have to be specified here. Where can we get it from? + dword gLocalIP = 0xC0A80101; // The local IP address. } // This method prepares anything in a way that sending with ModbusSnd() is possible. // Here: The method will create an ARP telegram to get the MAC address of the device with the specified Remote_IP word _ModbusConnectTo(char Remote_IP[], word remotePort) { - dword remoteIp; + 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(); - } + // 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 _ModbusConnectTo(remoteIp, remotePort); + return _ModbusConnectTo(remoteIp, remotePort); } // This method prepares anything in a way that sending with ModbusSnd() is possible. // Here: The method will create an ARP telegram to get the MAC address of the device with the specified remoteIp word _ModbusConnectTo(dword remoteIp, word remotePort) { - long error; - byte broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + 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; - } + 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); + // 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; - } + 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; + } - gSocketState = CONNECTING; + gSocketState = CONNECTING; - 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); - EthSetTokenInt(gPacket, "arp", "protDestinationAddr" , gRemoteIP); + 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); + EthSetTokenInt(gPacket, "arp", "protDestinationAddr" , gRemoteIP); - EthReceivePacket("OnEthReceivePacket"); + EthReceivePacket("OnEthReceivePacket"); - EthCompletePacket(gPacket); - EthOutputPacket(gPacket); - EthReleasePacket(gPacket); - gSocketState = CONNECTING; - gtModbusArp.set(@sysvar::Config::Modbus::RequestTimeout); - return 0; + EthCompletePacket(gPacket); + EthOutputPacket(gPacket); + EthReleasePacket(gPacket); + gSocketState = CONNECTING; + gtModbusArp.set(@sysvar::Config::Modbus::RequestTimeout); + return 0; } // This method prepares anything in a way that sending with ModbusSnd() is possible. // Here: The method will be called after an ARP telegram was received and set up the EthernetIL packet. void _ModbusConnectTo2() { - gPacket = EthInitPacket("udp"); - if (gPacket == 0) - { - gSocketState = ERROR; - writeDbg(ConnError, "EthInitPacket: Could not create UDP packet: %d", EthGetLastError()); - OnModbusClientPanics(ConnectionError); - return; - } + 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); + 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; + gSocketState = OK; } // This method will gracefully disconnect from the remote device. // Here: The method will invalidate the packet 'gPacket' void _ModbusDisconnect() { - if (gPacket != 0) - { - EthReleasePacket(gPacket); - gPacket = 0; - } - gSocketState = CLOSED; + if (gPacket != 0) + { + EthReleasePacket(gPacket); + gPacket = 0; + } + gSocketState = CLOSED; } // This method will wait for data from the remote device. @@ -142,83 +142,83 @@ void _ModbusRecv() // Here: It fills the packet 'gPacket' and sends it byte _ModbusSnd(byte buffer[], word length) { - char str[20*3]; + char str[20*3]; - switch (gSocketState) - { - case CLOSED: - _ModbusConnectTo(gRemoteIP, gRemotePort); - if (gSocketState != OK) - { - writeDbg(ConnWarning, "_ModbusSnd: Reconnecting failed!"); - return 1; - } - case OK: - break; - case NULL: // Delay - case CONNECTING: - return 1; - case ERROR: - writeDbg(ConnError, "_ModbusSnd: Socket status is not OK!"); - OnModbusClientPanics(ConnectionError); - return 1; - default: - writeDbg(ConnError, "_ModbusSnd: Unknown socket status: %d", gSocketState); - OnModbusClientPanics(SwitchArgumentInvalid); - return 1; - } + switch (gSocketState) + { + case CLOSED: + _ModbusConnectTo(gRemoteIP, gRemotePort); + if (gSocketState != OK) + { + writeDbg(ConnWarning, "_ModbusSnd: Reconnecting failed!"); + return 1; + } + case OK: + break; + case NULL: // Delay + case CONNECTING: + return 1; + case ERROR: + writeDbg(ConnError, "_ModbusSnd: Socket status is not OK!"); + OnModbusClientPanics(ConnectionError); + return 1; + default: + writeDbg(ConnError, "_ModbusSnd: Unknown socket status: %d", gSocketState); + OnModbusClientPanics(SwitchArgumentInvalid); + return 1; + } - bin_to_strhex(buffer, str); - writeDbg(ConnDebug, "_ModbusSnd: %s (Länge: %d)", str, length); + bin_to_strhex(buffer, str); + writeDbg(ConnDebug, "_ModbusSnd: %s (Länge: %d)", str, length); - EthResizeToken(gPacket, "udp", "data" , length*8); - EthSetTokenData(gPacket, "udp", "data" , length, buffer); + EthResizeToken(gPacket, "udp", "data" , length*8); + EthSetTokenData(gPacket, "udp", "data" , length, buffer); - EthCompletePacket(gPacket); - EthOutputPacket(gPacket); + EthCompletePacket(gPacket); + EthOutputPacket(gPacket); - return 0; + return 0; } // This Method simply combines the two EthGetLastError functions long _ModbusGetLastConnectionError(char string[]) { - EthGetLastErrorText(elCount(string), string); - return EthGetLastError(); + EthGetLastErrorText(elCount(string), string); + return EthGetLastError(); } // When the ARP times out the "connection" could not be opened and we have to throw an error on timer gtModbusArp { - gSocketState = ERROR; - writeDbg(ConnError, "No (valid) ARP response detected. The host seems to be offline!"); - OnModbusClientPanics(ConnectionError); + gSocketState = ERROR; + writeDbg(ConnError, "No (valid) ARP response detected. The host seems to be offline!"); + OnModbusClientPanics(ConnectionError); } // This function will handle incoming packets and give them to the Modbus layer void OnEthReceivePacket(long channel, long dir, long packet) { - byte buffer[gModbusMaxTelegramSize]; - long size; + byte buffer[gModbusMaxTelegramSize]; + long size; - if (dir == TX) - return; + if (dir == TX) + return; - if (EthGetTokenInt(packet, "arp", "protSourceAddr") == gRemoteIP) // this was our ARP package - { - if (EthGetTokenData(packet, "arp", "hwSourceAddr", elCount(gRemoteMac), gRemoteMac) == 6) // save it - { - gtModbusArp.Cancel(); - writeDbg(ConnDebug, "Remote Mac: %02X:%02X:%02X:%02X:%02X:%02X", gRemoteMac[0], gRemoteMac[1], gRemoteMac[2], gRemoteMac[3], gRemoteMac[4], gRemoteMac[5]); - _ModbusConnectTo2(); // create the UDP package - _ModbusStartQueue(); - } - return; - } + if (EthGetTokenInt(packet, "arp", "protSourceAddr") == gRemoteIP) // this was our ARP package + { + if (EthGetTokenData(packet, "arp", "hwSourceAddr", elCount(gRemoteMac), gRemoteMac) == 6) // save it + { + gtModbusArp.Cancel(); + writeDbg(ConnDebug, "Remote Mac: %02X:%02X:%02X:%02X:%02X:%02X", gRemoteMac[0], gRemoteMac[1], gRemoteMac[2], gRemoteMac[3], gRemoteMac[4], gRemoteMac[5]); + _ModbusConnectTo2(); // 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, gModbusMaxTelegramSize, buffer); - _OnModbusReceive(0, 0, EthGetTokenInt(packet, "ipv4", "source"), gRemoteIP, buffer, size); // Hand to Modbus Layer - } + if (EthGetTokenInt(packet, "ipv4", "protocol") == 0x11 && EthGetTokenInt(packet, "ipv4", "source") == gRemoteIP) // if this is a UDP package from our server + { + size = EthGetThisData(0, gModbusMaxTelegramSize, buffer); + _OnModbusReceive(0, 0, EthGetTokenInt(packet, "ipv4", "source"), gRemoteIP, buffer, size); // Hand to Modbus Layer + } } \ No newline at end of file diff --git a/Modbus-CAPL/include/CAPL/include/ModbusStructs.cin b/Modbus-CAPL/include/CAPL/include/ModbusStructs.cin index f9d91b2..4cdf64d 100644 --- a/Modbus-CAPL/include/CAPL/include/ModbusStructs.cin +++ b/Modbus-CAPL/include/CAPL/include/ModbusStructs.cin @@ -1,182 +1,182 @@ /*@!Encoding:1252*/ variables { - // Constant maximum values according to Modbus Specification v1.1 - const word gMaxBitsPerRead = 2000; - const word gMaxRegsPerRead = 125; - const word gMaxBitsPerWrite = 1968; // Multiple of 8! - const word gMaxRegsPerWrite = 123; + // Constant maximum values according to Modbus Specification v1.1 + const word gMaxBitsPerRead = 2000; + const word gMaxRegsPerRead = 125; + const word gMaxBitsPerWrite = 1968; // Multiple of 8! + const word gMaxRegsPerWrite = 123; - // Function Codes according to Modbus Specification v1.1 - enum ModbusFuncCode - { - ReadBitsOut = 0x01, // Read Coils - ReadBitsIn = 0x02, // Read Discrete Inputs - ReadRegistersOut = 0x03, // Read Holding Registers - ReadRegistersIn = 0x04, // Read Input Registers - WriteBit = 0x05, // Write Single Coil - WriteRegister = 0x06, // Write Single Holding Register - WriteBits = 0x0F, // Write Multiple Coils - WriteRegisters = 0x10, // Write Multiple Holding Registers - MaskRegister = 0x16, // Mask Write Holding Register - ReadWriteRegisters = 0x17 // Read/Write Multiple Registers - }; + // Function Codes according to Modbus Specification v1.1 + enum ModbusFuncCode + { + ReadBitsOut = 0x01, // Read Coils + ReadBitsIn = 0x02, // Read Discrete Inputs + ReadRegistersOut = 0x03, // Read Holding Registers + ReadRegistersIn = 0x04, // Read Input Registers + WriteBit = 0x05, // Write Single Coil + WriteRegister = 0x06, // Write Single Holding Register + WriteBits = 0x0F, // Write Multiple Coils + WriteRegisters = 0x10, // Write Multiple Holding Registers + MaskRegister = 0x16, // Mask Write Holding Register + ReadWriteRegisters = 0x17 // Read/Write Multiple Registers + }; - // 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; - }; + // 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; + }; - /// Request structures following - // 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[gMaxBitsPerWrite/8]; // 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[gMaxRegsPerWrite]; // 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[gMaxRegsPerWrite-2]; // Max length: 123-2 registers - }; + /// Request structures following + // 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[gMaxBitsPerWrite/8]; // 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[gMaxRegsPerWrite]; // 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[gMaxRegsPerWrite-2]; // Max length: 123-2 registers + }; - /// Response structures following - // Receive several bit values - _align(1) struct ModbusResReceiveBits - { - struct ModbusApHeader Header; - byte ByteCount; - byte Data[gMaxBitsPerRead/8]; // Max length: 2000 bits - }; - // Receive several register values - _align(1) struct ModbusResReceiveRegisters - { - struct ModbusApHeader Header; - byte ByteCount; - word Data[gMaxRegsPerRead]; // 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; - }; + /// Response structures following + // Receive several bit values + _align(1) struct ModbusResReceiveBits + { + struct ModbusApHeader Header; + byte ByteCount; + byte Data[gMaxBitsPerRead/8]; // Max length: 2000 bits + }; + // Receive several register values + _align(1) struct ModbusResReceiveRegisters + { + struct ModbusApHeader Header; + byte ByteCount; + word Data[gMaxRegsPerRead]; // 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; + }; - // The maximum modbus telegram size. - // Several telegrams use this many bytes, but CAPL does not support a constant max function to let it calculate it. So we use ModbusResReceiveRegisters - const word gModbusMaxTelegramSize = __size_of(struct ModbusResReceiveRegisters); + // The maximum modbus telegram size. + // Several telegrams use this many bytes, but CAPL does not support a constant max function to let it calculate it. So we use ModbusResReceiveRegisters + const word gModbusMaxTelegramSize = __size_of(struct ModbusResReceiveRegisters); - // Some errors that may occur when sending a request - enum ModbusRequestError - { - Exception, // Modbus exception was returned - Timeout, // Timeout occured, resending the packet - FinalTimeout, // Timeout occured, not resending the packet - NotSent // Sending the packet was impossible - }; - - // Modbus exception codes according to Modbus Specification v1.1 - enum ModbusException - { - None = 0x00, - IllegalFuncCode = 0x01, - IllegalDataAddress = 0x02, - IllegalDataValue = 0x03, - ServerFailure = 0x04, - Acknowledge = 0x05, - ServerBusy = 0x06, - GatewayPathsNA = 0x0A, - TargetOffline = 0x0B - }; - // Modbus Exception descriptions - 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" - }; - - // Fatal errors that may stop the code execution - enum FatalErrors - { - ParsingBuffer, - ModbusPackageWasSplit, - DeviceCodeUnknown, - VendorIdUnknown, - ConnectionError, - FuncCodeIncorrect, - AddressFailure, - SwitchArgumentInvalid - }; + // Some errors that may occur when sending a request + enum ModbusRequestError + { + Exception, // Modbus exception was returned + Timeout, // Timeout occured, resending the packet + FinalTimeout, // Timeout occured, not resending the packet + NotSent // Sending the packet was impossible + }; + + // Modbus exception codes according to Modbus Specification v1.1 + enum ModbusException + { + None = 0x00, + IllegalFuncCode = 0x01, + IllegalDataAddress = 0x02, + IllegalDataValue = 0x03, + ServerFailure = 0x04, + Acknowledge = 0x05, + ServerBusy = 0x06, + GatewayPathsNA = 0x0A, + TargetOffline = 0x0B + }; + // Modbus Exception descriptions + 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" + }; + + // Fatal errors that may stop the code execution + enum FatalErrors + { + ParsingBuffer, + ModbusPackageWasSplit, + DeviceCodeUnknown, + VendorIdUnknown, + ConnectionError, + FuncCodeIncorrect, + AddressFailure, + SwitchArgumentInvalid + }; } \ No newline at end of file diff --git a/Modbus-CAPL/include/CAPL/include/ModbusTcp.cin b/Modbus-CAPL/include/CAPL/include/ModbusTcp.cin index 8ae3cd4..254ab04 100644 --- a/Modbus-CAPL/include/CAPL/include/ModbusTcp.cin +++ b/Modbus-CAPL/include/CAPL/include/ModbusTcp.cin @@ -2,235 +2,235 @@ // This file contains functions that abstract the UDP/IP API /// It provides following methods -/// - _ModbusConnectTo() Prepare anything that sending works. Here: Open a TCP socket and connection -/// - _ModbusDisconnect() Gracefully disconnect from the device. Here: Close the TCP connection and socket -/// - _ModbusRecv() Receive data from the device. Here: Wait for a TCP packet on the connection -/// - _ModbusSnd() Send data to the device. Here: Send a packet on the TCP connection +/// - _ModbusConnectTo() Prepare anything that sending works. Here: Open a TCP socket and connection +/// - _ModbusDisconnect() Gracefully disconnect from the device. Here: Close the TCP connection and socket +/// - _ModbusRecv() Receive data from the device. Here: Wait for a TCP packet on the connection +/// - _ModbusSnd() Send data to the device. Here: Send a packet on the TCP connection /// - Some function that receives packets and hands them to _OnModbusReceive() includes { - #include "Common.cin" - #include "TcpUdpEilCommon.cin" + #include "Common.cin" + #include "TcpUdpEilCommon.cin" } variables { - TcpSocket gSocket; + TcpSocket gSocket; } // This method opens an TCP socket. It has to check for several errors. word _TcpOpenSocket() { - byte i; - char errorText[200]; - long error; + 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; - } + if (EthGetAdapterStatus() != 2) // Not connected + { + writeDbg(ConnError, "_TcpOpenSocket: Adapter status not ok: %d!", EthGetAdapterStatus()); + OnModbusClientPanics(ConnectionError); + return INVALID_IP; + } - // Try to open socket - 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); - OnModbusClientPanics(ConnectionError); - return error; - } - else - { - writeDbg(ConnInfo, "_TcpOpenSocket: Tcp socket opened."); - } - return 0; + // Try to open socket + 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); + OnModbusClientPanics(ConnectionError); + return error; + } + else + { + writeDbg(ConnInfo, "_TcpOpenSocket: Tcp socket opened."); + } + return 0; } // This method prepares anything in a way that sending with ModbusSnd() is possible. // Here: The method will open a TCP socket and connect to the remote device word _ModbusConnectTo(char Remote_IP[], word remotePort) { - dword remoteIp; + dword remoteIp; - // Convert IP string to Number - remoteIp = IpGetAddressAsNumber(Remote_IP); - if (remoteIp == INVALID_IP) - { - writeDbg(ConnError, "_ModbusConnectTo: invalid server Ip address: %s", Remote_IP); - OnModbusClientPanics(ConnectionError); - return 1; - } + // Convert IP string to Number + remoteIp = IpGetAddressAsNumber(Remote_IP); + if (remoteIp == INVALID_IP) + { + writeDbg(ConnError, "_ModbusConnectTo: invalid server Ip address: %s", Remote_IP); + OnModbusClientPanics(ConnectionError); + return 1; + } - return _ModbusConnectTo(remoteIp, remotePort); + return _ModbusConnectTo(remoteIp, remotePort); } // This method prepares anything in a way that sending with ModbusSnd() is possible. // Here: The method will open a TCP socket and connect to the remote device word _ModbusConnectTo(dword remoteIp, word remotePort) { - long error; + long error; - // Try to open a socket - error = _TcpOpenSocket(); - if (error != 0) - { - gSocketState = ERROR; - return error; - } + // Try to open a socket + error = _TcpOpenSocket(); + if (error != 0) + { + gSocketState = ERROR; + return error; + } - gRemoteIP = remoteIp; - gRemotePort = remotePort; + gRemoteIP = remoteIp; + gRemotePort = remotePort; - // Connect to Server - if (gSocket.Connect(remoteIp, remotePort) != 0) - { - error = gSocket.GetLastSocketError(); + // Connect to Server + if (gSocket.Connect(remoteIp, remotePort) != 0) + { + error = gSocket.GetLastSocketError(); - if (error != WSAEWOULDBLOCK) // OnTcpConnect will be called otherwise - { - writeDbg(ConnError, "_ModbusConnectTo: No connection established: %d", error); - gSocketState = ERROR; - OnModbusClientPanics(ConnectionError); - return error; - } - else - { - writeDbg(ConnDebug, "_ModbusConnectTo: WSAE would block"); - gSocketState = CONNECTING; - } - return 0; - } - gSocketState = CONNECTING; // Don't set state OK because the Stack doesn't tell us WSAEWOULDBLOCK each time whensoever is neccessary - return 0; + if (error != WSAEWOULDBLOCK) // OnTcpConnect will be called otherwise + { + writeDbg(ConnError, "_ModbusConnectTo: No connection established: %d", error); + gSocketState = ERROR; + OnModbusClientPanics(ConnectionError); + return error; + } + else + { + writeDbg(ConnDebug, "_ModbusConnectTo: WSAE would block"); + gSocketState = CONNECTING; + } + return 0; + } + gSocketState = CONNECTING; // Don't set state OK because the Stack doesn't tell us WSAEWOULDBLOCK each time whensoever is neccessary + return 0; } // This method will be called when TcpSocket.Connect() had to defer the result (and returned WSAEWOULDBLOCK). // It checks whether the connection was opened successfully and sets the socket state accordingly 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(); - } + 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(); + } } // This method will gracefully disconnect from the remote device. // Here: Simply close the socket. This will also disconnect the remote device void _ModbusDisconnect() { - writeDbg(ConnDebug, "_ModbusDisconnect: Disconnecting"); - gSocket.Close(); - gSocketState = CLOSED; + writeDbg(ConnDebug, "_ModbusDisconnect: Disconnecting"); + gSocket.Close(); + gSocketState = CLOSED; } // This method will check for data from the remote device. // Here: Tell the API to check for new TCP telegrams. When data arrived OnTcpReceive() will be called by the API void _ModbusRecv() { - int result; + int result; - if (gSocketState != OK) - { - writeDbg(ConnWarning, "_ModbusRecv: Socket status is not OK!"); - _ModbusDisconnect(); -// OnModbusClientPanics(ConnectionError); - return; - } - - result = gSocket.Receive(gRxBuffer, elcount(gRxBuffer)); + if (gSocketState != OK) + { + writeDbg(ConnWarning, "_ModbusRecv: Socket status is not OK!"); + _ModbusDisconnect(); +// OnModbusClientPanics(ConnectionError); + return; + } + + result = gSocket.Receive(gRxBuffer, elcount(gRxBuffer)); - if (result != 0) // Calling OnTcpReceive otherwise - { - gIpLastErr = gSocket.GetLastSocketError(); + if (result != 0) // Calling OnTcpReceive otherwise + { + gIpLastErr = gSocket.GetLastSocketError(); - if (gIpLastErr != WSA_IO_PENDING) // Calling OnTcpReceive otherwise - { - gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); - writeDbg(ConnError, "_ModbusRecv: (%d) %s", gIpLastErr, gIpLastErrStr); - _ModbusDisconnect(); - } - } + if (gIpLastErr != WSA_IO_PENDING) // Calling OnTcpReceive otherwise + { + gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); + writeDbg(ConnError, "_ModbusRecv: (%d) %s", gIpLastErr, gIpLastErrStr); + _ModbusDisconnect(); + } + } - return; + return; } // This method will send the payload 'buffer' to the device. // Here: Call the appropriate API function word _ModbusSnd(byte buffer[], word length) { - char str[20*3]; + char str[20*3]; - switch (gSocketState) - { - case OK: // Go on and send - break; - case CLOSED: // If the connection is closed - _ModbusConnectTo(gRemoteIP, gRemotePort); // Try to (re)connect - if (gSocketState < OK) // If this didn't work (state != OK) - { - if (gSocketState < CONNECTING) - { - writeDbg(ConnError, "_ModbusSnd: Reconnecting failed!"); - OnModbusClientPanics(ConnectionError); - } - return 1; // Abort sending in all cases - } - case NULL: // Delay - case CONNECTING: - return 1; - case ERROR: - writeDbg(ConnError, "_ModbusSnd: Socket status is not OK!"); - OnModbusClientPanics(ConnectionError); - return 1; - default: - writeDbg(ConnError, "_ModbusSnd: Unknown socket status: %d", gSocketState); - OnModbusClientPanics(SwitchArgumentInvalid); - return 1; - } + switch (gSocketState) + { + case OK: // Go on and send + break; + case CLOSED: // If the connection is closed + _ModbusConnectTo(gRemoteIP, gRemotePort); // Try to (re)connect + if (gSocketState < OK) // If this didn't work (state != OK) + { + if (gSocketState < CONNECTING) + { + writeDbg(ConnError, "_ModbusSnd: Reconnecting failed!"); + OnModbusClientPanics(ConnectionError); + } + return 1; // Abort sending in all cases + } + case NULL: // Delay + case CONNECTING: + return 1; + case ERROR: + writeDbg(ConnError, "_ModbusSnd: Socket status is not OK!"); + OnModbusClientPanics(ConnectionError); + return 1; + default: + writeDbg(ConnError, "_ModbusSnd: Unknown socket status: %d", gSocketState); + OnModbusClientPanics(SwitchArgumentInvalid); + return 1; + } - bin_to_strhex(buffer, str); + bin_to_strhex(buffer, str); - if (gSocket.Send(buffer, length) != 0) - { - gIpLastErr = gSocket.GetLastSocketError(); + if (gSocket.Send(buffer, length) != 0) + { + gIpLastErr = gSocket.GetLastSocketError(); - if (gIpLastErr != WSA_IO_PENDING) - { - gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); - writeDbg(ConnError, "_ModbusSnd: (%d) %s", gIpLastErr, gIpLastErrStr); - _ModbusDisconnect(); - return 1; - } - // else: tough luck! - } - writeDbg(ConnDebug, "_ModbusSnd: %s (Länge: %d)", str, length); - return 0; + if (gIpLastErr != WSA_IO_PENDING) + { + gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); + writeDbg(ConnError, "_ModbusSnd: (%d) %s", gIpLastErr, gIpLastErrStr); + _ModbusDisconnect(); + return 1; + } + // else: tough luck! + } + writeDbg(ConnDebug, "_ModbusSnd: %s (Länge: %d)", str, length); + return 0; } // This method simply combines the two EthGetLastError functions long _ModbusGetLastConnectionError(char string[]) { - gSocket.GetLastSocketErrorAsString(string, elCount(string)); - return gSocket.GetLastSocketError(); + gSocket.GetLastSocketErrorAsString(string, elCount(string)); + return gSocket.GetLastSocketError(); } // This method receives telegrams (from the TCP/IP API). ModbusRecv() has to be called first void OnTcpReceive(dword socket, long result, dword address, dword port, byte buffer[], dword size) { - _OnModbusReceive(socket, result, address, port, buffer, size); // Hand to Modbus layer + _OnModbusReceive(socket, result, address, port, buffer, size); // Hand to Modbus layer } \ No newline at end of file diff --git a/Modbus-CAPL/include/CAPL/include/ModbusUdp.cin b/Modbus-CAPL/include/CAPL/include/ModbusUdp.cin index 8c80f15..5e29a10 100644 --- a/Modbus-CAPL/include/CAPL/include/ModbusUdp.cin +++ b/Modbus-CAPL/include/CAPL/include/ModbusUdp.cin @@ -2,188 +2,188 @@ // This file contains functions that abstract the UDP/IP API /// It provides following methods -/// - ModbusConnectTo() Prepare anything that sending works. Here: Open a UDP socket -/// - ModbusDisconnect() Gracefully disconnect from the device. Here: Close the UDP socket -/// - ModbusRecv() Receive data from the device. Here: Wait for a UDP packet -/// - ModbusSnd() Send data to the device. Here: Send a packet on the UDP connection to the remote device 'gIpRemote' +/// - ModbusConnectTo() Prepare anything that sending works. Here: Open a UDP socket +/// - ModbusDisconnect() Gracefully disconnect from the device. Here: Close the UDP socket +/// - ModbusRecv() Receive data from the device. Here: Wait for a UDP packet +/// - ModbusSnd() Send data to the device. Here: Send a packet on the UDP connection to the remote device 'gIpRemote' includes { - #include "Common.cin" - #include "TcpUdpEilCommon.cin" + #include "Common.cin" + #include "TcpUdpEilCommon.cin" } variables { - UdpSocket gSocket; + UdpSocket gSocket; } // This method opens an UDP socket. It has to check for several errors. word _UdpOpenSocket() { - byte i; - char errorText[200]; - long error; + byte i; + char errorText[200]; + long error; - if (EthGetAdapterStatus() != 2) // EthernetIL says: Not connected - { - writeDbg(ConnError, "UdpOpenSocket: Adapter status not ok: %d!", EthGetAdapterStatus()); - OnModbusClientPanics(ConnectionError); - return INVALID_IP; - } + if (EthGetAdapterStatus() != 2) // EthernetIL says: Not connected + { + writeDbg(ConnError, "UdpOpenSocket: Adapter status not ok: %d!", EthGetAdapterStatus()); + OnModbusClientPanics(ConnectionError); + return INVALID_IP; + } - // Try to open socket - 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); - OnModbusClientPanics(ConnectionError); - return error; - } - else - { - writeDbg(ConnInfo, "Udp socket opened."); - } - return 0; + // Try to open socket + 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); + OnModbusClientPanics(ConnectionError); + return error; + } + else + { + writeDbg(ConnInfo, "Udp socket opened."); + } + return 0; } // This method prepares anything in a way that sending with ModbusSnd() is possible. // Here: The method will open a UDP socket and save the IP and Port in global variables so they can be used when sending word _ModbusConnectTo(char Remote_IP[], word remotePort) { - dword remoteIp; + dword remoteIp; - // Convert IP string to Number - remoteIp = IpGetAddressAsNumber(Remote_IP); - if (remoteIp == INVALID_IP) - { - writeDbg(ConnError, "ModbusConnectTo: invalid server Ip address: %s", Remote_IP); - OnModbusClientPanics(ConnectionError); - return 1; - } + // Convert IP string to Number + remoteIp = IpGetAddressAsNumber(Remote_IP); + if (remoteIp == INVALID_IP) + { + writeDbg(ConnError, "ModbusConnectTo: invalid server Ip address: %s", Remote_IP); + OnModbusClientPanics(ConnectionError); + return 1; + } - return _ModbusConnectTo(remoteIp, remotePort); + return _ModbusConnectTo(remoteIp, remotePort); } // This method prepares anything in a way that sending with ModbusSnd() is possible. // Here: The method will open a UDP socket and save the IP and Port in global variables so they can be used when sending word _ModbusConnectTo(dword remoteIp, word remotePort) { - long error; + long error; - // Try to open a socket - error = _UdpOpenSocket(); - if (error != 0) - { - gSocketState = ERROR; - return error; - } + // Try to open a socket + error = _UdpOpenSocket(); + if (error != 0) + { + gSocketState = ERROR; + return error; + } - gRemoteIP = remoteIp; - gRemotePort = remotePort; - gSocketState = OK; - return 0; + gRemoteIP = remoteIp; + gRemotePort = remotePort; + gSocketState = OK; + return 0; } // This method will gracefully disconnect from the remote device. // Here: Simply close the socket void _ModbusDisconnect() { - gSocket.Close(); - gSocketState = CLOSED; + gSocket.Close(); + gSocketState = CLOSED; } // This method will check for data from the remote device. // Here: Tell the API to check for new UDP datagrams. When data arrived OnUdpReceiveFrom() will be called by the API void _ModbusRecv() { - int result; + int result; - if (gSocketState != OK) - { - writeDbg(ConnError, "ModbusRecv: Socket status is not OK! Doing nothing."); - OnModbusClientPanics(ConnectionError); - return; - } - - result = gSocket.ReceiveFrom(gRxBuffer, elCount(gRxBuffer)); + if (gSocketState != OK) + { + writeDbg(ConnError, "ModbusRecv: Socket status is not OK! Doing nothing."); + OnModbusClientPanics(ConnectionError); + return; + } + + result = gSocket.ReceiveFrom(gRxBuffer, elCount(gRxBuffer)); - if (result != 0) // Calling OnUdpReceiveFrom otherwise - { - gIpLastErr = gSocket.GetLastSocketError(); + if (result != 0) // Calling OnUdpReceiveFrom otherwise + { + gIpLastErr = gSocket.GetLastSocketError(); - if (gIpLastErr != WSA_IO_PENDING) // Calling OnUdpReceive otherwise - { - gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elCount(gIpLastErrStr)); - writeDbg(ConnError, "UdpReceiveFrom: (%d) %s", gIpLastErr, gIpLastErrStr); - _ModbusDisconnect(); - } - } + if (gIpLastErr != WSA_IO_PENDING) // Calling OnUdpReceive otherwise + { + gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elCount(gIpLastErrStr)); + writeDbg(ConnError, "UdpReceiveFrom: (%d) %s", gIpLastErr, gIpLastErrStr); + _ModbusDisconnect(); + } + } - return; + return; } // This method will send the payload 'buffer' to the device. // Here: Call the appropriate API function byte _ModbusSnd(byte buffer[], word length) { - char str[20*3]; + char str[20*3]; - switch (gSocketState) - { - case OK: // Send - break; - case CLOSED: // If the connection is closed - _ModbusConnectTo(gRemoteIP, gRemotePort); // Try to (re)connect - if (gSocketState != OK) // If this didn't work - { - writeDbg(ConnError, "ModbusSnd: Reconnecting failed!"); - OnModbusClientPanics(ConnectionError); - return 1; - } - case NULL: // Delay - case CONNECTING: - return 1; - case ERROR: - writeDbg(ConnError, "_ModbusSnd: Socket status is not OK!"); - OnModbusClientPanics(ConnectionError); - return 1; - default: - writeDbg(ConnError, "_ModbusSnd: Unknown socket status: %d", gSocketState); - OnModbusClientPanics(SwitchArgumentInvalid); - return 1; - } + switch (gSocketState) + { + case OK: // Send + break; + case CLOSED: // If the connection is closed + _ModbusConnectTo(gRemoteIP, gRemotePort); // Try to (re)connect + if (gSocketState != OK) // If this didn't work + { + writeDbg(ConnError, "ModbusSnd: Reconnecting failed!"); + OnModbusClientPanics(ConnectionError); + return 1; + } + case NULL: // Delay + case CONNECTING: + return 1; + case ERROR: + writeDbg(ConnError, "_ModbusSnd: Socket status is not OK!"); + OnModbusClientPanics(ConnectionError); + return 1; + default: + writeDbg(ConnError, "_ModbusSnd: Unknown socket status: %d", gSocketState); + OnModbusClientPanics(SwitchArgumentInvalid); + return 1; + } - bin_to_strhex(buffer, str); - writeDbg(ConnDebug, "ModbusSnd: %s (Länge: %d, Time: %f)", str, length, timeNowFloat()/100000.0); - - if (gSocket.SendTo(gRemoteIP, gRemotePort, buffer, length) != 0) - { - gIpLastErr = gSocket.GetLastSocketError(); + bin_to_strhex(buffer, str); + writeDbg(ConnDebug, "ModbusSnd: %s (Länge: %d, Time: %f)", str, length, timeNowFloat()/100000.0); + + if (gSocket.SendTo(gRemoteIP, gRemotePort, buffer, length) != 0) + { + gIpLastErr = gSocket.GetLastSocketError(); - if (gIpLastErr != WSA_IO_PENDING) - { - gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); - writeDbg(ConnError, "ModbusSnd error (%d): %s", gIpLastErr, gIpLastErrStr); - _ModbusDisconnect(); - return 1; - } - // else: tough luck! - } - return 0; + if (gIpLastErr != WSA_IO_PENDING) + { + gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); + writeDbg(ConnError, "ModbusSnd error (%d): %s", gIpLastErr, gIpLastErrStr); + _ModbusDisconnect(); + return 1; + } + // else: tough luck! + } + return 0; } // This method simply combines the two EthGetLastError functions long _ModbusGetLastConnectionError(char string[]) { - gSocket.GetLastSocketErrorAsString(string, elCount(string)); - return gSocket.GetLastSocketError(); + gSocket.GetLastSocketErrorAsString(string, elCount(string)); + return gSocket.GetLastSocketError(); } // This method receives datagrams (from the UDP/IP API). ModbusRecv() has to be called first void OnUdpReceiveFrom(dword socket, long result, dword address, dword port, byte buffer[], dword size) { - _OnModbusReceive(socket, result, address, port, buffer, size); // Hand to Modbus layer + _OnModbusReceive(socket, result, address, port, buffer, size); // Hand to Modbus layer } \ No newline at end of file diff --git a/Modbus-CAPL/include/CAPL/include/TcpUdpEilCommon.cin b/Modbus-CAPL/include/CAPL/include/TcpUdpEilCommon.cin index 630edec..1502418 100644 --- a/Modbus-CAPL/include/CAPL/include/TcpUdpEilCommon.cin +++ b/Modbus-CAPL/include/CAPL/include/TcpUdpEilCommon.cin @@ -2,21 +2,21 @@ variables { - // Some constants - const long WSA_IO_PENDING = 997; - const long WSAEWOULDBLOCK = 10035; - const dword INVALID_IP = 0xFFFFFFFF; + // Some constants + const long WSA_IO_PENDING = 997; + const long WSAEWOULDBLOCK = 10035; + const dword INVALID_IP = 0xFFFFFFFF; - long gIpLastErr = 0; - char gIpLastErrStr[512] = ""; + long gIpLastErr = 0; + char gIpLastErrStr[512] = ""; - // The state of the socket will be safed here. This way we can check if we can send/receive packets - enum SocketState {ERROR = 0, NULL = 100, CONNECTING = 120, CLOSED = 140, OK = 200}; - enum SocketState gSocketState = NULL; + // The state of the socket will be safed here. This way we can check if we can send/receive packets + enum SocketState {ERROR = 0, NULL = 100, CONNECTING = 120, CLOSED = 140, OK = 200}; + enum SocketState gSocketState = NULL; - dword gRemoteIP = INVALID_IP; - word gRemotePort = 0; + dword gRemoteIP = INVALID_IP; + word gRemotePort = 0; - // The buffer in which received telegrams are saved - byte gRxBuffer[8192]; + // The buffer in which received telegrams are saved + byte gRxBuffer[8192]; } diff --git a/Modbus-DLL/include/CAPL/MakeConfig.can b/Modbus-DLL/include/CAPL/MakeConfig.can index f2c2d2d..028e3be 100644 --- a/Modbus-DLL/include/CAPL/MakeConfig.can +++ b/Modbus-DLL/include/CAPL/MakeConfig.can @@ -1,155 +1,155 @@ /*@!Encoding:1252*/ includes { - #include "include/ModbusUdpClientCommon.cin" - #include "include/ModbusFunctions.cin" + #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; - }; + 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[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 + 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; + file f; + byte gIpNets[long]; + struct device gIpsSorted[long]; + dword gScanFirst, gScanLast; + word ADi, ADn, ADl; - byte gMaxTransmissionCount; + 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); - */ + // 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); + // 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; + // 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; + gMaxTransmissionCount = @sysvar::Config::Modbus::MaxTransmissionCount; - if (gIps.Size() == 0) - DetectDevices(); - else - MakeIpNets(); + if (gIps.Size() == 0) + DetectDevices(); + else + MakeIpNets(); } /// void PutString(file f, char str[]) { - f.PutString(str, strlen(str)); + f.PutString(str, strlen(str)); } /// void PutString(file f, word d) { - char str[6]; - ltoa(d, str, 10); - f.PutString(str, strlen(str)); + char str[6]; + ltoa(d, str, 10); + f.PutString(str, strlen(str)); } /// void PutString(file f, byte d) { - char str[4]; - ltoa(d, str, 10); - f.PutString(str, strlen(str)); + char str[4]; + ltoa(d, str, 10); + f.PutString(str, strlen(str)); } // Step 1: Detect active devices and collect IP addresses /// 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); + @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); } /// 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); + // 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); } /// void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - DetectDevicesNext(); + DetectDevicesNext(); } /// void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq) { - ipGetAddressAsString(gScanFirst, gIps[gScanFirst], 16); - DetectDevicesNext(); + ipGetAddressAsString(gScanFirst, gIps[gScanFirst], 16); + DetectDevicesNext(); } // Step 2: Sort into subnets @@ -157,28 +157,28 @@ void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[] /// void MakeIpNets() { - long ipNum; + long ipNum; - if (gIps.Size() == 0) - { - stop(); - return; - } + if (gIps.Size() == 0) + { + stop(); + return; + } - for (long i : gIps) - { - ipNum = ipGetAddressAsNumber(gIps[i]); // convert IP to dword + 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 + 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); - } + gIps.Remove(i); + } - AnalyzeDevices(); + AnalyzeDevices(); } @@ -186,302 +186,302 @@ void MakeIpNets() /// 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); + 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); } /// void AnalyzeDevicesNext() { - if (++ADi >= ADl) // we have analyzed all devices - { - MakeFiles(); - return; - } + 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); + 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); } /// 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; - } + 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; + } } /// void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq) { - byte i; + 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; - } + 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(); + if (++ADn == 6) + AnalyzeDevicesNext(); } // Step 4: Create the files with the queried data /// void MakeFiles() { - GenSysvars(); - GenDbc(); - stop(); + GenSysvars(); + GenDbc(); + stop(); } // Generate the SysVars XML /// void GenSysvars() { - write("GenSysvars() -> %s", fnSysvar); - f.Open(fnSysvar, 0, 0); // rewrite file in ASCII + write("GenSysvars() -> %s", fnSysvar); + f.Open(fnSysvar, 0, 0); // rewrite file in ASCII - PutString(f, "\n"); - PutString(f, "\n"); - PutString(f, " \n"); + PutString(f, "\n"); + PutString(f, "\n"); + PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); - for (long net : gIpNets) - { - byte nett; - nett = net; - PutString(f, " \n"); + for (long net : gIpNets) + { + byte nett; + nett = net; + PutString(f, " \n"); - for (long ipN : gIpsSorted) - { + for (long ipN : gIpsSorted) + { - if (((ipN >> 16) & 0xFF) != net) - continue; + if (((ipN >> 16) & 0xFF) != net) + continue; - PutString(f, " \n"); + PutString(f, " \n"); - // Namespace Config - PutString(f, " \n"); - // IP - PutString(f, " \n"); - // Intveral - PutString(f, " \n"); - PutString(f, " \n"); + // Namespace Config + PutString(f, " \n"); + // IP + PutString(f, " \n"); + // Intveral + PutString(f, " \n"); + PutString(f, " \n"); - //Namespace Info - PutString(f, " \n"); - // Vendor - PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - // SerialCode - PutString(f, " \n"); - // DeviceCode - PutString(f, " \n"); - // Modules - gIpsSorted[ipN].DeviceIOs.Modules[strlen(gIpsSorted[ipN].DeviceIOs.Modules)-1] = 0; - PutString(f, " \n"); - // InputRegisters - PutString(f, " \n"); - // InputBits - PutString(f, " \n"); - // OutputRegisters - PutString(f, " \n"); - // OutputBits - PutString(f, " \n"); - PutString(f, " \n"); + //Namespace Info + PutString(f, " \n"); + // Vendor + PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); + PutString(f, " \n"); + // SerialCode + PutString(f, " \n"); + // DeviceCode + PutString(f, " \n"); + // Modules + gIpsSorted[ipN].DeviceIOs.Modules[strlen(gIpsSorted[ipN].DeviceIOs.Modules)-1] = 0; + PutString(f, " \n"); + // InputRegisters + PutString(f, " \n"); + // InputBits + PutString(f, " \n"); + // OutputRegisters + PutString(f, " \n"); + // OutputBits + PutString(f, " \n"); + PutString(f, " \n"); - // Namespace Data - PutString(f, " \n"); - // InputRegisters - PutString(f, " \n"); - // InputBits - PutString(f, " \n"); - // OutputRegisters - PutString(f, " \n"); - // OutputBits - PutString(f, " \n"); + // Namespace Data + PutString(f, " \n"); + // InputRegisters + PutString(f, " \n"); + // InputBits + PutString(f, " \n"); + // OutputRegisters + PutString(f, " \n"); + // OutputBits + PutString(f, " \n"); - PutString(f, " \n"); - PutString(f, " \n"); - } - PutString(f, " \n"); - } + PutString(f, " \n"); + PutString(f, " \n"); + } + PutString(f, " \n"); + } - PutString(f, " \n"); - PutString(f, "\n"); - - f.Close(); + PutString(f, " \n"); + PutString(f, "\n"); + + f.Close(); } // Generate the Database /// void GenDbc() { - write("GenDbc() -> %s", fnDbc); - f.Open(fnDbc, 0, 0); // rewrite file in ASCII + 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_:"); + 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"); + 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(); + f.Close(); } @@ -494,16 +494,16 @@ void GenDbc() /// 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; - } + writeLineEx(0, 4, "<%NODE_NAME%> FATAL! %d", reason); + switch(reason) + { + case ParsingBuffer: + case ModbusPackageWasSplit: + case DeviceCodeUnknown: + case VendorIdUnknown: + case ConnectionError: + break; + } } /// void OnModbusWriteBitFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap){} diff --git a/Modbus-DLL/include/CAPL/ModbusClient.can b/Modbus-DLL/include/CAPL/ModbusClient.can index 5391fad..e780b36 100644 --- a/Modbus-DLL/include/CAPL/ModbusClient.can +++ b/Modbus-DLL/include/CAPL/ModbusClient.can @@ -2,83 +2,83 @@ includes { - #include "include\ModbusEilDllClientCommon.cin" - #include "include\ModbusFunctions.cin" + #include "include\ModbusEilDllClientCommon.cin" + #include "include\ModbusFunctions.cin" } variables { - msTimer gtRead; - - //message Client_2_RecBits rb; - //message Client_2_Ex81 ex; + msTimer gtRead; + + //message Client_2_RecBits rb; + //message Client_2_Ex81 ex; } // Get information of local network interface such like ip address on preStart { - writeClear(0); - setStartdelay(10); - OutputDebugLevel = Debug; + writeClear(0); + setStartdelay(10); + OutputDebugLevel = Debug; } on start { - ModbusInit(); + 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); + // 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); - setTimerCyclic(gtRead, 1, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval); + 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; + 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; - } + 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; + 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; - } + 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) @@ -103,51 +103,51 @@ void OnModbusWriteRegistersFailed(enum ModbusRequestError error, enum ModbusExce void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq) { - word i; + 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; - } + 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; + 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; - } + 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) @@ -168,88 +168,88 @@ 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; - } + 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); + 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]; + 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; + 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]; + for (i = 0; i < count; i++) + bitStatus[i] = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits[i]; - ModbusWriteBitsB(firstBitAddr, count, bitStatus); + ModbusWriteBitsB(firstBitAddr, count, bitStatus); } on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters { - word count, i; - word regValues[123]; + word count, i; + word regValues[123]; - count = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters; + 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]; + for (i = 0; i < count; i++) + regValues[i] = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters[i]; - ModbusWriteRegisters(0x000, count, regValues); + ModbusWriteRegisters(0x000, count, regValues); }*/ on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval { - if (@this <= 0) - gtRead.Cancel(); - else - setTimerCyclic(gtRead, @this); + if (@this <= 0) + gtRead.Cancel(); + else + setTimerCyclic(gtRead, @this); } on key '+' { - word i; + 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"); + 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; + 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"); + 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"); } /* on message rb { - write("Hello! Read Bits =)"); + write("Hello! Read Bits =)"); } on message ex { - write("Oh no, exception!"); + write("Oh no, exception!"); }*/ \ No newline at end of file diff --git a/Modbus-DLL/include/CAPL/include/Common.cin b/Modbus-DLL/include/CAPL/include/Common.cin index 8c51bc9..2dd956b 100644 --- a/Modbus-DLL/include/CAPL/include/Common.cin +++ b/Modbus-DLL/include/CAPL/include/Common.cin @@ -2,181 +2,181 @@ variables { - enum DebugLvl { - Debug = 0x00, - AlgoDebug = 0x02, - ConnDebug = 0x04, - MbDebug = 0x07, + enum DebugLvl { + Debug = 0x00, + AlgoDebug = 0x02, + ConnDebug = 0x04, + MbDebug = 0x07, - Info = 0x10, - AlgoInfo = 0x12, - ConnInfo = 0x14, - MbInfo = 0x17, + Info = 0x10, + AlgoInfo = 0x12, + ConnInfo = 0x14, + MbInfo = 0x17, - Warning = 0x20, - AlgoWarning = 0x22, - ConnWarning = 0x24, - MbWarning = 0x27, + Warning = 0x20, + AlgoWarning = 0x22, + ConnWarning = 0x24, + MbWarning = 0x27, - Error = 0x30, - AlgoError = 0x32, - ConnError = 0x34, - MbError = 0x37 + Error = 0x30, + AlgoError = 0x32, + ConnError = 0x34, + MbError = 0x37 }; - char DebugLvlStr[4][8] = {"Debug", "Info", "Warning", "Error"}; - enum DebugLvl OutputDebugLevel = Debug; + char DebugLvlStr[4][8] = {"Debug", "Info", "Warning", "Error"}; + enum DebugLvl OutputDebugLevel = Debug; } /// 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)); + strncpy(msg, "<%NODE_NAME%> ", elCount(msg)); + strncat(msg, DebugLvlStr[lVl], elCount(msg)); + strncat(msg, ": ", elCount(msg)); + strncat(msg, format, elCount(msg)-strlen(msg)); } /// void writeDbg(enum DebugLvl lvl, char format[]) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg); } /// void writeDbg(enum DebugLvl lvl, char format[], char string[]) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, string); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, string); } /// void writeDbg(enum DebugLvl lvl, char format[], char string1[], char string2[]) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, string1, string2); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, string1, string2); } /// void writeDbg(enum DebugLvl lvl, char format[], long num, char string[]) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num, string); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num, string); } /// void writeDbg(enum DebugLvl lvl, char format[], char string[], long num) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, string, num); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, string, num); } /// void writeDbg(enum DebugLvl lvl, char format[], long num1) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1); } /// void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, char string[]) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1, num2, string); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1, num2, string); } /// void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1, num2); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1, num2); } /// void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, long num3) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1, num2, num3); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1, num2, num3); } /// void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, long num3, long num4) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1, num2, num3, num4); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1, num2, num3, num4); } /// void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, long num3, long num4, long num5, long num6) { - char msg[500]; - byte lVl; + char msg[500]; + byte lVl; - if (lvl < OutputDebugLevel) - return; - lVl = (byte)lvl >> 4; + if (lvl < OutputDebugLevel) + return; + lVl = (byte)lvl >> 4; - writeDbgFormat(lVl, msg, format); - writeLineEx(1, lVl, msg, num1, num2, num3, num4, num5, num6); + writeDbgFormat(lVl, msg, format); + writeLineEx(1, lVl, msg, num1, num2, num3, num4, num5, num6); } @@ -184,80 +184,80 @@ void writeDbg(enum DebugLvl lvl, char format[], long num1, long num2, long num3, 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; + 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] = ' '; - } + 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; + 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; + 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] = ' '; - } + 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; + 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; + 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] = ' '; - } + 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; + if (elCount(bin) > 20) // trailing "..." + { + result[96] = '.'; + result[97] = '.'; + result[98] = '.'; + } + result[(byte)(binsz * 2.5) - 1] = 0; } \ No newline at end of file diff --git a/Modbus-DLL/include/CAPL/include/EilCommon.cin b/Modbus-DLL/include/CAPL/include/EilCommon.cin index 02f970b..3237ee5 100644 --- a/Modbus-DLL/include/CAPL/include/EilCommon.cin +++ b/Modbus-DLL/include/CAPL/include/EilCommon.cin @@ -1,119 +1,119 @@ /*@!Encoding:1252*/ includes { - #include "Common.cin" - #include "TcpUdpCommon.cin" + #include "Common.cin" + #include "TcpUdpCommon.cin" } variables { - long gPacket; - msTimer gtArp; - - byte gLocalMac[6]; - byte gRemoteMac[6]; - dword gLocalIP = 0xC0A80101; + long gPacket; + msTimer gtArp; + + byte gLocalMac[6]; + byte gRemoteMac[6]; + dword gLocalIP = 0xC0A80101; } word EilConnectTo(char Remote_IP[], word remotePort) { - dword remoteIp; + 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(); - } + // 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); + return EilConnectTo(remoteIp, remotePort); } word EilConnectTo(dword remoteIp, word remotePort) { - long error; - byte broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + 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; - } + 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); + // 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; - } + 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); + 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"); + EthReceivePacket("OnEthReceivePacket"); - EthCompletePacket(gPacket); - EthOutputPacket(gPacket); - EthReleasePacket(gPacket); - gSocketState = NULL; - gtArp.set(@sysvar::Config::Modbus::RequestTimeout); - return 0; + 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; - } + 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); + 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; + gSocketState = OK; } void EilDisconnect() { - if (gPacket != 0) - { - EthReleasePacket(gPacket); - gPacket = 0; - } - gSocketState = CLOSED; + if (gPacket != 0) + { + EthReleasePacket(gPacket); + gPacket = 0; + } + gSocketState = CLOSED; } @@ -123,45 +123,45 @@ void EilRecv() byte EilSnd(byte buffer[], word length) { - char str[20*3]; + 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; - } + 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); + 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); + EthResizeToken(gPacket, "udp", "data" , length*8); + EthSetTokenData(gPacket, "udp", "data" , length, buffer); - EthCompletePacket(gPacket); - EthOutputPacket(gPacket); + EthCompletePacket(gPacket); + EthOutputPacket(gPacket); - return 0; + return 0; } long EilGetLastConnectionError(char string[]) { - EthGetLastErrorText(elCount(string), string); - return EthGetLastError(); + 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); + gSocketState = ERROR; + writeDbg(ConnError, "No (valid) ARP response detected. The host seems to be offline!"); + OnModbusClientPanics(ConnectionError); } \ No newline at end of file diff --git a/Modbus-DLL/include/CAPL/include/EilDllCommon.cin b/Modbus-DLL/include/CAPL/include/EilDllCommon.cin index 88eaa50..5f420eb 100644 --- a/Modbus-DLL/include/CAPL/include/EilDllCommon.cin +++ b/Modbus-DLL/include/CAPL/include/EilDllCommon.cin @@ -1,119 +1,119 @@ /*@!Encoding:1252*/ includes { - #include "Common.cin" - #include "TcpUdpCommon.cin" + #include "Common.cin" + #include "TcpUdpCommon.cin" } variables { - long gPacket; - msTimer gtArp; - - byte gLocalMac[6]; - byte gRemoteMac[6]; - dword gLocalIP = 0xC0A80101; + long gPacket; + msTimer gtArp; + + byte gLocalMac[6]; + byte gRemoteMac[6]; + dword gLocalIP = 0xC0A80101; } word EilConnectTo(char Remote_IP[], word remotePort) { - dword remoteIp; + dword remoteIp; - // Convert IP string to Number - remoteIp = IpGetAddressAsNumber(Remote_IP); - if (remoteIp == ~1) - { - writeDbg(ConnError, "EilConnectTo: invalid server Ip address!"); - OnModbusClientPanics(ConnectionError); - return ipGetLastError(); - } + // Convert IP string to Number + remoteIp = IpGetAddressAsNumber(Remote_IP); + if (remoteIp == ~1) + { + writeDbg(ConnError, "EilConnectTo: invalid server Ip address!"); + OnModbusClientPanics(ConnectionError); + return ipGetLastError(); + } - return EilConnectTo(remoteIp, remotePort); + return EilConnectTo(remoteIp, remotePort); } word EilConnectTo(dword remoteIp, word remotePort) { - long error; - byte broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + 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; - } + 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); + // 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; - } + 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); + 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"); + EthReceivePacket("OnEthReceivePacket"); - EthCompletePacket(gPacket); - EthOutputPacket(gPacket); - EthReleasePacket(gPacket); - gSocketState = NULL; - gtArp.set(@sysvar::Config::Modbus::RequestTimeout); - return 0; + EthCompletePacket(gPacket); + EthOutputPacket(gPacket); + EthReleasePacket(gPacket); + gSocketState = NULL; + gtArp.set(@sysvar::Config::Modbus::RequestTimeout); + return 0; } void EilConnectTo2() { - gPacket = EthInitPacket("modbus"); - if (gPacket == 0) - { - gSocketState = ERROR; - writeDbg(ConnError, "EthInitPacket: Could not create Modbus packet: %d", EthGetLastError()); - OnModbusClientPanics(ConnectionError); - return; - } + gPacket = EthInitPacket("modbus"); + if (gPacket == 0) + { + gSocketState = ERROR; + writeDbg(ConnError, "EthInitPacket: Could not create Modbus 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); // we dont need those - //EthSetTokenInt(gPacket, "udp", "destination" , 502); // we do use modbus defaults + 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); // we dont need those + //EthSetTokenInt(gPacket, "udp", "destination" , 502); // we do use modbus defaults - gSocketState = OK; + gSocketState = OK; } void EilDisconnect() { - if (gPacket != 0) - { - EthReleasePacket(gPacket); - gPacket = 0; - } - gSocketState = CLOSED; + if (gPacket != 0) + { + EthReleasePacket(gPacket); + gPacket = 0; + } + gSocketState = CLOSED; } @@ -123,45 +123,45 @@ void EilRecv() byte EilSnd(byte buffer[], word length) { - char str[20*3]; + 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; - } + 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); + bin_to_strhex(buffer, str); + writeDbg(ConnDebug, "EilSnd: %s (Länge: %d)", str, length); - EthResizeToken(gPacket, "modbus", "data" , length*8); - EthSetTokenData(gPacket, "modbus", "data" , length, buffer); + EthResizeToken(gPacket, "modbus", "data" , length*8); + EthSetTokenData(gPacket, "modbus", "data" , length, buffer); - EthCompletePacket(gPacket); - EthOutputPacket(gPacket); + EthCompletePacket(gPacket); + EthOutputPacket(gPacket); - return 0; + return 0; } long EilGetLastConnectionError(char string[]) { - EthGetLastErrorText(elCount(string), string); - return EthGetLastError(); + 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); + gSocketState = ERROR; + writeDbg(ConnError, "No (valid) ARP response detected. The host seems to be offline!"); + OnModbusClientPanics(ConnectionError); } \ No newline at end of file diff --git a/Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin b/Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin index 2e105d1..b12fd6f 100644 --- a/Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin +++ b/Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin @@ -2,51 +2,51 @@ // Additionally include ModbusTcpCommon.cin or ModbusUdpCommon.cin includes { - #include "ModbusStructs.cin" + #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 + 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 - { - byte FuncCode; - word TimeoutTicks; - byte Timeouts; - word Length; - byte Buffer[gMaxPacketLength]; - }; - struct QueueElement gQueuePending[long, 2]; - struct QueueElement gQueueSent[long, 2]; - struct QueueElement gQueueAck[long, 2]; + // Global storage for pending and sent requests, associated by TxID + struct QueueElement + { + byte FuncCode; + 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" - }; + 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)); + 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); + writeDbg(MbInfo, "Connecting to %s:%d", ip, @sysvar::Config::Modbus::Port); + ModbusConnectTo(ip, @sysvar::Config::Modbus::Port); } @@ -55,50 +55,50 @@ void ModbusInit() /// void ModbusReadBits(word address, word count) { - const byte length = __size_of(struct ModbusReqRead); - const byte funcCode = 0x01; - byte buffer[length]; - struct ModbusReqRead mbr; + const byte length = __size_of(struct ModbusReqRead); + const byte funcCode = 0x01; + byte buffer[length]; + struct ModbusReqRead mbr; - mbr.Address = address; - mbr.Count = count; + mbr.Address = address; + mbr.Count = count; - writeDbg(MbDebug, "Sending 'Read Bits' (0x01) command. Addr: 0x%04X, Count: %d", address, count); + writeDbg(MbDebug, "Sending 'Read Bits' (0x01) command. Addr: 0x%04X, Count: %d", address, count); - memcpy_h2n(buffer, mbr); - ModbusSend(buffer, length, funcCode); + memcpy_h2n(buffer, mbr); + ModbusSend(buffer, length, funcCode); } /// void OnModbusReceiveBits(struct ModbusApHeader mbap, byte buffer[]) { - struct ModbusResReceiveBits mbres; - struct ModbusReqRead mbreq; - byte bitStatus[1968]; - word numBits; - byte i, j; + struct ModbusResReceiveBits mbres; + struct ModbusReqRead mbreq; + byte bitStatus[1968]; + word numBits; + byte i, j; - memcpy_n2h(mbres, buffer); - memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); + memcpy_n2h(mbres, buffer); + memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); - writeDbg(MbInfo, "Received %d bits from 0x%04X", mbreq.Count, mbreq.Address); + writeDbg(MbInfo, "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; - } - } + 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); + OnModbusReadBitsSuccess(mbres, bitStatus, mbreq); } /// void OnModbusReceiveBitsException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while reading bits: %s", ModbusExceptions[ex-1]); - OnModbusReadBitsFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while reading bits: %s", ModbusExceptions[ex-1]); + OnModbusReadBitsFailed(Exception, ex, mbap); } @@ -107,41 +107,41 @@ void OnModbusReceiveBitsException(struct ModbusApHeader mbap, enum ModbusExcepti // REGION: ModbusReadRegisters ------------------------------------------------------- /// -void ModbusReadRegisters(word address, word count) // 16 bit +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; + const byte length = __size_of(struct ModbusReqRead); + const byte funcCode = 0x03; + byte buffer[length]; + struct ModbusReqRead mbr; - mbr.Address = address; // [2] Start address - mbr.Count = count; // [2] Number of items; 1:max 125=0x7D + 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); + writeDbg(MbDebug, "Sending 'Read Registers' (0x03) command. Addr: 0x%04X, Count: %d", address, count); - memcpy_h2n(buffer, mbr); - ModbusSend(buffer, length, funcCode); + memcpy_h2n(buffer, mbr); + ModbusSend(buffer, length, funcCode); } /// void OnModbusReceiveRegisters(struct ModbusApHeader mbap, byte buffer[]) { - struct ModbusResReceiveRegisters mbres; - struct ModbusReqRead mbreq; + struct ModbusResReceiveRegisters mbres; + struct ModbusReqRead mbreq; - memcpy_n2h(mbres, buffer); - memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); + memcpy_n2h(mbres, buffer); + memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); - writeDbg(MbInfo, "Received %d registers from 0x%04X", mbreq.Count, mbreq.Address); + writeDbg(MbInfo, "Received %d registers from 0x%04X", mbreq.Count, mbreq.Address); - OnModbusReadRegistersSuccess(mbres, mbreq); + OnModbusReadRegistersSuccess(mbres, mbreq); } /// void OnModbusReceiveRegistersException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while reading registers: %s", ModbusExceptions[ex-1]); - OnModbusReadRegistersFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while reading registers: %s", ModbusExceptions[ex-1]); + OnModbusReadRegistersFailed(Exception, ex, mbap); } @@ -152,40 +152,40 @@ void OnModbusReceiveRegistersException(struct ModbusApHeader mbap, enum ModbusEx /// void ModbusWriteBit(word address, byte value) { - const byte length = __size_of(struct ModbusReqWriteSingle); - const byte funcCode = 0x05; - byte buffer[length]; - struct ModbusReqWriteSingle mbw; + const byte length = __size_of(struct ModbusReqWriteSingle); + const byte funcCode = 0x05; + byte buffer[length]; + struct ModbusReqWriteSingle mbw; - if (value >= 1) - value = 0xFF; + if (value >= 1) + value = 0xFF; - mbw.Address = address; // [2] Output address - mbw.Value = value << 8; // [2] Output value (0x0000: Off, 0xFF00: On) + 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, funcCode); + writeDbg(Debug, "Sending 'Write Bit' (0x05) command. Addr: 0x%04X, Value: 0x%02X", address, value); + + memcpy_h2n(buffer, mbw); + ModbusSend(buffer, length, funcCode); } /// void OnModbusConfirmBit(struct ModbusApHeader mbap, byte buffer[]) { - struct ModbusResConfirmSingle mbc; + struct ModbusResConfirmSingle mbc; - memcpy_n2h(mbc, buffer); + memcpy_n2h(mbc, buffer); - writeDbg(MbInfo, "Set bit at 0x%04X to %d", mbc.Address, mbc.Value); + writeDbg(MbInfo, "Set bit at 0x%04X to %d", mbc.Address, mbc.Value); - OnModbusWriteBitSuccess(mbc); + OnModbusWriteBitSuccess(mbc); } /// void OnModbusConfirmBitException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while writing bit: %s", ModbusExceptions[ex-1]); - OnModbusWriteBitFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while writing bit: %s", ModbusExceptions[ex-1]); + OnModbusWriteBitFailed(Exception, ex, mbap); } @@ -196,37 +196,37 @@ void OnModbusConfirmBitException(struct ModbusApHeader mbap, enum ModbusExceptio /// void ModbusWriteRegister(word address, int value) { - const byte length = __size_of(struct ModbusReqWriteSingle); - const byte funcCode = 0x06; - byte buffer[length]; - struct ModbusReqWriteSingle mbw; + const byte length = __size_of(struct ModbusReqWriteSingle); + const byte funcCode = 0x06; + byte buffer[length]; + struct ModbusReqWriteSingle mbw; - mbw.Address = address; // [2] Output address - mbw.Value = value; // [2] Output value + 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); + writeDbg(MbDebug, "Sending 'Write Register' (0x06) command. Addr: 0x%04X, Value: 0x%02X", address, value); - memcpy_h2n(buffer, mbw); - ModbusSend(buffer, length, funcCode); + memcpy_h2n(buffer, mbw); + ModbusSend(buffer, length, funcCode); } /// void OnModbusConfirmRegister(struct ModbusApHeader mbap, byte buffer[]) { - struct ModbusResConfirmSingle mbc; + struct ModbusResConfirmSingle mbc; - memcpy_n2h(mbc, buffer); + memcpy_n2h(mbc, buffer); - writeDbg(MbInfo, "Set register at 0x%04X to %d", mbc.Address, mbc.Value); + writeDbg(MbInfo, "Set register at 0x%04X to %d", mbc.Address, mbc.Value); - OnModbusWriteRegisterSuccess(mbc); + OnModbusWriteRegisterSuccess(mbc); } /// void OnModbusConfirmRegisterException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while writing register: %s", ModbusExceptions[ex-1]); - OnModbusWriteRegisterFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while writing register: %s", ModbusExceptions[ex-1]); + OnModbusWriteRegisterFailed(Exception, ex, mbap); } @@ -239,84 +239,84 @@ void OnModbusConfirmRegisterException(struct ModbusApHeader mbap, enum ModbusExc /// 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; + 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; + dataLength = _ceil(count / 8.0); + overallLength = maxLength - 1968/8 + dataLength; - 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 -.- + 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); + writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. Addr: 0x%04X, Count: %d", address, count); - memcpy_h2n(buffer, mbw); - ModbusSend(buffer, overallLength, funcCode); + memcpy_h2n(buffer, mbw); + ModbusSend(buffer, overallLength, funcCode); } /// 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]; + 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); + length = (word)_ceil(count / 8.0); + writeDbg(AlgoDebug, "ModbusWriteBitsB: count: %d; length: %d", count, length); - if (count % 8 != 0) - 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]); + 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); + hbin_to_strhex(values, str1); + bin_to_strhex(buffer, str2); + writeDbg(AlgoDebug, "ModbusWriteBitsB: Encoded %s to %s", str1, str2); + ModbusWriteBits(address, count, buffer); } /// void OnModbusConfirmBits(struct ModbusApHeader mbap, byte buffer[]) { - struct ModbusResConfirmMultiple mbc; + struct ModbusResConfirmMultiple mbc; - memcpy_n2h(mbc, buffer); + memcpy_n2h(mbc, buffer); - writeDbg(MbInfo, "Updated &d bits at 0x%04X", mbc.Count, mbc.Address); + writeDbg(MbInfo, "Updated &d bits at 0x%04X", mbc.Count, mbc.Address); - OnModbusWriteBitsSuccess(mbc); + OnModbusWriteBitsSuccess(mbc); } /// void OnModbusConfirmBitsException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while writing bits: %s", ModbusExceptions[ex-1]); - OnModbusWriteBitsFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while writing bits: %s", ModbusExceptions[ex-1]); + OnModbusWriteBitsFailed(Exception, ex, mbap); } @@ -328,45 +328,45 @@ void OnModbusConfirmBitsException(struct ModbusApHeader mbap, enum ModbusExcepti /// 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; + 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; + dataLength = 2 * count; + overallLength = maxLength - 2*123 + dataLength; - 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 + 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]; + for (i = 0; i < dataLength; i++) + mbw.Data[i] = values[i]; - memcpy_h2n(buffer, mbw); - ModbusSend(buffer, overallLength, funcCode); + memcpy_h2n(buffer, mbw); + ModbusSend(buffer, overallLength, funcCode); } /// void OnModbusConfirmRegisters(struct ModbusApHeader mbap, byte buffer[]) { - struct ModbusResConfirmMultiple mbc; + struct ModbusResConfirmMultiple mbc; - memcpy_n2h(mbc, buffer); + memcpy_n2h(mbc, buffer); - writeDbg(MbInfo, "Updated %d registers at 0x%04X", mbc.Count, mbc.Address); + writeDbg(MbInfo, "Updated %d registers at 0x%04X", mbc.Count, mbc.Address); - OnModbusWriteRegistersSuccess(mbc); + OnModbusWriteRegistersSuccess(mbc); } /// void OnModbusConfirmRegistersException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while writing registers: %s", ModbusExceptions[ex-1]); - OnModbusWriteRegistersFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while writing registers: %s", ModbusExceptions[ex-1]); + OnModbusWriteRegistersFailed(Exception, ex, mbap); } @@ -378,36 +378,36 @@ void OnModbusConfirmRegistersException(struct ModbusApHeader mbap, enum ModbusEx /// 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; + const word length = __size_of(struct ModbusReqWriteMasks); + const byte funcCode = 0x16; + byte buffer[length]; + struct ModbusReqWriteMasks mbw; - mbw.Address = address; // [2] Output address - mbw.And = and; // [2] AND mask - mbw.Or = or; // [2] OR mask + 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, funcCode); + memcpy_h2n(buffer, mbw); + ModbusSend(buffer, length, funcCode); } /// void OnModbusConfirmMasks(struct ModbusApHeader mbap, byte buffer[]) { - struct ModbusResConfirmMasks mbc; + struct ModbusResConfirmMasks mbc; - memcpy_n2h(mbc, buffer); + memcpy_n2h(mbc, buffer); - writeDbg(MbInfo, "Applied masks at 0x%04X", mbc.Address); + writeDbg(MbInfo, "Applied masks at 0x%04X", mbc.Address); - OnModbusWriteMasksSuccess(mbc); + OnModbusWriteMasksSuccess(mbc); } /// void OnModbusConfirmMasksException(struct ModbusApHeader mbap, enum ModbusException ex) { - writeDbg(MbError, "Received an Exception while applying masks: %s", ModbusExceptions[ex-1]); - OnModbusWriteMasksFailed(Exception, ex, mbap); + writeDbg(MbError, "Received an Exception while applying masks: %s", ModbusExceptions[ex-1]); + OnModbusWriteMasksFailed(Exception, ex, mbap); } @@ -418,49 +418,49 @@ void OnModbusConfirmMasksException(struct ModbusApHeader mbap, enum ModbusExcept /// 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; + 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; + dataLength = 2 * writeCount; + overallLength = maxLength - 2*121 + dataLength; - 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 + 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]; + for (i = 0; i < dataLength; i++) + mbw.Data[i] = values[i]; - memcpy_h2n(buffer, mbw); - ModbusSend(buffer, overallLength, funcCode); + memcpy_h2n(buffer, mbw); + ModbusSend(buffer, overallLength, funcCode); } /// void OnModbusReceiveConfirmRegisters(struct ModbusApHeader mbap, byte buffer[]) { - struct ModbusResReceiveRegisters mbres; - struct ModbusReqRead mbreq; + struct ModbusResReceiveRegisters mbres; + struct ModbusReqRead mbreq; - memcpy_n2h(mbres, buffer); - memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); + memcpy_n2h(mbres, buffer); + memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer); - writeDbg(MbInfo, "Wrote some registers and received %d registers from 0x%04X", mbreq.Count, mbreq.Address); + writeDbg(MbInfo, "Wrote some registers and received %d registers from 0x%04X", mbreq.Count, mbreq.Address); - OnModbusReadRegistersSuccess(mbres, mbreq); + OnModbusReadRegistersSuccess(mbres, mbreq); } /// 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); + writeDbg(MbError, "Received an Exception while reading and writing registers: %s", ModbusExceptions[ex-1]); + OnModbusWriteRegistersFailed(Exception, ex, mbap); } @@ -475,129 +475,129 @@ void OnModbusReceiveConfirmRegistersException(struct ModbusApHeader mbap, enum M /// <-OnModbusReceive> void OnModbusReceive2(long packet) { - struct ModbusApHeader mbap; - byte buffer[gMaxPacketLength]; - long size; // packet size in bits - //char str[3*20]; - byte header[__size_of(struct ModbusApHeader)]; + struct ModbusApHeader mbap; + byte buffer[gMaxPacketLength]; + long size; // packet size in bits + //char str[3*20]; + byte header[__size_of(struct ModbusApHeader)]; - size = EthGetThisData(0, gMaxPacketLength, buffer); - EthGetTokenData(packet, "modbus", "header", __size_of(struct ModbusApHeader), header); // TODO: EthGetTokenData does not handle endianness :( ///////////////////////////////////////////////// - memcpy_n2h(mbap, header); + size = EthGetThisData(0, gMaxPacketLength, buffer); + EthGetTokenData(packet, "modbus", "header", __size_of(struct ModbusApHeader), header); // TODO: EthGetTokenData does not handle endianness :( ///////////////////////////////////////////////// + memcpy_n2h(mbap, header); - //bin_to_strhex(header, str); - //writeDbg(MbError, "Header: %s", str); - //writeDbg(MbError, "Header Length: 0x%X", mbap.Length); - OnModbusReceive2OnePacket(buffer, size, mbap); + //bin_to_strhex(header, str); + //writeDbg(MbError, "Header: %s", str); + //writeDbg(MbError, "Header Length: 0x%X", mbap.Length); + OnModbusReceive2OnePacket(buffer, size, mbap); } /// <-OnModbusReceive> void OnModbusReceive2OnePacket(byte buffer[], long size, struct ModbusApHeader mbap) { - // Test transaction identifier? - // Test unit/device identifier? - word i; // counter + // Test transaction identifier? + // Test unit/device identifier? + word i; // counter - if (mbap.Length-2 != size) - { - writeDbg(ConnError, "OnModbusReceive2OnePAcket: Packet payload length (%d) is different from specified length (%d)!", size, mbap.Length-2); - return; - } + if (mbap.Length-2 != size) + { + writeDbg(ConnError, "OnModbusReceive2OnePAcket: Packet payload length (%d) is different from specified length (%d)!", size, mbap.Length-2); + return; + } - if (mbap.Protocol != 0) // Protocol is not Modbus (0x0000). Wayne. - { - writeDbg(ConnDebug, "OnModbusReceive2OnePacket: packet is no Modbus packet: Protocol = %d", mbap.Protocol); - return; - } - // MBAP Header is OK :) Go on - - if (!gQueueSent.ContainsKey(mbap.TxID)) // We don't wait for this message! - return; + if (mbap.Protocol != 0) // Protocol is not Modbus (0x0000). Wayne. + { + writeDbg(ConnDebug, "OnModbusReceive2OnePacket: packet is no Modbus packet: Protocol = %d", mbap.Protocol); + 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); + //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[0], mbap); + if (mbap.FuncCode > 0x80) // Oh no, we got a exception! + { + OnModbusReceive2Exceptions(buffer[0], mbap); - gQueueAck.Remove(mbap.TxID); // Remove from acknowledge queue + gQueueAck.Remove(mbap.TxID); // Remove from acknowledge queue - return; - } + return; + } - // Let's give the PDU to the corresponding function - switch (mbap.FuncCode) - { - case 0x01: - case 0x02: - OnModbusReceiveBits(mbap, buffer); - break; - case 0x03: - case 0x04: - OnModbusReceiveRegisters(mbap, buffer); - break; - case 0x05: - OnModbusConfirmBit(mbap, buffer); - break; - case 0x06: - OnModbusConfirmRegister(mbap, buffer); - break; - case 0x0F: - OnModbusConfirmBits(mbap, buffer); - break; - case 0x10: - OnModbusConfirmRegisters(mbap, buffer); - break; - case 0x16: - OnModbusConfirmMasks(mbap, buffer); - break; - case 0x17: - OnModbusReceiveConfirmRegisters(mbap, buffer); - break; - default: - writeDbg(MbError, "OnModbusReceive2OnePacket: We received funcCode 0x%X!?", mbap.FuncCode); - } + // Let's give the PDU to the corresponding function + switch (mbap.FuncCode) + { + case 0x01: + case 0x02: + OnModbusReceiveBits(mbap, buffer); + break; + case 0x03: + case 0x04: + OnModbusReceiveRegisters(mbap, buffer); + break; + case 0x05: + OnModbusConfirmBit(mbap, buffer); + break; + case 0x06: + OnModbusConfirmRegister(mbap, buffer); + break; + case 0x0F: + OnModbusConfirmBits(mbap, buffer); + break; + case 0x10: + OnModbusConfirmRegisters(mbap, buffer); + break; + case 0x16: + OnModbusConfirmMasks(mbap, buffer); + break; + case 0x17: + OnModbusReceiveConfirmRegisters(mbap, buffer); + break; + default: + writeDbg(MbError, "OnModbusReceive2OnePacket: We received funcCode 0x%X!?", mbap.FuncCode); + } - gQueueAck.Remove(mbap.TxID); // Remove from acknowledge queue + gQueueAck.Remove(mbap.TxID); // Remove from acknowledge queue } /// <-OnModbusReceive> void OnModbusReceive2Exceptions(byte exCode, struct ModbusApHeader mbap) { - enum ModbusException ex; - ex = (enum ModbusException)exCode; + 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; - } + 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; + } } @@ -606,113 +606,113 @@ void OnModbusReceive2Exceptions(byte exCode, struct ModbusApHeader mbap) /// <-ModbusSend> void ModbusSend(byte buffer[], word length, byte funcCode) { - struct QueueElement qe; - word TxID; + struct QueueElement qe; + word TxID; - TxID = gTxID++; + TxID = gTxID++; - qe.FuncCode = funcCode; - qe.Length = length; - memcpy(qe.Buffer, buffer, length); + qe.FuncCode = funcCode; + qe.Length = length; + memcpy(qe.Buffer, buffer, length); - memcpy(gQueuePending[TxID], qe); - writeDbg(ConnDebug, "Appended packet 0x%04X to pending queue", TxID); + 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(); + 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); + writeDbg(ConnDebug, "Starting Timer gtRobin"); + setTimerCyclic(gtRobin, 1); } /// <-ModbusSend> on timer gtRobin { - struct ModbusApHeader mbap; - enum ModbusRequestError reqError; + struct ModbusApHeader mbap; + enum ModbusRequestError reqError; - writeDbg(ConnDebug, "gtRobin: Queue Sent: %d, Queue Pending: %d, Queue Ack: %d", gQueueSent.Size(), gQueuePending.Size(), gQueueAck.Size()); + 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; - EthSetTokenInt(gPacket, "modbus", "TxId", TxID); - EthSetTokenInt(gPacket, "modbus", "FuncCode", gQueueSent[TxID].FuncCode); - 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; - } + // 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; + EthSetTokenInt(gPacket, "modbus", "TxId", TxID); + EthSetTokenInt(gPacket, "modbus", "FuncCode", gQueueSent[TxID].FuncCode); + 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 - } + 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; + // 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; - EthSetTokenInt(gPacket, "modbus", "TxId", TxID); - EthSetTokenInt(gPacket, "modbus", "FuncCode", gQueuePending[TxID].FuncCode); - // 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(); - } - } + EthSetTokenInt(gPacket, "modbus", "TxId", TxID); + EthSetTokenInt(gPacket, "modbus", "FuncCode", gQueuePending[TxID].FuncCode); + // 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(); - } + if (gSocketState == ERROR || gQueueSent.Size() == 0 && gQueuePending.Size() == 0) // Stop timer to reduce latency of first packet + { + writeDbg(ConnDebug, "Stopping Timer gtRobin"); + this.Cancel(); + } } \ No newline at end of file diff --git a/Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin_0.brp b/Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin_0.brp deleted file mode 100644 index b52731a..0000000 --- a/Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin_0.brp +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Modbus-DLL/include/CAPL/include/ModbusEilClientCommon.cin b/Modbus-DLL/include/CAPL/include/ModbusEilClientCommon.cin index 06c6ae3..8ae4960 100644 --- a/Modbus-DLL/include/CAPL/include/ModbusEilClientCommon.cin +++ b/Modbus-DLL/include/CAPL/include/ModbusEilClientCommon.cin @@ -2,63 +2,63 @@ includes { - #include "EilCommon.cin" - #include "ModbusClientCommon.cin" + #include "EilCommon.cin" + #include "ModbusClientCommon.cin" } void ModbusConnectTo(char Remote_IP[], word Remote_Port) { - EilConnectTo(Remote_IP, Remote_Port); + EilConnectTo(Remote_IP, Remote_Port); } void ModbusConnectTo(dword Remote_IP, word Remote_Port) { - EilConnectTo(Remote_IP, Remote_Port); + EilConnectTo(Remote_IP, Remote_Port); } byte ModbusSnd(byte buffer[], word length) { - return EilSnd(buffer, length); + return EilSnd(buffer, length); } void ModbusRecv() { - EilRecv(); + EilRecv(); } void ModbusDisconnect() { - EilDisconnect(); + EilDisconnect(); } long ModbusGetLastConnectionError(char string[]) { - return EilGetLastConnectionError(string); + return EilGetLastConnectionError(string); } void OnEthReceivePacket(long channel, long dir, long packet) { - byte buffer[gMaxPacketLength]; - long size; + byte buffer[gMaxPacketLength]; + long size; - if (dir == TX) - return; + 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, "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); - } + 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); + } } \ No newline at end of file diff --git a/Modbus-DLL/include/CAPL/include/ModbusEilDllClientCommon.cin b/Modbus-DLL/include/CAPL/include/ModbusEilDllClientCommon.cin index 7026153..5473b4f 100644 --- a/Modbus-DLL/include/CAPL/include/ModbusEilDllClientCommon.cin +++ b/Modbus-DLL/include/CAPL/include/ModbusEilDllClientCommon.cin @@ -2,60 +2,60 @@ includes { - #include "EilDllCommon.cin" - #include "ModbusClientCommon.cin" + #include "EilDllCommon.cin" + #include "ModbusClientCommon.cin" } void ModbusConnectTo(char Remote_IP[], word Remote_Port) { - EilConnectTo(Remote_IP, Remote_Port); + EilConnectTo(Remote_IP, Remote_Port); } void ModbusConnectTo(dword Remote_IP, word Remote_Port) { - EilConnectTo(Remote_IP, Remote_Port); + EilConnectTo(Remote_IP, Remote_Port); } byte ModbusSnd(byte buffer[], word length) { - return EilSnd(buffer, length); + return EilSnd(buffer, length); } void ModbusRecv() { - EilRecv(); + EilRecv(); } void ModbusDisconnect() { - EilDisconnect(); + EilDisconnect(); } long ModbusGetLastConnectionError(char string[]) { - return EilGetLastConnectionError(string); + return EilGetLastConnectionError(string); } void OnEthReceivePacket(long channel, long dir, long packet) { - if (dir == TX) - return; + 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, "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 - { - OnModbusReceive2(packet); - } + if (EthGetTokenInt(packet, "ipv4", "protocol") == 0x11 && EthGetTokenInt(packet, "ipv4", "source") == gRemoteIP) // if this is a UDP package from our server + { + OnModbusReceive2(packet); + } } \ No newline at end of file diff --git a/Modbus-DLL/include/CAPL/include/ModbusFunctions.cin b/Modbus-DLL/include/CAPL/include/ModbusFunctions.cin index 853a724..dc3258a 100644 --- a/Modbus-DLL/include/CAPL/include/ModbusFunctions.cin +++ b/Modbus-DLL/include/CAPL/include/ModbusFunctions.cin @@ -1,86 +1,86 @@ /*@!Encoding:1252*/ variables { - enum Vendor - { - BuR = 2, - Wago = 23 - }; + enum Vendor + { + BuR = 2, + Wago = 23 + }; - struct deviceIOs - { - byte InputRegisters; - word InputBits; - byte OutputRegisters; - word OutputBits; - char Modules[1024]; - }; + 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]; + byte input; + byte numChannels; + char module[10]; - switch(vendor) - { - case Wago: // if this is a Wago device + switch(vendor) + { + case Wago: // if this is a Wago device - if (dev & 0x8000) // Digital Module - { - numChannels = (dev >> 8) & 0x007F; + 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; - } + 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)); + snprintf(module, elCount(module), module, numChannels); + strncat(dios.Modules, module, elCount(dios.Modules)); } \ No newline at end of file diff --git a/Modbus-DLL/include/CAPL/include/ModbusStructs.cin b/Modbus-DLL/include/CAPL/include/ModbusStructs.cin index 1d8224a..1917715 100644 --- a/Modbus-DLL/include/CAPL/include/ModbusStructs.cin +++ b/Modbus-DLL/include/CAPL/include/ModbusStructs.cin @@ -1,135 +1,135 @@ /*@!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 - { - word Address; - word Count; - }; - // Write a single value to a bit/register - _align(1) struct ModbusReqWriteSingle - { - word Address; - word Value; - }; - // Write several values to a bit/register starting with Address - _align(1) struct ModbusReqWriteBits - { - 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 - { - 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 - { - word Address; - word And; - word Or; - }; - // Read and write multiple registers - _align(1) struct ModbusReqReadWriteRegisters - { - 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 - { - byte ByteCount; - byte Data[250]; // Max length: 2000 bits - }; - // Receive several register values - _align(1) struct ModbusResReceiveRegisters - { - byte ByteCount; - word Data[125]; // Max length: 125 registers - }; - // Confirm the write of a single bit/register - _align(1) struct ModbusResConfirmSingle - { - word Address; - word Value; - }; - // Confirm the write of several bits/registers - _align(1) struct ModbusResConfirmMultiple - { - word Address; - word Count; - }; - // Confirm the write of AND and OR mask - _align(1) struct ModbusResConfirmMasks - { - word Address; - word And; - word Or; - }; - - - - enum ModbusRequestError - { - Exception, - Timeout, - FinalTimeout + // 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 + { + word Address; + word Count; + }; + // Write a single value to a bit/register + _align(1) struct ModbusReqWriteSingle + { + word Address; + word Value; + }; + // Write several values to a bit/register starting with Address + _align(1) struct ModbusReqWriteBits + { + 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 + { + 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 + { + word Address; + word And; + word Or; + }; + // Read and write multiple registers + _align(1) struct ModbusReqReadWriteRegisters + { + word ReadAddress; + word ReadCount; + word WriteAddress; + word WriteCount; + byte ByteCount; + word Data[121]; // Max length: 123-2 registers }; - 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 - }; + // Receive several bit values + _align(1) struct ModbusResReceiveBits + { + byte ByteCount; + byte Data[250]; // Max length: 2000 bits + }; + // Receive several register values + _align(1) struct ModbusResReceiveRegisters + { + byte ByteCount; + word Data[125]; // Max length: 125 registers + }; + // Confirm the write of a single bit/register + _align(1) struct ModbusResConfirmSingle + { + word Address; + word Value; + }; + // Confirm the write of several bits/registers + _align(1) struct ModbusResConfirmMultiple + { + word Address; + word Count; + }; + // Confirm the write of AND and OR mask + _align(1) struct ModbusResConfirmMasks + { + 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 + }; } \ No newline at end of file diff --git a/Modbus-DLL/include/CAPL/include/TcpUdpCommon.cin b/Modbus-DLL/include/CAPL/include/TcpUdpCommon.cin index be3029a..4cafe92 100644 --- a/Modbus-DLL/include/CAPL/include/TcpUdpCommon.cin +++ b/Modbus-DLL/include/CAPL/include/TcpUdpCommon.cin @@ -2,19 +2,19 @@ variables { - const long WSA_IO_PENDING = 997; - const long WSAEWOULDBLOCK = 10035; - const dword INVALID_IP = 0xffffffff; - - long gIpLastErr = 0; - char gIpLastErrStr[512] = ""; + 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; + enum SocketState { NULL, OK, ERROR, CLOSED }; + enum SocketState gSocketState = NULL; - dword gRemoteIP = INVALID_IP; - word gRemotePort = 0; + dword gRemoteIP = INVALID_IP; + word gRemotePort = 0; - byte gRxBuffer[8192]; + byte gRxBuffer[8192]; }