#225 work in progress comms changes

This commit is contained in:
Mikayla
2023-06-05 05:13:22 +00:00
parent 50c0a4a3eb
commit 337fca7e7c
19 changed files with 373 additions and 293 deletions

View File

@@ -446,14 +446,15 @@ end
---@param id integer reactor ID
---@param version string PLC version
---@param modem table modem device
---@param local_port integer local listening port
---@param server_port integer remote server port
---@param plc_channel integer PLC comms channel
---@param svr_channel integer supervisor server channel
---@param range integer trusted device connection range
---@param reactor table reactor device
---@param rps rps RPS reference
---@param conn_watchdog watchdog watchdog reference
function plc.comms(id, version, modem, local_port, server_port, range, reactor, rps, conn_watchdog)
function plc.comms(id, version, modem, plc_channel, svr_channel, range, reactor, rps, conn_watchdog)
local self = {
sv_addr = comms.BROADCAST,
seq_num = 0,
r_seq_num = nil,
scrammed = false,
@@ -472,7 +473,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
-- configure modem channels
local function _conf_channels()
modem.closeAll()
modem.open(local_port)
modem.open(plc_channel)
end
_conf_channels()
@@ -485,9 +486,9 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
local r_pkt = comms.rplc_packet()
r_pkt.make(id, msg_type, msg)
s_pkt.make(self.seq_num, PROTOCOL.RPLC, r_pkt.raw_sendable())
s_pkt.make(self.sv_addr, self.seq_num, PROTOCOL.RPLC, r_pkt.raw_sendable())
modem.transmit(server_port, local_port, s_pkt.raw_sendable())
modem.transmit(svr_channel, plc_channel, s_pkt.raw_sendable())
self.seq_num = self.seq_num + 1
end
@@ -499,9 +500,9 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
local m_pkt = comms.mgmt_packet()
m_pkt.make(msg_type, msg)
s_pkt.make(self.seq_num, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
s_pkt.make(self.sv_addr, self.seq_num, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
modem.transmit(server_port, local_port, s_pkt.raw_sendable())
modem.transmit(svr_channel, plc_channel, s_pkt.raw_sendable())
self.seq_num = self.seq_num + 1
end
@@ -667,6 +668,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
-- unlink from the server
function public.unlink()
self.sv_addr = comms.BROADCAST
self.linked = false
self.r_seq_num = nil
self.status_cache = nil
@@ -731,7 +733,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
end
end
-- parse an RPLC packet
-- parse a packet
---@nodiscard
---@param side string
---@param sender integer
@@ -760,14 +762,14 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
pkt = mgmt_pkt.get()
end
else
log.debug("illegal packet type " .. s_pkt.protocol(), true)
log.debug("unsupported packet type " .. s_pkt.protocol(), true)
end
end
return pkt
end
-- handle an RPLC packet
-- handle RPLC and MGMT packets
---@param packet rplc_frame|mgmt_frame packet frame
---@param plc_state plc_state PLC state
---@param setpoints setpoints setpoint control table
@@ -775,10 +777,11 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
-- print a log message to the terminal as long as the UI isn't running
local function println_ts(message) if not plc_state.fp_ok then util.println_ts(message) end end
local l_port = packet.scada_frame.local_port()
local l_chan = packet.scada_frame.local_channel()
local src_addr = packet.scada_frame.src_addr()
-- handle packets now that we have prints setup
if l_port == local_port then
if l_chan == plc_channel then
-- check sequence number
if self.r_seq_num == nil then
self.r_seq_num = packet.scada_frame.seq_num()
@@ -797,7 +800,8 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
-- handle packet
if protocol == PROTOCOL.RPLC then
---@cast packet rplc_frame
if self.linked then
-- if linked, only accept packets from configured supervisor
if self.linked and (self.sv_addr == src_addr) then
if packet.type == RPLC_TYPE.STATUS then
-- request of full status, clear cache first
self.status_cache = nil
@@ -928,15 +932,18 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
else
log.debug("received unknown RPLC packet type " .. packet.type)
end
else
elseif not self.linked then
log.debug("discarding RPLC packet before linked")
else
log.debug("discarding RPLC from different supervisor (src_addr " .. src_addr .. "" .. self.sv_addr .. "sv_addr)")
end
elseif protocol == PROTOCOL.SCADA_MGMT then
---@cast packet mgmt_frame
if self.linked then
-- if linked, only accept packets from configured supervisor
if self.linked and (self.sv_addr == src_addr) then
if packet.type == SCADA_MGMT_TYPE.ESTABLISH then
-- link request confirmation
if packet.length == 1 then
if (packet.length == 1) and (self.sv_addr == src_addr) then
log.debug("received unsolicited establish response")
local est_ack = packet.data[1]
@@ -945,22 +952,26 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
self.status_cache = nil
_send_struct()
public.send_status(plc_state.no_reactor, plc_state.reactor_formed)
log.debug("re-sent initial status data")
elseif est_ack == ESTABLISH_ACK.DENY then
println_ts("received unsolicited link denial, unlinking")
log.warning("unsolicited establish request denied")
elseif est_ack == ESTABLISH_ACK.COLLISION then
println_ts("received unsolicited link collision, unlinking")
log.warning("unsolicited establish request collision")
elseif est_ack == ESTABLISH_ACK.BAD_VERSION then
println_ts("received unsolicited link version mismatch, unlinking")
log.warning("unsolicited establish request version mismatch")
log.debug("re-sent initial status data due to re-establish")
else
println_ts("invalid unsolicited link response")
log.debug("unsolicited unknown establish request response")
end
if est_ack == ESTABLISH_ACK.DENY then
println_ts("received unsolicited link denial, unlinking")
log.warning("unsolicited establish request denied")
elseif est_ack == ESTABLISH_ACK.COLLISION then
println_ts("received unsolicited link collision, unlinking")
log.warning("unsolicited establish request collision")
elseif est_ack == ESTABLISH_ACK.BAD_VERSION then
println_ts("received unsolicited link version mismatch, unlinking")
log.warning("unsolicited establish request version mismatch")
else
println_ts("invalid unsolicited link response")
log.debug("unsolicited unknown establish request response")
end
self.linked = est_ack == ESTABLISH_ACK.ALLOW
-- unlink
self.sv_addr = comms.BROADCAST
self.linked = false
end
-- clear this since this is for something that was unsolicited
self.last_est_ack = ESTABLISH_ACK.ALLOW
@@ -980,7 +991,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
log.warning("PLC KEEP_ALIVE trip time > 750ms (" .. trip_time .. "ms)")
end
-- log.debug("RPLC RTT = " .. trip_time .. "ms")
-- log.debug("PLC RTT = " .. trip_time .. "ms")
_send_keep_alive_ack(timestamp)
else
@@ -1002,9 +1013,11 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
if est_ack == ESTABLISH_ACK.ALLOW then
println_ts("linked!")
log.info("supervisor establish request approved, PLC is linked")
log.info("supervisor establish request approved, linked to SV (CID#" .. src_addr .. ")")
-- reset remote sequence number and cache
-- link + reset remote sequence number and cache
self.sv_addr = src_addr
self.linked = true
self.r_seq_num = nil
self.status_cache = nil
@@ -1012,23 +1025,28 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
public.send_status(plc_state.no_reactor, plc_state.reactor_formed)
log.debug("sent initial status data")
elseif self.last_est_ack ~= est_ack then
if est_ack == ESTABLISH_ACK.DENY then
println_ts("link request denied, retrying...")
log.info("supervisor establish request denied, retrying")
elseif est_ack == ESTABLISH_ACK.COLLISION then
println_ts("reactor PLC ID collision (check config), retrying...")
log.warning("establish request collision, retrying")
elseif est_ack == ESTABLISH_ACK.BAD_VERSION then
println_ts("supervisor version mismatch (try updating), retrying...")
log.warning("establish request version mismatch, retrying")
else
println_ts("invalid link response, bad channel? retrying...")
log.error("unknown establish request response, retrying")
else
if self.last_est_ack ~= est_ack then
if est_ack == ESTABLISH_ACK.DENY then
println_ts("link request denied, retrying...")
log.info("supervisor establish request denied, retrying")
elseif est_ack == ESTABLISH_ACK.COLLISION then
println_ts("reactor PLC ID collision (check config), retrying...")
log.warning("establish request collision, retrying")
elseif est_ack == ESTABLISH_ACK.BAD_VERSION then
println_ts("supervisor version mismatch (try updating), retrying...")
log.warning("establish request version mismatch, retrying")
else
println_ts("invalid link response, bad channel? retrying...")
log.error("unknown establish request response, retrying")
end
end
-- unlink
self.sv_addr = comms.BROADCAST
self.linked = false
end
self.linked = est_ack == ESTABLISH_ACK.ALLOW
self.last_est_ack = est_ack
-- report link state
@@ -1044,7 +1062,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
log.error("illegal packet type " .. protocol, true)
end
else
log.debug("received packet on unconfigured channel " .. l_port, true)
log.debug("received packet on unconfigured channel " .. l_chan, true)
end
end