From 912011bfede5c239cbf170a203a1a9d575d715f8 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Fri, 22 Apr 2022 20:21:28 -0400 Subject: [PATCH] #30 modbus comms changes --- scada-common/comms.lua | 17 ++++++-------- scada-common/modbus.lua | 51 ++++++++++++++++++++++++++++------------- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/scada-common/comms.lua b/scada-common/comms.lua index c4b8791..972f768 100644 --- a/scada-common/comms.lua +++ b/scada-common/comms.lua @@ -88,7 +88,7 @@ function scada_packet() -- public accessors -- 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 receiver = function () return self.r_port end @@ -106,7 +106,7 @@ function scada_packet() receive = receive, -- raw access modem_event = modem_event, - raw = raw, + raw_sendable = raw_sendable, -- sender/receiver sender = sender, receiver = receiver, @@ -121,13 +121,12 @@ function scada_packet() end -- 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() local self = { frame = nil, raw = nil, txn_id = txn_id, - protocol = protocol, length = length, unit_id = unit_id, func_code = func_code, @@ -135,16 +134,15 @@ function 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.protocol = protocol self.length = #data self.unit_id = unit_id self.func_code = func_code self.data = data -- 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 table.insert(self.raw, data[i]) end @@ -156,11 +154,11 @@ function modbus_packet() self.frame = frame if frame.protocol() == PROTOCOLS.MODBUS_TCP then - local size_ok = frame.length() >= 4 + local size_ok = frame.length() >= 3 if size_ok then 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 return size_ok @@ -182,7 +180,6 @@ function modbus_packet() return { scada_frame = self.frame, txn_id = self.txn_id, - protocol = self.protocol, length = self.length, unit_id = self.unit_id, func_code = self.func_code, diff --git a/scada-common/modbus.lua b/scada-common/modbus.lua index a8148b7..494fde8 100644 --- a/scada-common/modbus.lua +++ b/scada-common/modbus.lua @@ -203,10 +203,10 @@ function new(rtu_dev) return return_ok, response end + -- handle a MODBUS TCP packet and generate a reply local handle_packet = function (packet) local return_code = true local response = nil - local reply = packet if #packet.data == 2 then -- handle by function code @@ -236,32 +236,51 @@ function new(rtu_dev) return_code = false end - if return_code then - -- default is to echo back - if type(response) == "table" then - reply.length = #response - reply.data = response - end - else + -- default is to echo back + local func_code = packet.func_code + if not return_code then -- 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 - reply.length = 0 - reply.data = {} + response = { } elseif type(response) == "number" then - reply.length = 1 - reply.data = { response } + response = { response } elseif type(response) == "table" then - reply.length = #response - reply.data = response + response = response end end + -- create reply + local reply = comms.modbus_packet() + reply.make(packet.txn_id, packet.unit_id, func_code, response) + return return_code, reply 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 { - handle_packet = handle_packet + handle_packet = handle_packet, + reply__neg_ack = reply__neg_ack, + reply__gw_unavailable = reply__gw_unavailable } end