I will begin with a simple way to receive a packet from a MODBUS TCP device:
arr = {} srv = net.createServer(net.TCP) srv:listen(502, function(conn) conn:on("receive", function(sck, payload) payload:gsub(".", function(c) table.insert(arr, string.byte(c)) end) print (table.concat(arr, " ")) end) end)
Output to the terminal will be as follows:
0 1 0 0 0 6 1 3 0 0 0 1 . . 0 30 0 0 0 6 1 3 0 0 0 1 0 31 0 0 0 6 1 3 0 0 0 1 0 32 0 0 0 6 1 3 0 0 0 1
In my case, the OPC server, which requests information from the device using the TCP protocol, sends it to the IP address specified in it for port 502. The code that receives it above is written to the array and then output to the terminal. You can do anything with an array.
How to transfer a packet to a MODBUS TCP device? Very simple:
arr = {0,1,0,0,0,6,1,3,0,0,0,1} srv = net.createServer(net.TCP) srv:listen(502, function(conn) conn:on("receive", function(sck, payload) buff = "" for i=1, #arr do line = string.char(arr[i]) buff = buff .. line end sck:send(buff) end) end)
In this case, the array is transmitted in response to a request from a MODBUS TCP device. Knowing the MODBUS protocol, you can form an array of the necessary variables depending on the query.
And lastly, the code that the received packet writes to the array sends it back:
arr = {} srv = net.createServer(net.TCP) srv:listen(502, function(conn) conn:on("receive", function(sck, payload) payload:gsub(".", function(c) table.insert(arr, string.byte(c)) end) local buff = "" for i=1, #arr do line = string.char(arr[i]) buff = buff .. line end sck:send(buff) buff = "" end) end)
This is certainly not correct, the MODBUS TCP device will swear at the wrong answer, but in the interval between reception and transmission you can modify the array and give the correct answer, I think that those who know the MODBUS protocol will be able to understand how to answer correctly. I just debugged the reception and transmission, the basic algorithm that works, then everyone will redo it to fit their needs. There is another point to which I draw your attention. It happens that a MODBUS TCP device can send a very long packet consisting of several without waiting for an answer to them, and then the array will instantly become very large and naturally the answer will be the same and wrong. I decided it is very simple, I check the size of the received packet, if it is equal to the required number of bytes, then after receiving the code, if not, then everything is skipped and the device waits for the following request:
if string.len(payload) == 12 then . . end
I do this check immediately after receiving the packet and if the packet is 12 bytes, the code is executed, if not, then the next request from the MODBUS TCP device is waited. This code can be altered under MODBUS RS485, the checksum can be calculated by the module from the MODEMCU firmware.
Here you can compile the firmware with the necessary modules.