modbus_tcp_custom
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
— | modbus_tcp_custom [2019/01/09 12:23] (current) – created emozolyak | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== An example of custom protocol for ModBus TCP ====== | ||
+ | ***Type**: TCP | ||
+ | ***Default TCP port**: 502 | ||
+ | ***Address validation**: | ||
+ | |||
+ | Code: | ||
+ | |||
+ | <code lua> | ||
+ | -- MODBUS TCP Demo Driver | ||
+ | |||
+ | function createDevices () | ||
+ | addDevice({name = " | ||
+ | addDevice({name = " | ||
+ | addDevice({name = " | ||
+ | addDevice({name = " | ||
+ | end | ||
+ | |||
+ | local transId = 0; | ||
+ | local errorCount = 0; | ||
+ | |||
+ | function readRegister (reg, device, unitId) | ||
+ | |||
+ | local request = {}; | ||
+ | |||
+ | -- transaction ID | ||
+ | transId = transId + 1; | ||
+ | |||
+ | request[1] = bit.band(bit.rshift(transId, | ||
+ | request[2] = bit.band(transId, | ||
+ | |||
+ | -- protocol ID | ||
+ | request[3] = 0; | ||
+ | request[4] = 0; | ||
+ | |||
+ | -- message length | ||
+ | request[5] = 0; | ||
+ | request[6] = 6; | ||
+ | |||
+ | -- unit ID | ||
+ | request[7] = unitId; | ||
+ | |||
+ | -- function code | ||
+ | request[8] = device.xtraFields[1]; | ||
+ | |||
+ | -- address of register | ||
+ | request[9] = bit.band(bit.rshift(reg.internalAddr, | ||
+ | request[10] = bit.band(reg.internalAddr, | ||
+ | |||
+ | -- count of registers | ||
+ | request[11] = 0; | ||
+ | request[12] = 1; | ||
+ | |||
+ | if (reg.dataType == 3) then -- double word | ||
+ | request[12] = 2; | ||
+ | end | ||
+ | |||
+ | local res = sendBytes(request); | ||
+ | |||
+ | if (res == false) then | ||
+ | DEBUG(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | |||
+ | |||
+ | local response = {}; | ||
+ | -- read MBAP Header | ||
+ | response = readBytes(7); | ||
+ | if (response == false) then | ||
+ | DEBUG(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | res = #response; | ||
+ | if (res ~= 7) then | ||
+ | errorCount = errorCount + 1; | ||
+ | if (errorCount > 3) then | ||
+ | closeConnection(); | ||
+ | errorCount = 0; | ||
+ | end | ||
+ | DEBUG(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | if (response[1] ~= request[1] or response[2] ~= request[2]) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | if (response[3] ~= request[3] or response[4] ~= request[4]) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | if (response[7] ~= request[7]) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | local length = response[5] * 256 + response[6]; | ||
+ | |||
+ | if (length < 1) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | local responsePDU = {}; | ||
+ | -- read MBAP Header | ||
+ | |||
+ | responsePDU = readBytes(length - 1); | ||
+ | if (responsePDU == false) then | ||
+ | DEBUG(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | res = # | ||
+ | |||
+ | if (responsePDU[1] ~= request[8]) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | local dataLength = responsePDU[2]; | ||
+ | if (dataLength ~= length - 3) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | local result = {}; | ||
+ | |||
+ | if (dataLength >= 1) then | ||
+ | for i = 1, dataLength do | ||
+ | result[i] = responsePDU[2 + i]; | ||
+ | end | ||
+ | end | ||
+ | |||
+ | return result; | ||
+ | end | ||
+ | |||
+ | function writeRegister (reg, device, unitId, newValue) | ||
+ | local request = {}; | ||
+ | |||
+ | transId = transId + 1; | ||
+ | -- transaction ID | ||
+ | request[1] = bit.band(bit.rshift(transId, | ||
+ | request[2] = bit.band(transId, | ||
+ | |||
+ | -- protocol ID | ||
+ | request[3] = 0; | ||
+ | request[4] = 0; | ||
+ | |||
+ | if (reg.dataType == 3) then -- double word | ||
+ | -- message length | ||
+ | request[5] = 0; | ||
+ | request[6] = 11; | ||
+ | |||
+ | -- unit ID | ||
+ | request[7] = unitId; | ||
+ | |||
+ | -- function code | ||
+ | request[8] = device.xtraFields[3]; | ||
+ | |||
+ | -- address of register | ||
+ | request[9] = bit.band(bit.rshift(reg.internalAddr, | ||
+ | request[10] = bit.band(reg.internalAddr, | ||
+ | |||
+ | -- count of registers | ||
+ | request[11] = 0; | ||
+ | request[12] = 2; | ||
+ | |||
+ | -- bytes with data | ||
+ | request[13] = 4; | ||
+ | |||
+ | -- value of registers | ||
+ | request[14] = bit.band(bit.rshift(newValue, | ||
+ | request[15] = bit.band(bit.rshift(newValue, | ||
+ | request[16] = bit.band(bit.rshift(newValue, | ||
+ | request[17] = bit.band(newValue, | ||
+ | |||
+ | local res = sendBytes(request); | ||
+ | |||
+ | if (res == false) then | ||
+ | DEBUG(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | local response = {}; | ||
+ | |||
+ | response = readBytes(7); | ||
+ | if (response == false) then | ||
+ | DEBUG(" | ||
+ | return false; | ||
+ | end | ||
+ | res = #response; | ||
+ | |||
+ | if (res ~= 7) then | ||
+ | DEBUG(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | if (response[1] ~= request[1] or response[2] ~= request[2]) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | if (response[3] ~= request[3] or response[4] ~= request[4]) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | if (response[7] ~= request[7]) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | local length = response[5] * 256 + response[6]; | ||
+ | |||
+ | if (length < 1) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | local responsePDU = {}; | ||
+ | |||
+ | responsePDU = readBytes(length - 1); | ||
+ | if (responsePDU == false) then | ||
+ | DEBUG(" | ||
+ | return false; | ||
+ | end | ||
+ | res = # | ||
+ | |||
+ | if (responsePDU[1] ~= request[8]) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | if (responsePDU[2] ~= request[9] or responsePDU[3] ~= request[10]) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | if (responsePDU[4] ~= 0 or responsePDU[5] ~= 2) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | else | ||
+ | if (device.xtraFields[2] == 0) then | ||
+ | ERROR(" | ||
+ | return false; | ||
+ | end | ||
+ | -- message length | ||
+ | request[5] = 0; | ||
+ | request[6] = 6; | ||
+ | |||
+ | -- unit ID | ||
+ | request[7] = unitId; | ||
+ | request[8] = device.xtraFields[2]; | ||
+ | |||
+ | -- address of register | ||
+ | request[9] = bit.band(bit.rshift(reg.internalAddr, | ||
+ | request[10] = bit.band(reg.internalAddr, | ||
+ | |||
+ | local val = newValue; | ||
+ | if (reg.dataType == 0) then | ||
+ | if (val > 0) then | ||
+ | val = 255*256; | ||
+ | else | ||
+ | val = 0; | ||
+ | end | ||
+ | end | ||
+ | |||
+ | -- value of registers | ||
+ | request[11] = bit.band(bit.rshift(val, | ||
+ | request[12] = bit.band(val, | ||
+ | |||
+ | |||
+ | local res = sendBytes(request); | ||
+ | |||
+ | if (res == false) then | ||
+ | DEBUG(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | local response = {}; | ||
+ | local requestLen = #request; | ||
+ | |||
+ | response = readBytes(requestLen); | ||
+ | if (response == false) then | ||
+ | DEBUG(" | ||
+ | return false; | ||
+ | end | ||
+ | res = #response; | ||
+ | if (res ~= requestLen) then | ||
+ | DEBUG(" | ||
+ | return false; | ||
+ | end | ||
+ | |||
+ | for i = 1,res do | ||
+ | if (response[i] ~= request[i]) then | ||
+ | DEBUG(" | ||
+ | return false; | ||
+ | end | ||
+ | end | ||
+ | |||
+ | end | ||
+ | |||
+ | return true; | ||
+ | end | ||
+ | </ |
modbus_tcp_custom.txt · Last modified: 2019/01/09 12:23 by emozolyak