#30 modbus comms changes

This commit is contained in:
Mikayla Fischler
2022-04-22 20:21:28 -04:00
parent 78a1073e2a
commit 912011bfed
2 changed files with 42 additions and 26 deletions

View File

@@ -88,7 +88,7 @@ function scada_packet()
-- public accessors -- -- public accessors --
local modem_event = function () return self.modem_msg_in end local modem_event = function () return self.modem_msg_in end
local raw = function () return self.raw end local raw_sendable = function () return self.raw end
local sender = function () return self.s_port end local sender = function () return self.s_port end
local receiver = function () return self.r_port end local receiver = function () return self.r_port end
@@ -106,7 +106,7 @@ function scada_packet()
receive = receive, receive = receive,
-- raw access -- raw access
modem_event = modem_event, modem_event = modem_event,
raw = raw, raw_sendable = raw_sendable,
-- sender/receiver -- sender/receiver
sender = sender, sender = sender,
receiver = receiver, receiver = receiver,
@@ -121,13 +121,12 @@ function scada_packet()
end end
-- MODBUS packet -- MODBUS packet
-- modeled after MODBUS TCP packet, but length is not transmitted since these are tables (#data = length, easy) -- modeled after MODBUS TCP packet
function modbus_packet() function modbus_packet()
local self = { local self = {
frame = nil, frame = nil,
raw = nil, raw = nil,
txn_id = txn_id, txn_id = txn_id,
protocol = protocol,
length = length, length = length,
unit_id = unit_id, unit_id = unit_id,
func_code = func_code, func_code = func_code,
@@ -135,16 +134,15 @@ function modbus_packet()
} }
-- make a MODBUS packet -- make a MODBUS packet
local make = function (txn_id, protocol, unit_id, func_code, data) local make = function (txn_id, unit_id, func_code, data)
self.txn_id = txn_id self.txn_id = txn_id
self.protocol = protocol
self.length = #data self.length = #data
self.unit_id = unit_id self.unit_id = unit_id
self.func_code = func_code self.func_code = func_code
self.data = data self.data = data
-- populate raw array -- populate raw array
self.raw = { self.txn_id, self.protocol, self.unit_id, self.func_code } self.raw = { self.txn_id, self.unit_id, self.func_code }
for i = 1, self.length do for i = 1, self.length do
table.insert(self.raw, data[i]) table.insert(self.raw, data[i])
end end
@@ -156,11 +154,11 @@ function modbus_packet()
self.frame = frame self.frame = frame
if frame.protocol() == PROTOCOLS.MODBUS_TCP then if frame.protocol() == PROTOCOLS.MODBUS_TCP then
local size_ok = frame.length() >= 4 local size_ok = frame.length() >= 3
if size_ok then if size_ok then
local data = frame.data() local data = frame.data()
make(data[1], data[2], data[3], data[4], { table.unpack(data, 5, #data) }) make(data[1], data[2], data[3], { table.unpack(data, 4, #data) })
end end
return size_ok return size_ok
@@ -182,7 +180,6 @@ function modbus_packet()
return { return {
scada_frame = self.frame, scada_frame = self.frame,
txn_id = self.txn_id, txn_id = self.txn_id,
protocol = self.protocol,
length = self.length, length = self.length,
unit_id = self.unit_id, unit_id = self.unit_id,
func_code = self.func_code, func_code = self.func_code,

View File

@@ -203,10 +203,10 @@ function new(rtu_dev)
return return_ok, response return return_ok, response
end end
-- handle a MODBUS TCP packet and generate a reply
local handle_packet = function (packet) local handle_packet = function (packet)
local return_code = true local return_code = true
local response = nil local response = nil
local reply = packet
if #packet.data == 2 then if #packet.data == 2 then
-- handle by function code -- handle by function code
@@ -236,32 +236,51 @@ function new(rtu_dev)
return_code = false return_code = false
end end
if return_code then
-- default is to echo back -- default is to echo back
if type(response) == "table" then local func_code = packet.func_code
reply.length = #response if not return_code then
reply.data = response
end
else
-- echo back with error flag -- echo back with error flag
reply.func_code = bit.bor(packet.func_code, MODBUS_FCODE.ERROR_FLAG) func_code = bit.bor(packet.func_code, MODBUS_FCODE.ERROR_FLAG)
if type(response) == "nil" then if type(response) == "nil" then
reply.length = 0 response = { }
reply.data = {}
elseif type(response) == "number" then elseif type(response) == "number" then
reply.length = 1 response = { response }
reply.data = { response }
elseif type(response) == "table" then elseif type(response) == "table" then
reply.length = #response response = response
reply.data = response
end end
end end
-- create reply
local reply = comms.modbus_packet()
reply.make(packet.txn_id, packet.unit_id, func_code, response)
return return_code, reply return return_code, reply
end end
-- return a NEG_ACKNOWLEDGE error reply
local reply__neg_ack = function (packet)
-- reply back with error flag and exception code
local reply = comms.modbus_packet()
local fcode = bit.bor(packet.func_code, MODBUS_FCODE.ERROR_FLAG)
local data = { MODBUS_EXCODE.NEG_ACKNOWLEDGE }
reply.make(packet.txn_id, packet.unit_id, fcode, data)
return reply
end
-- return a GATEWAY_PATH_UNAVAILABLE error reply
local reply__gw_unavailable = function (packet)
-- reply back with error flag and exception code
local reply = comms.modbus_packet()
local fcode = bit.bor(packet.func_code, MODBUS_FCODE.ERROR_FLAG)
local data = { MODBUS_EXCODE.GATEWAY_PATH_UNAVAILABLE }
reply.make(packet.txn_id, packet.unit_id, fcode, data)
return reply
end
return { return {
handle_packet = handle_packet handle_packet = handle_packet,
reply__neg_ack = reply__neg_ack,
reply__gw_unavailable = reply__gw_unavailable
} }
end end