From b6f211d5d31f5537b7b4e282a718e3f54190394f Mon Sep 17 00:00:00 2001 From: Jonny007-MKD Date: Fri, 4 Jul 2014 10:59:58 +0000 Subject: [PATCH] Prefixed "private" functions with underscore --- .../include/CAPL/PollingModbusClient.can | 2 +- .../CAPL/include/DeviceInformation.cin | 8 +- .../include/CAPL/include/ModbusClient.cin | 306 +++++++++++------- .../include/CAPL/include/ModbusEil.cin | 30 +- .../include/CAPL/include/ModbusTcp.cin | 31 +- .../include/CAPL/include/ModbusUdp.cin | 26 +- 6 files changed, 230 insertions(+), 173 deletions(-) diff --git a/Modbus-CAPL/include/CAPL/PollingModbusClient.can b/Modbus-CAPL/include/CAPL/PollingModbusClient.can index 6d2be1d..067c373 100644 --- a/Modbus-CAPL/include/CAPL/PollingModbusClient.can +++ b/Modbus-CAPL/include/CAPL/PollingModbusClient.can @@ -31,7 +31,7 @@ on start 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); // Connect to device. Opens socket and connection or what ever + ModbusInit(ip, @sysvar::Config::Modbus::Port); // Connect to device. Opens socket and connection or what ever ModbusReadOutBits(gDevOutputBitAddrR, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits); // Read the start status of the output bits ModbusReadOutRegisters(gDevOutputRegAddrR, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters); // Read the start status of the output registers diff --git a/Modbus-CAPL/include/CAPL/include/DeviceInformation.cin b/Modbus-CAPL/include/CAPL/include/DeviceInformation.cin index be920c7..66bc414 100644 --- a/Modbus-CAPL/include/CAPL/include/DeviceInformation.cin +++ b/Modbus-CAPL/include/CAPL/include/DeviceInformation.cin @@ -86,7 +86,7 @@ void DeviceInit(byte vendor) // This function parses the received device code/module code received from the device and writes it to struct deviceIO.Modules. // The quantity of IO does not have to be parsed here because it is extracted from extra registers /// -void DeviceParseCode(word dev, enum Vendor vendor, struct deviceIOs dios) +void _DeviceParseCode(word dev, enum Vendor vendor, struct deviceIOs dios) { byte input; byte numChannels; @@ -207,7 +207,7 @@ void DeviceParseCode(word dev, enum Vendor vendor, struct deviceIOs dios) // Requested information has to be: Count of AOs, AIs, DOs, DIs // Additionaly information can be: Serial Code, Device/Product Code, Codes of connected modules /// -byte DeviceGetInformation(enum Vendor vendor) +byte _DeviceGetInformation(enum Vendor vendor) { switch (vendor) { @@ -240,7 +240,7 @@ byte DeviceGetInformation(enum Vendor vendor) // This function parses the received registers (requested by DeviceGetInformation()) // It is called in the callback OnModbusReadRegistersSuccess() to fill the 'device' structure /// -void DeviceParseRegister(struct device device, word address, word data[], word count) +void _DeviceParseRegister(struct device device, word address, word data[], word count) { byte i; @@ -276,7 +276,7 @@ void DeviceParseRegister(struct device device, word address, word data[], word c { if (data[i] == 0x0000) // No more devices --> end break; - DeviceParseCode(data[i], device.Vendor, device.DeviceIOs); + _DeviceParseCode(data[i], device.Vendor, device.DeviceIOs); } break; } diff --git a/Modbus-CAPL/include/CAPL/include/ModbusClient.cin b/Modbus-CAPL/include/CAPL/include/ModbusClient.cin index d5b11fb..d2f175f 100644 --- a/Modbus-CAPL/include/CAPL/include/ModbusClient.cin +++ b/Modbus-CAPL/include/CAPL/include/ModbusClient.cin @@ -76,12 +76,12 @@ variables // It has to be called by the user/modbus client at the beginning with IP and Port of the Modbus server void ModbusInit(char Remote_IP[], word remotePort) { - ModbusConnectTo(ip, @sysvar::Config::Modbus::Port); + _ModbusConnectTo(Remote_IP, remotePort); } // This method fills the ModbusApHeader structure 'mbap'. // It gets called by the Modbus request methods -void ModbusMakeHeader(struct ModbusApHeader mbap, word length, byte funcCode) +void _ModbusMakeHeader(struct ModbusApHeader mbap, word length, byte funcCode) { mbap.TxID = gTxID++; // [2] Transaction ID mbap.Protocol = 0x0000; // [2] Protocol ID = 0 = Modbus @@ -94,23 +94,26 @@ void ModbusMakeHeader(struct ModbusApHeader mbap, word length, byte funcCode) // REGION: ModbusReadBits ------------------------------------------------------------- /// -// This method will submit a request to the Modbus server to read +// This method will submit a request to the Modbus server to read discrete inputs void ModbusReadInBits(word address, long count) { - ModbusReadBits(0x02, address, count); + _ModbusReadBits(0x02, address, count); } /// +// This method will submit a request to the Modbus server to read coils void ModbusReadBits(word address, long count) { - ModbusReadBits(0x02, address, count); + _ModbusReadBits(0x02, address, count); } /// +// This method will submit a request to the Modbus server to read coils void ModbusReadOutBits(word address, long count) { - ModbusReadBits(0x01, address, count); + _ModbusReadBits(0x01, address, count); } /// -void ModbusReadBits(byte funcCode, word address, long count) +// This method will submit a request to the Modbus server to read discrete inputs or coils +void _ModbusReadBits(byte funcCode, word address, long count) { const byte length = __size_of(struct ModbusReqRead); byte buffer[length]; @@ -121,7 +124,7 @@ void ModbusReadBits(byte funcCode, word address, long count) while (count > 0) { curCount = count > gMaxBitsPerRead ? gMaxBitsPerRead : count; - 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 @@ -129,7 +132,7 @@ void ModbusReadBits(byte funcCode, word address, long count) 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); + _ModbusSend(buffer, length, mbreq.Header.TxID); count -= gMaxBitsPerRead; address += gMaxBitsPerRead; @@ -137,7 +140,8 @@ void ModbusReadBits(byte funcCode, word address, long count) } /// -void OnModbusReceiveBits(byte buffer[]) +// This method will be called by _OnModbusReceive2OnePacket() when receiving data +void _OnModbusReceiveBits(byte buffer[]) { struct ModbusResReceiveBits mbres; struct ModbusReqRead mbreq; @@ -161,7 +165,8 @@ void OnModbusReceiveBits(byte buffer[]) } /// -void OnModbusReceiveBitsException(struct ModbusApHeader mbap, enum ModbusException ex) +// 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); @@ -173,22 +178,26 @@ void OnModbusReceiveBitsException(struct ModbusApHeader mbap, enum ModbusExcepti // REGION: ModbusReadRegisters ------------------------------------------------------- /// +// This method will submit a request to the Modbus server to read input registers void ModbusReadInRegisters(word address, long count) { - ModbusReadRegisters(0x04, address, count); + _ModbusReadRegisters(0x04, address, count); } /// +// This method will submit a request to the Modbus server to read holding registers void ModbusReadRegisters(word address, long count) { - ModbusReadRegisters(0x04, address, count); + _ModbusReadRegisters(0x04, address, count); } /// +// This method will submit a request to the Modbus server to read holding registers void ModbusReadOutRegisters(word address, long count) { - ModbusReadRegisters(0x03, address, count); + _ModbusReadRegisters(0x03, address, count); } /// -void ModbusReadRegisters(byte funcCode, word address, long count) +// This method will submit a request to the Modbus server to read input or holding registers +void _ModbusReadRegisters(byte funcCode, word address, long count) { const byte length = __size_of(struct ModbusReqRead); byte buffer[length]; @@ -199,7 +208,7 @@ void ModbusReadRegisters(byte funcCode, word address, long count) while (count > 0) { curCount = count > gMaxRegsPerRead ? gMaxRegsPerRead : count; - 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 @@ -207,7 +216,7 @@ void ModbusReadRegisters(byte funcCode, word address, long count) 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); + _ModbusSend(buffer, length, mbreq.Header.TxID); count -= gMaxRegsPerRead; address += gMaxRegsPerRead; @@ -215,7 +224,8 @@ void ModbusReadRegisters(byte funcCode, word address, long count) } /// -void OnModbusReceiveRegisters(byte buffer[]) +// This method will be called by _OnModbusReceive2OnePacket() when receiving data +void _OnModbusReceiveRegisters(byte buffer[]) { struct ModbusResReceiveRegisters mbres; struct ModbusReqRead mbreq; @@ -229,7 +239,8 @@ void OnModbusReceiveRegisters(byte buffer[]) } /// -void OnModbusReceiveRegistersException(struct ModbusApHeader mbap, enum ModbusException ex) +// 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); @@ -241,6 +252,7 @@ void OnModbusReceiveRegistersException(struct ModbusApHeader mbap, enum ModbusEx // REGION: ModbusWriteBit ------------------------------------------------------------- /// +// 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); @@ -252,7 +264,7 @@ void ModbusWriteBit(word address, byte value) value = 0xFF; // FC5: Write Single Coil (DO) - ModbusMakeHeader(mbreq.Header, length, funcCode); + _ModbusMakeHeader(mbreq.Header, length, funcCode); mbreq.Address = address; // [2] Output address mbreq.Value = value << 8; // [2] Output value (0x0000: Off, 0xFF00: On) @@ -260,11 +272,12 @@ void ModbusWriteBit(word address, byte value) 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); + _ModbusSend(buffer, length, mbreq.Header.TxID); } /// -void OnModbusConfirmBit(byte buffer[]) +// This method will be called by _OnModbusReceive2OnePacket() when confirming the request +void _OnModbusConfirmBit(byte buffer[]) { struct ModbusResConfirmSingle mbc; @@ -276,7 +289,8 @@ void OnModbusConfirmBit(byte buffer[]) } /// -void OnModbusConfirmBitException(struct ModbusApHeader mbap, enum ModbusException ex) +// 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); @@ -286,8 +300,10 @@ void OnModbusConfirmBitException(struct ModbusApHeader mbap, enum ModbusExceptio + // REGION: ModbusWriteRegister ------------------------------------------------------ /// +// 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); @@ -296,7 +312,7 @@ void ModbusWriteRegister(word address, word value) struct ModbusReqWriteSingle mbreq; // 5: Write Single Register (AO) - ModbusMakeHeader(mbreq.Header, length, funcCode); + _ModbusMakeHeader(mbreq.Header, length, funcCode); mbreq.Address = address; // [2] Output address mbreq.Value = value; // [2] Output value @@ -304,11 +320,12 @@ void ModbusWriteRegister(word address, word 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); + _ModbusSend(buffer, length, mbreq.Header.TxID); } /// -void OnModbusConfirmRegister(byte buffer[]) +// This method will be called by _OnModbusReceive2OnePacket() when confirming the request +void _OnModbusConfirmRegister(byte buffer[]) { struct ModbusResConfirmSingle mbc; @@ -320,7 +337,8 @@ void OnModbusConfirmRegister(byte buffer[]) } /// -void OnModbusConfirmRegisterException(struct ModbusApHeader mbap, enum ModbusException ex) +// 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); @@ -334,6 +352,8 @@ void OnModbusConfirmRegisterException(struct ModbusApHeader mbap, enum ModbusExc // REGION: ModbusWriteBits ---------------------------------------------------------- /// +// This method will submit a request to the Modbus server to set several coils +// It will not encode the 'values' void ModbusWriteBits(word address, long count, byte values[]) { const word maxLength = __size_of(struct ModbusReqWriteBits); @@ -360,7 +380,7 @@ void ModbusWriteBits(word address, long count, byte values[]) dataLength = _ceil(curCount / 8.0); overallLength = maxLength - gMaxBitsPerWrite/8 + dataLength; } - ModbusMakeHeader(mbreq.Header, overallLength, funcCode); + _ModbusMakeHeader(mbreq.Header, overallLength, funcCode); mbreq.Address = address; // [2] Output address mbreq.Count = curCount; // [2] Number of items; 1:max 1968=0x7B0 @@ -370,7 +390,7 @@ void ModbusWriteBits(word address, long count, byte values[]) writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. Addr: 0x%04X, Count: %d", address, curCount); memcpy_h2n(buffer, mbreq); - ModbusSend(buffer, overallLength, mbreq.Header.TxID); + _ModbusSend(buffer, overallLength, mbreq.Header.TxID); count -= gMaxBitsPerWrite; address += gMaxBitsPerWrite; @@ -378,6 +398,9 @@ void ModbusWriteBits(word address, long count, byte values[]) } /// +// This method will submit a request to the Modbus server to set several coils +// It additionally encodes the bit 'values' to bytes. This means that 8 bytes of 'values' are stacked into one byte. +// Use this when you simply have 1s and 0s void ModbusWriteBitsB(word address, long count, byte values[]) { byte buffer[gMaxBitsPerWrite/8]; // length @@ -417,7 +440,8 @@ void ModbusWriteBitsB(word address, long count, byte values[]) } /// -void OnModbusConfirmBits(byte buffer[]) +// This method will be called by _OnModbusReceive2OnePacket() when confirming the request +void _OnModbusConfirmBits(byte buffer[]) { struct ModbusResConfirmMultiple mbc; @@ -429,7 +453,8 @@ void OnModbusConfirmBits(byte buffer[]) } /// -void OnModbusConfirmBitsException(struct ModbusApHeader mbap, enum ModbusException ex) +// 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); @@ -442,6 +467,7 @@ void OnModbusConfirmBitsException(struct ModbusApHeader mbap, enum ModbusExcepti // REGION: ModbusWriteRegisters ------------------------------------------------------- /// +// 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); @@ -460,7 +486,7 @@ void ModbusWriteRegisters(word address, long count, word values[]) dataLength = 2 * curCount; overallLength = maxLength - 2*gMaxRegsPerWrite + dataLength; - ModbusMakeHeader(mbreq.Header, overallLength, funcCode); + _ModbusMakeHeader(mbreq.Header, overallLength, funcCode); mbreq.Address = address; // [2] Output address mbreq.Count = curCount; // [2] Number of items; 1:max 123=0x7B @@ -472,12 +498,13 @@ void ModbusWriteRegisters(word address, long count, word values[]) mbreq.Data[i] = 0; memcpy_h2n(buffer, mbreq); - ModbusSend(buffer, overallLength, mbreq.Header.TxID); + _ModbusSend(buffer, overallLength, mbreq.Header.TxID); } } /// -void OnModbusConfirmRegisters(byte buffer[]) +// This method will be called by _OnModbusReceive2OnePacket() when confirming the request +void _OnModbusConfirmRegisters(byte buffer[]) { struct ModbusResConfirmMultiple mbc; @@ -489,7 +516,8 @@ void OnModbusConfirmRegisters(byte buffer[]) } /// -void OnModbusConfirmRegistersException(struct ModbusApHeader mbap, enum ModbusException ex) +// 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); @@ -502,6 +530,7 @@ void OnModbusConfirmRegistersException(struct ModbusApHeader mbap, enum ModbusEx // REGION: ModbusWriteMasks ------------------------------------------------------------ /// +// This method will submit a request to the Modbus server to mask a holding registers void ModbusWriteMasks(word address, word and, word or) { const word length = __size_of(struct ModbusReqWriteMasks); @@ -510,18 +539,19 @@ void ModbusWriteMasks(word address, word and, word or) struct ModbusReqWriteMasks mbreq; // FC22: Mask Write Registers (AO) - ModbusMakeHeader(mbreq.Header, length, funcCode); + _ModbusMakeHeader(mbreq.Header, length, funcCode); 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); + _ModbusSend(buffer, length, mbreq.Header.TxID); } /// -void OnModbusConfirmMasks(byte buffer[]) +// This method will be called by _OnModbusReceive2OnePacket() when confirming the request +void _OnModbusConfirmMasks(byte buffer[]) { struct ModbusResConfirmMasks mbc; @@ -533,7 +563,8 @@ void OnModbusConfirmMasks(byte buffer[]) } /// -void OnModbusConfirmMasksException(struct ModbusApHeader mbap, enum ModbusException ex) +// 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); @@ -545,6 +576,7 @@ void OnModbusConfirmMasksException(struct ModbusApHeader mbap, enum ModbusExcept // REGION: ModbusReadWriteRegisters ------------------------------------------------------- /// +// 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); @@ -574,7 +606,7 @@ void ModbusReadWriteRegisters(word readAddress, long readCount, word writeAddres overallLength = maxLength - 2*(gMaxRegsPerWrite-2) + dataLength; // FC16: Write Multiple Registers (AOs) - ModbusMakeHeader(mbreq.Header, overallLength, funcCode); + _ModbusMakeHeader(mbreq.Header, overallLength, funcCode); mbreq.ReadAddress = readAddress; // [2] Input address mbreq.ReadCount = readCount; // [2] Number of items; 1:max 125=0x7D @@ -586,11 +618,12 @@ void ModbusReadWriteRegisters(word readAddress, long readCount, word writeAddres mbreq.Data[i] = values[i + offset]; memcpy_h2n(buffer, mbreq); - ModbusSend(buffer, overallLength, mbreq.Header.TxID); + _ModbusSend(buffer, overallLength, mbreq.Header.TxID); } /// -void OnModbusReceiveConfirmRegisters(byte buffer[]) +// This method will be called by _OnModbusReceive2OnePacket() when confirming the request +void _OnModbusReceiveConfirmRegisters(byte buffer[]) { struct ModbusResReceiveRegisters mbres; struct ModbusReqRead mbreq; @@ -604,7 +637,8 @@ void OnModbusReceiveConfirmRegisters(byte buffer[]) } /// -void OnModbusReceiveConfirmRegistersException(struct ModbusApHeader mbap, enum ModbusException ex) +// 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); @@ -619,7 +653,9 @@ void OnModbusReceiveConfirmRegistersException(struct ModbusApHeader mbap, enum M // ------------------------------------------------------------------------------------ // REGION: OnModbusReceive ------------------------------------------------------------ /// <-OnModbusReceive> -void OnModbusReceive(dword socket, long result, dword address, dword port, byte buffer[], dword size) +// This method parses the received data. It checks for network errors +// 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) @@ -628,24 +664,26 @@ void OnModbusReceive(dword socket, long result, dword address, dword port, byte { // Size of zero indicates that the socket was closed by the communication peer. writeDbg(ConnWarning, "OnModbusReceive: Socket closed by peer"); - ModbusDisconnect(); + _ModbusDisconnect(); } else { // Sucessfully received some bytes over the TCP/IP connection. - OnModbusReceive2(buffer, size); + _OnModbusReceive2(buffer, size); } } else { - gIpLastErr = ModbusGetLastConnectionError(gIpLastErrStr); + gIpLastErr = _ModbusGetLastConnectionError(gIpLastErrStr); writeDbg(ConnError, "OnModbusReceive error (%d): %s", gIpLastErr, gIpLastErrStr); - ModbusDisconnect(); + _ModbusDisconnect(); } } /// <-OnModbusReceive> -void OnModbusReceive2(byte buffer[], dword size) +// This method continues with parsing the received data. It tries to separate several packets in the buffer +// It gets called by _OnModbusReceive() +void _OnModbusReceive2(byte buffer[], dword size) { struct ModbusApHeader mbap; long offset; @@ -659,7 +697,7 @@ void OnModbusReceive2(byte buffer[], dword size) { writeDbg(ConnDebug, "OnModbusReceive2: Offset pre = %d", offset); memcpy_n2h(mbap, buffer, offset); - OnModbusReceive2OnePacket(buffer, offset, mbap); + _OnModbusReceive2OnePacket(buffer, offset, mbap); offset += __offset_of(struct ModbusApHeader, UnitID) + mbap.Length; writeDbg(ConnDebug, "OnModbusReceive2: offset post = %d. %d <= %d?", offset, offset, size-8); @@ -676,13 +714,15 @@ void OnModbusReceive2(byte buffer[], dword size) } /// <-OnModbusReceive> -void OnModbusReceive2OnePacket(byte buffer[], int offset, struct ModbusApHeader mbap) +// This method continues with parsing the received packet. +// It checks whether it is a modbus packet and then hands it to _OnModbusReceive2Exceptions() or to the Success() function of the request +// It gets called by _OnModbusReceive2() +void _OnModbusReceive2OnePacket(byte buffer[], int offset, struct ModbusApHeader mbap) { // Test transaction identifier? // Test unit/device identifier? word i; // counter word length; // length of current packet - byte mbuffer[gModbusMaxTelegramSize]; // second buffer where we copy the message. This way the user won't overwrite other packages. length = __offset_of(struct ModbusApHeader, UnitID) + mbap.Length; // We cannot check this properly anymore. We have to trust the TCP/UDP stack and the sender... *sigh* @@ -708,95 +748,102 @@ void OnModbusReceive2OnePacket(byte buffer[], int offset, struct ModbusApHeader gQueueSent.Remove(mbap.TxID); if (mbap.FuncCode > 0x80) // Oh no, we got a exception! - { - OnModbusReceive2Exceptions(buffer[offset+08], mbap); - - gQueueAck.Remove(mbap.TxID); // Remove from acknowledge queue - - return; - } - - // Copy the message - memcpy_off(mbuffer, 0, buffer, offset, length); - - // Let's give the PDU to the corresponding function - switch (mbap.FuncCode) - { - case 0x01: - case 0x02: - OnModbusReceiveBits(mbuffer); - break; - case 0x03: - case 0x04: - OnModbusReceiveRegisters(mbuffer); - break; - case 0x05: - OnModbusConfirmBit(mbuffer); - break; - case 0x06: - OnModbusConfirmRegister(mbuffer); - break; - case 0x0F: - OnModbusConfirmBits(mbuffer); - break; - case 0x10: - OnModbusConfirmRegisters(mbuffer); - break; - case 0x16: - OnModbusConfirmMasks(mbuffer); - break; - case 0x17: - OnModbusReceiveConfirmRegisters(mbuffer); - break; - default: - writeDbg(MbError, "OnModbusReceive2OnePacket: We received funcCode 0x%X!?", mbap.FuncCode); - } + _OnModbusReceive2Exceptions(buffer[offset+08], mbap); + else // Ok, everything is alright + _OnModbusReceive2Success(buffer, mbap); gQueueAck.Remove(mbap.TxID); // Remove from acknowledge queue } /// <-OnModbusReceive> -void OnModbusReceive2Exceptions(byte exCode, struct ModbusApHeader mbap) +// This method will hand the exception code to the correct Exception() function +// It gets called by _OnModbusReceive2OnePacket() +void _OnModbusReceive2Exceptions(byte exCode, struct ModbusApHeader mbap) { enum ModbusException ex; ex = (enum ModbusException)exCode; switch (mbap.FuncCode) { - case 0x81: - case 0x82: - OnModbusReceiveBitsException(mbap, ex); + case 0x80+ReadBits1: + case 0x80+ReadBits2: + _OnModbusReceiveBitsException(mbap, ex); break; - case 0x83: - case 0x84: - OnModbusReceiveRegistersException(mbap, ex); + case 0x80+ReadRegisters1: + case 0x80+ReadRegisters2: + _OnModbusReceiveRegistersException(mbap, ex); break; - case 0x85: - OnModbusConfirmBitException(mbap, ex); + case 0x80+WriteBit: + _OnModbusConfirmBitException(mbap, ex); break; - case 0x86: - OnModbusConfirmRegisterException(mbap, ex); + case 0x80+WriteRegister: + _OnModbusConfirmRegisterException(mbap, ex); break; - case 0x8F: - OnModbusConfirmBitsException(mbap, ex); + case 0x80+WriteBits: + _OnModbusConfirmBitsException(mbap, ex); break; - case 0x90: - OnModbusConfirmRegistersException(mbap, ex); + case 0x80+WriteRegisters: + _OnModbusConfirmRegistersException(mbap, ex); break; - case 0x96: - OnModbusConfirmMasksException(mbap, ex); + case 0x80+MaskRegister: + _OnModbusConfirmMasksException(mbap, ex); break; - case 0x97: - OnModbusReceiveConfirmRegistersException(mbap, ex); + case 0x80+ReadWriteRegisters: + _OnModbusReceiveConfirmRegistersException(mbap, ex); break; } } +/// <-OnModbusReceive> +// This method will hand the received data to the correct Success() function +// It gets called by _OnModbusReceive2OnePacket() +void _OnModbusReceive2Success(byte exCode, struct ModbusApHeader mbap) +{ + 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 ReadBits1: + case ReadBits2: + _OnModbusReceiveBits(mbuffer); + break; + case ReadRegisters1: + case ReadRegisters2: + _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); + } +} + // ------------------------------------------------------------------------------------ // REGION: ModbusSend ----------------------------------------------------------------- /// <-ModbusSend> -void ModbusSend(byte buffer[], word length, word TxID) +// This method will enqueue the data in gQueuePending and start gtModbusRobin if appropriate +// It will get called by the Modbus request functions +void _ModbusSend(byte buffer[], word length, word TxID) { struct QueueElement qe; @@ -807,16 +854,22 @@ void ModbusSend(byte buffer[], word length, word TxID) 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(); + _ModbusStartQueue(); } -void ModbusStartQueue() +// This method will start the timer. Nothing special :) +// It is seperate because the network layer may want to start it when it delayed some messages (e.g. while waiting for an ARP response) +// It gets called by _ModbusSend() and OnEthReceivePacket() in ModbusEil.cin +void _ModbusStartQueue() { writeDbg(ConnDebug, "Starting Timer gtModbusRobin"); setTimerCyclic(gtModbusRobin, 1); } /// <-ModbusSend> +// This timer will handle the pending and sent queues. +// The sent packets will be checked for timeouts (.TimeoutTicks) and may be resent +// The pending packets may be sent when there is free space in the sending window on timer gtModbusRobin { struct ModbusApHeader mbap; @@ -834,9 +887,9 @@ on timer gtModbusRobin { writeDbg(ConnInfo, "Packet 0x%04X timed out! Retrying...", TxID); gQueueSent[TxID].TimeoutTicks = 0; - ModbusSnd(gQueueSent[TxID].Buffer, gQueueSent[TxID].Length); // resend it + _ModbusSnd(gQueueSent[TxID].Buffer, gQueueSent[TxID].Length); // resend it reqError = Timeout; - ModbusRecv(); + _ModbusRecv(); } else // we will NOT resend it { @@ -876,25 +929,28 @@ on timer gtModbusRobin } if (reqError == FinalTimeout) // remove the packet from queue - gQueueSent.Remove(TxID); // wait until here to let the methods access the request + 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() >= gDevReceiveWindow) // Device cannot handle many messages at a time - break; + if (gQueueSent.Size() >= gDevReceiveWindow) // 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 || gSocketState != NULL) + // what was that thing with the socket state? Somehow it was neccessary... + 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(); + _ModbusRecv(); // wait for new packets } } - if (gSocketState == ERROR || gQueueSent.Size() == 0 && gQueuePending.Size() == 0) // Stop timer to reduce latency of first packet + // Stop timer to reduce load and latency of first new packet + if (gSocketState == ERROR || gQueueSent.Size() == 0 && gQueuePending.Size() == 0) { writeDbg(ConnDebug, "Stopping Timer gtModbusRobin"); this.Cancel(); diff --git a/Modbus-CAPL/include/CAPL/include/ModbusEil.cin b/Modbus-CAPL/include/CAPL/include/ModbusEil.cin index 8da6b0a..2aac176 100644 --- a/Modbus-CAPL/include/CAPL/include/ModbusEil.cin +++ b/Modbus-CAPL/include/CAPL/include/ModbusEil.cin @@ -2,11 +2,11 @@ // 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 -/// - Some function that received packets +/// - _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 { @@ -27,7 +27,7 @@ variables // 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) +word _ModbusConnectTo(char Remote_IP[], word remotePort) { dword remoteIp; @@ -44,7 +44,7 @@ word ModbusConnectTo(char Remote_IP[], word 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) +word _ModbusConnectTo(dword remoteIp, word remotePort) { long error; byte broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; @@ -97,7 +97,7 @@ word ModbusConnectTo(dword remoteIp, word remotePort) } // 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() +void _ModbusConnectTo2() { gPacket = EthInitPacket("udp"); if (gPacket == 0) @@ -120,7 +120,7 @@ void ModbusConnectTo2() // This method will gracefully disconnect from the remote device. // Here: The method will invalidate the packet 'gPacket' -void ModbusDisconnect() +void _ModbusDisconnect() { if (gPacket != 0) { @@ -132,13 +132,13 @@ void ModbusDisconnect() // This method will wait for data from the remote device. // Here: Nothing has to be done, EthernetIL is waiting for packets all the time -void ModbusRecv() +void _ModbusRecv() { } // This method will send the payload 'buffer' to the device. // Here: It fills the packet 'gPacket' and sends it -byte ModbusSnd(byte buffer[], word length) +byte _ModbusSnd(byte buffer[], word length) { char str[20*3]; @@ -171,7 +171,7 @@ byte ModbusSnd(byte buffer[], word length) } // This Method simply combines the two EthGetLastError functions -long ModbusGetLastConnectionError(char string[]) +long _ModbusGetLastConnectionError(char string[]) { EthGetLastErrorText(elCount(string), string); return EthGetLastError(); @@ -200,8 +200,8 @@ void OnEthReceivePacket(long channel, long dir, long packet) { 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(); + _ModbusConnectTo2(); // create the UDP package + _ModbusStartQueue(); } return; } @@ -209,6 +209,6 @@ void OnEthReceivePacket(long channel, long dir, long packet) 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 + _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/ModbusTcp.cin b/Modbus-CAPL/include/CAPL/include/ModbusTcp.cin index 06859f3..e099d07 100644 --- a/Modbus-CAPL/include/CAPL/include/ModbusTcp.cin +++ b/Modbus-CAPL/include/CAPL/include/ModbusTcp.cin @@ -2,10 +2,11 @@ // This file connected 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 { @@ -19,7 +20,7 @@ variables } // This method opens an TCP socket. It has to check for several errors. -word TcpOpenSocket() +word _TcpOpenSocket() { byte i; char errorText[200]; @@ -51,7 +52,7 @@ word TcpOpenSocket() // 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) +word _ModbusConnectTo(char Remote_IP[], word remotePort) { dword remoteIp; @@ -64,12 +65,12 @@ word ModbusConnectTo(char Remote_IP[], word remotePort) 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) +word _ModbusConnectTo(dword remoteIp, word remotePort) { long fehler; @@ -109,7 +110,7 @@ word ModbusConnectTo(dword remoteIp, word remotePort) // 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) +void _OnTcpConnect(dword socket, long result) { if (result != 0) { @@ -129,7 +130,7 @@ void OnTcpConnect(dword socket, long result) // This method will gracefully disconnect from the remote device. // Here: Simply close the socket. This will also disconnect the remote device -void ModbusDisconnect() +void _ModbusDisconnect() { gSocket.Close(); gSocketState = CLOSED; @@ -137,7 +138,7 @@ void ModbusDisconnect() // 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() +void _ModbusRecv() { int result; @@ -167,14 +168,14 @@ void ModbusRecv() // This method will send the payload 'buffer' to the device. // Here: Call the appropriate API function -word ModbusSnd(byte buffer[], word length) +word _ModbusSnd(byte buffer[], word length) { char str[20*3]; switch (gSocketState) { case CLOSED: // If the connection is closed - ModbusConnectTo(gRemoteIP, gRemotePort); // Try to (re)connect + _ModbusConnectTo(gRemoteIP, gRemotePort); // Try to (re)connect if (gSocketState != OK) // If this didn't work { writeDbg(ConnError, "ModbusSnd: Reconnecting failed!"); @@ -209,7 +210,7 @@ word ModbusSnd(byte buffer[], word length) } // This method simply combines the two EthGetLastError functions -long ModbusGetLastConnectionError(char string[]) +long _ModbusGetLastConnectionError(char string[]) { gSocket.GetLastSocketErrorAsString(string, elCount(string)); return gSocket.GetLastSocketError(); @@ -218,5 +219,5 @@ long ModbusGetLastConnectionError(char string[]) // 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 6b3e82d..db40863 100644 --- a/Modbus-CAPL/include/CAPL/include/ModbusUdp.cin +++ b/Modbus-CAPL/include/CAPL/include/ModbusUdp.cin @@ -19,7 +19,7 @@ variables } // This method opens an UDP socket. It has to check for several errors. -word UdpOpenSocket() +word _UdpOpenSocket() { byte i; char errorText[200]; @@ -51,7 +51,7 @@ word UdpOpenSocket() // 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) +word _ModbusConnectTo(char Remote_IP[], word remotePort) { dword remoteIp; @@ -64,17 +64,17 @@ word ModbusConnectTo(char Remote_IP[], word remotePort) 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) +word _ModbusConnectTo(dword remoteIp, word remotePort) { long fehler; // Try to open a socket - fehler = UdpOpenSocket(); + fehler = _UdpOpenSocket(); if (fehler != 0) { gSocketState = ERROR; @@ -89,7 +89,7 @@ word ModbusConnectTo(dword remoteIp, word remotePort) // This method will gracefully disconnect from the remote device. // Here: Simply close the socket -void ModbusDisconnect() +void _ModbusDisconnect() { gSocket.Close(); gSocketState = CLOSED; @@ -97,7 +97,7 @@ void ModbusDisconnect() // 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() +void _ModbusRecv() { int result; @@ -118,7 +118,7 @@ void ModbusRecv() { gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elCount(gIpLastErrStr)); writeDbg(ConnError, "UdpReceiveFrom: (%d) %s", gIpLastErr, gIpLastErrStr); - ModbusDisconnect(); + _ModbusDisconnect(); } } @@ -127,14 +127,14 @@ void ModbusRecv() // This method will send the payload 'buffer' to the device. // Here: Call the appropriate API function -byte ModbusSnd(byte buffer[], word length) +byte _ModbusSnd(byte buffer[], word length) { char str[20*3]; switch (gSocketState) { case CLOSED: // If the connection is closed - ModbusConnectTo(gRemoteIP, gRemotePort); // Try to (re)connect + _ModbusConnectTo(gRemoteIP, gRemotePort); // Try to (re)connect if (gSocketState != OK) // If this didn't work { writeDbg(ConnError, "ModbusSnd: Reconnecting failed!"); @@ -160,7 +160,7 @@ byte ModbusSnd(byte buffer[], word length) { gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); writeDbg(ConnError, "ModbusSnd error (%d): %s", gIpLastErr, gIpLastErrStr); - ModbusDisconnect(); + _ModbusDisconnect(); return 1; } // else: tough luck! @@ -169,7 +169,7 @@ byte ModbusSnd(byte buffer[], word length) } // This method simply combines the two EthGetLastError functions -long ModbusGetLastConnectionError(char string[]) +long _ModbusGetLastConnectionError(char string[]) { gSocket.GetLastSocketErrorAsString(string, elCount(string)); return gSocket.GetLastSocketError(); @@ -178,5 +178,5 @@ long ModbusGetLastConnectionError(char string[]) // 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