Prefixed "private" functions with underscore

This commit is contained in:
Jonny007-MKD 2014-07-04 10:59:58 +00:00
parent bf03b46d34
commit b6f211d5d3
6 changed files with 230 additions and 173 deletions

View file

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

View file

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

View file

@ -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 -------------------------------------------------------------
/// <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);
}
/// <ModbusReadBits>
// 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);
}
/// <ModbusReadBits>
// 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);
}
/// <ModbusReadBits>
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)
}
/// <ModbusReadBits>
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[])
}
/// <ModbusReadBits>
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 -------------------------------------------------------
/// <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);
}
/// <ModbusReadRegisters>
// 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);
}
/// <ModbusReadRegisters>
// 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);
}
/// <ModbusReadRegisters>
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)
}
/// <ModbusReadRegisters>
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[])
}
/// <ModbusReadRegisters>
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 -------------------------------------------------------------
/// <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);
}
/// <ModbusWriteBit>
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[])
}
/// <ModbusWriteBit>
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 ------------------------------------------------------
/// <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);
}
/// <ModbusWriteRegister>
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[])
}
/// <ModbusWriteRegister>
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 ----------------------------------------------------------
/// <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[])
}
/// <ModbusWriteBits>
// 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[])
}
/// <ModbusWriteBits>
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[])
}
/// <ModbusWriteBits>
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 -------------------------------------------------------
/// <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);
}
}
/// <ModbusWriteRegisters>
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[])
}
/// <ModbusWriteRegisters>
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 ------------------------------------------------------------
/// <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);
}
/// <ModbusWriteMasks>
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[])
}
/// <ModbusWriteMasks>
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 -------------------------------------------------------
/// <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);
}
/// <ModbusReadWriteRegisters>
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[])
}
/// <ModbusReadWriteRegisters>
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();

View file

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

View file

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

View file

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