mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
consistent packet constructors/receiving
This commit is contained in:
parent
013656bc4d
commit
36fb4587a1
@ -172,6 +172,78 @@ function iss_init(reactor)
|
||||
}
|
||||
end
|
||||
|
||||
function rplc_packet()
|
||||
local self = {
|
||||
frame = nil,
|
||||
id = nil,
|
||||
type = nil,
|
||||
length = nil,
|
||||
body = nil
|
||||
}
|
||||
|
||||
local _rplc_type_valid = function ()
|
||||
return self.type == RPLC_TYPES.KEEP_ALIVE or
|
||||
self.type == RPLC_TYPES.LINK_REQ or
|
||||
self.type == RPLC_TYPES.STATUS or
|
||||
self.type == RPLC_TYPES.MEK_STRUCT or
|
||||
self.type == RPLC_TYPES.MEK_SCRAM or
|
||||
self.type == RPLC_TYPES.MEK_ENABLE or
|
||||
self.type == RPLC_TYPES.MEK_BURN_RATE or
|
||||
self.type == RPLC_TYPES.ISS_ALARM or
|
||||
self.type == RPLC_TYPES.ISS_GET or
|
||||
self.type == RPLC_TYPES.ISS_CLEAR
|
||||
end
|
||||
|
||||
-- make an RPLC packet
|
||||
local make = function (id, packet_type, length, data)
|
||||
self.id = id
|
||||
self.type = packet_type
|
||||
self.length = length
|
||||
self.data = data
|
||||
end
|
||||
|
||||
-- decode an RPLC packet from a SCADA frame
|
||||
local decode = function (frame)
|
||||
if frame then
|
||||
self.frame = frame
|
||||
|
||||
if frame.protocol() == comms.PROTOCOLS.RPLC then
|
||||
local data = frame.data()
|
||||
local ok = #data > 2
|
||||
|
||||
if ok then
|
||||
make(data[1], data[2], data[3], { table.unpack(data, 4, #data) })
|
||||
ok = _rplc_type_valid()
|
||||
end
|
||||
|
||||
return ok
|
||||
else
|
||||
log._debug("attempted RPLC parse of incorrect protocol " .. frame.protocol(), true)
|
||||
return false
|
||||
end
|
||||
else
|
||||
log._debug("nil frame encountered", true)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local get = function ()
|
||||
return {
|
||||
scada_frame = self.frame,
|
||||
id = self.id,
|
||||
type = self.type,
|
||||
length = self.length,
|
||||
data = self.data
|
||||
}
|
||||
end
|
||||
|
||||
return {
|
||||
make = make,
|
||||
decode = decode,
|
||||
get = get
|
||||
}
|
||||
end
|
||||
|
||||
-- reactor PLC communications
|
||||
function rplc_comms(id, modem, local_port, server_port, reactor)
|
||||
local self = {
|
||||
@ -249,17 +321,21 @@ function rplc_comms(id, modem, local_port, server_port, reactor)
|
||||
-- parse packet as generic SCADA packet
|
||||
s_pkt.recieve(side, sender, reply_to, message, distance)
|
||||
|
||||
-- get using RPLC protocol format
|
||||
if s_pkt.is_valid() and s_pkt.protocol() == PROTOCOLS.RPLC then
|
||||
local body = s_pkt.data()
|
||||
if #body > 2 then
|
||||
pkt = {
|
||||
scada_frame = s_pkt,
|
||||
id = body[1],
|
||||
type = body[2],
|
||||
length = #body - 2,
|
||||
body = { table.unpack(body, 3, 2 + #body) }
|
||||
}
|
||||
if s_pkt.is_valid() then
|
||||
-- get as RPLC packet
|
||||
if s_pkt.protocol() == PROTOCOLS.RPLC then
|
||||
local rplc_pkt = rplc_packet()
|
||||
if rplc_pkt.decode(s_pkt) then
|
||||
pkt = rplc_pkt.get()
|
||||
end
|
||||
-- get as SCADA management packet
|
||||
elseif s_pkt.protocol() == PROTOCOLS.SCADA_MGMT then
|
||||
local mgmt_pkt = mgmt_packet()
|
||||
if mgmt_pkt.decode(s_pkt) then
|
||||
pkt = mgmt_packet.get()
|
||||
end
|
||||
else
|
||||
log._error("illegal packet type " .. s_pkt.protocol(), true)
|
||||
end
|
||||
end
|
||||
|
||||
|
38
rtu/rtu.lua
38
rtu/rtu.lua
@ -121,34 +121,17 @@ function rtu_comms(modem, local_port, server_port)
|
||||
-- get as MODBUS TCP packet
|
||||
if s_pkt.protocol() == PROTOCOLS.MODBUS_TCP then
|
||||
local m_pkt = modbus_packet()
|
||||
m_pkt.receive(s_pkt.data())
|
||||
|
||||
pkt = {
|
||||
scada_frame = s_pkt,
|
||||
modbus_frame = m_pkt
|
||||
}
|
||||
if m_pkt.decode(s_pkt) then
|
||||
pkt = m_pkt.get()
|
||||
end
|
||||
-- get as SCADA management packet
|
||||
elseif s_pkt.protocol() == PROTOCOLS.SCADA_MGMT then
|
||||
local body = s_pkt.data()
|
||||
if #body > 1 then
|
||||
pkt = {
|
||||
scada_frame = s_pkt,
|
||||
type = body[1],
|
||||
length = #body - 1,
|
||||
body = { table.unpack(body, 2, 1 + #body) }
|
||||
}
|
||||
elseif #body == 1 then
|
||||
pkt = {
|
||||
scada_frame = s_pkt,
|
||||
type = body[1],
|
||||
length = #body - 1,
|
||||
body = nil
|
||||
}
|
||||
else
|
||||
log._error("Malformed SCADA packet has no length field")
|
||||
local mgmt_pkt = mgmt_packet()
|
||||
if mgmt_pkt.decode(s_pkt) then
|
||||
pkt = mgmt_packet.get()
|
||||
end
|
||||
else
|
||||
log._error("Illegal packet type " .. s_pkt.protocol(), true)
|
||||
log._error("illegal packet type " .. s_pkt.protocol(), true)
|
||||
end
|
||||
end
|
||||
|
||||
@ -161,8 +144,9 @@ function rtu_comms(modem, local_port, server_port)
|
||||
|
||||
if protocol == PROTOCOLS.MODBUS_TCP then
|
||||
-- MODBUS instruction
|
||||
if packet.modbus_frame.unit_id <= #units then
|
||||
local return_code, response = units.modbus_io.handle_packet(packet.modbus_frame)
|
||||
if packet.unit_id <= #units then
|
||||
local unit = units[packet.unit_id]
|
||||
local return_code, response = unit.modbus_io.handle_packet(packet)
|
||||
_send(response, PROTOCOLS.MODBUS_TCP)
|
||||
|
||||
if not return_code then
|
||||
@ -186,7 +170,7 @@ function rtu_comms(modem, local_port, server_port)
|
||||
end
|
||||
else
|
||||
-- should be unreachable assuming packet is from parse_packet()
|
||||
log._error("Illegal packet type " .. protocol, true)
|
||||
log._error("illegal packet type " .. protocol, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -114,3 +114,67 @@ function scada_packet()
|
||||
data = data
|
||||
}
|
||||
end
|
||||
|
||||
function mgmt_packet()
|
||||
local self = {
|
||||
frame = nil,
|
||||
type = nil,
|
||||
length = nil,
|
||||
data = nil
|
||||
}
|
||||
|
||||
local _scada_type_valid = function ()
|
||||
return self.type == SCADA_MGMT_TYPES.PING or
|
||||
self.type == SCADA_MGMT_TYPES.SV_HEARTBEAT or
|
||||
self.type == SCADA_MGMT_TYPES.REMOTE_LINKED or
|
||||
self.type == SCADA_MGMT_TYPES.RTU_ADVERT or
|
||||
self.type == SCADA_MGMT_TYPES.RTU_HEARTBEAT
|
||||
end
|
||||
|
||||
-- make a SCADA management packet
|
||||
local make = function (packet_type, length, data)
|
||||
self.type = packet_type
|
||||
self.length = length
|
||||
self.data = data
|
||||
end
|
||||
|
||||
-- decode a SCADA management packet from a SCADA frame
|
||||
local decode = function (frame)
|
||||
if frame then
|
||||
self.frame = frame
|
||||
|
||||
if frame.protocol() == comms.PROTOCOLS.SCADA_MGMT then
|
||||
local data = frame.data()
|
||||
local ok = #data > 1
|
||||
|
||||
if ok then
|
||||
make(data[1], data[2], { table.unpack(data, 3, #data) })
|
||||
ok = _scada_type_valid()
|
||||
end
|
||||
|
||||
return ok
|
||||
else
|
||||
log._debug("attempted SCADA_MGMT parse of incorrect protocol " .. frame.protocol(), true)
|
||||
return false
|
||||
end
|
||||
else
|
||||
log._debug("nil frame encountered", true)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local get = function ()
|
||||
return {
|
||||
scada_frame = self.frame,
|
||||
type = self.type,
|
||||
length = self.length,
|
||||
data = self.data
|
||||
}
|
||||
end
|
||||
|
||||
return {
|
||||
make = make,
|
||||
decode = decode,
|
||||
get = get
|
||||
}
|
||||
end
|
||||
|
@ -176,9 +176,8 @@ function modbus_init(rtu_dev)
|
||||
end
|
||||
|
||||
function modbus_packet()
|
||||
local MODBUS_TCP = 0
|
||||
|
||||
local self = {
|
||||
frame = nil,
|
||||
txn_id = txn_id,
|
||||
protocol = protocol,
|
||||
length = length,
|
||||
@ -187,6 +186,7 @@ function modbus_packet()
|
||||
data = data
|
||||
}
|
||||
|
||||
-- make a MODBUS packet
|
||||
local make = function (txn_id, protocol, length, unit_id, func_code, data)
|
||||
self.txn_id = txn_id
|
||||
self.protocol = protocol
|
||||
@ -196,18 +196,29 @@ function modbus_packet()
|
||||
self.data = data
|
||||
end
|
||||
|
||||
local receive = function (raw)
|
||||
local size_ok = #raw ~= 6
|
||||
-- decode a MODBUS packet from a SCADA frame
|
||||
local decode = function (frame)
|
||||
if frame then
|
||||
self.frame = frame
|
||||
|
||||
local data = frame.data()
|
||||
local size_ok = #data ~= 6
|
||||
|
||||
if size_ok then
|
||||
make(raw[1], raw[2], raw[3], raw[4], raw[5], raw[6])
|
||||
if size_ok then
|
||||
make(data[1], data[2], data[3], data[4], data[5], data[6])
|
||||
end
|
||||
|
||||
return size_ok and self.protocol == comms.PROTOCOLS.MODBUS_TCP
|
||||
else
|
||||
log._debug("nil frame encountered", true)
|
||||
return false
|
||||
end
|
||||
|
||||
return size_ok and self.protocol == MODBUS_TCP
|
||||
end
|
||||
|
||||
-- get this packet
|
||||
local get = function ()
|
||||
return {
|
||||
scada_frame = self.frame,
|
||||
txn_id = self.txn_id,
|
||||
protocol = self.protocol,
|
||||
length = self.length,
|
||||
@ -219,7 +230,7 @@ function modbus_packet()
|
||||
|
||||
return {
|
||||
make = make,
|
||||
receive = receive,
|
||||
decode = decode,
|
||||
get = get
|
||||
}
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user