#41 PLC connection closing

This commit is contained in:
Mikayla Fischler 2022-05-02 12:06:04 -04:00
parent b280201446
commit 5ce3f84dfa
3 changed files with 64 additions and 12 deletions

View File

@ -197,6 +197,7 @@ end
function comms_init(id, modem, local_port, server_port, reactor, iss) function comms_init(id, modem, local_port, server_port, reactor, iss)
local self = { local self = {
id = id, id = id,
open = false,
seq_num = 0, seq_num = 0,
r_seq_num = nil, r_seq_num = nil,
modem = modem, modem = modem,
@ -218,14 +219,29 @@ function comms_init(id, modem, local_port, server_port, reactor, iss)
-- PRIVATE FUNCTIONS -- -- PRIVATE FUNCTIONS --
local _send = function (msg_type, msg) local _send = function (msg_type, msg)
local s_pkt = comms.scada_packet() if self.open then
local r_pkt = comms.rplc_packet() local s_pkt = comms.scada_packet()
local r_pkt = comms.rplc_packet()
r_pkt.make(self.id, msg_type, msg) r_pkt.make(self.id, msg_type, msg)
s_pkt.make(self.seq_num, PROTOCOLS.RPLC, r_pkt.raw_sendable()) s_pkt.make(self.seq_num, PROTOCOLS.RPLC, r_pkt.raw_sendable())
self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable()) self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable())
self.seq_num = self.seq_num + 1 self.seq_num = self.seq_num + 1
end
end
local _send_mgmt = function (msg_type, msg)
if self.open then
local s_pkt = comms.scada_packet()
local m_pkt = comms.mgmt_packet()
m_pkt.make(msg_type, msg)
s_pkt.make(self.seq_num, PROTOCOLS.RPLC, m_pkt.raw_sendable())
self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable())
self.seq_num = self.seq_num + 1
end
end end
-- variable reactor status information, excluding heating rate -- variable reactor status information, excluding heating rate
@ -425,6 +441,9 @@ function comms_init(id, modem, local_port, server_port, reactor, iss)
self.r_seq_num = packet.scada_frame.seq_num() self.r_seq_num = packet.scada_frame.seq_num()
end end
-- mark connection as open
self.open = true
-- feed the watchdog first so it doesn't uhh...eat our packets -- feed the watchdog first so it doesn't uhh...eat our packets
conn_watchdog.feed() conn_watchdog.feed()
@ -555,19 +574,34 @@ function comms_init(id, modem, local_port, server_port, reactor, iss)
log._debug("discarding non-link packet before linked") log._debug("discarding non-link packet before linked")
end end
elseif packet.scada_frame.protocol() == PROTOCOLS.SCADA_MGMT then elseif packet.scada_frame.protocol() == PROTOCOLS.SCADA_MGMT then
-- @todo -- handle session close
if packet.type == SCADA_MGMT_TYPES.CLOSE then
self.open = false
conn_watchdog.cancel()
unlink()
else
log._warning("received unknown SCADA_MGMT packet type " .. packet.type)
end
end end
end end
end end
local is_scrammed = function () return self.scrammed end local is_scrammed = function () return self.scrammed end
local is_linked = function () return self.linked end local is_linked = function () return self.linked end
local is_closed = function () return not self.open end
local unlink = function () local unlink = function ()
self.linked = false self.linked = false
self.r_seq_num = nil self.r_seq_num = nil
end end
local close = function ()
self.open = false
conn_watchdog.cancel()
unlink()
_send_mgmt(SCADA_MGMT_TYPES.CLOSE, {})
end
return { return {
reconnect_modem = reconnect_modem, reconnect_modem = reconnect_modem,
reconnect_reactor = reconnect_reactor, reconnect_reactor = reconnect_reactor,
@ -579,6 +613,8 @@ function comms_init(id, modem, local_port, server_port, reactor, iss)
send_iss_alarm = send_iss_alarm, send_iss_alarm = send_iss_alarm,
is_scrammed = is_scrammed, is_scrammed = is_scrammed,
is_linked = is_linked, is_linked = is_linked,
unlink = unlink is_closed = is_closed,
unlink = unlink,
close = close
} }
end end

View File

@ -12,7 +12,7 @@ os.loadAPI("config.lua")
os.loadAPI("plc.lua") os.loadAPI("plc.lua")
os.loadAPI("threads.lua") os.loadAPI("threads.lua")
local R_PLC_VERSION = "alpha-v0.4.13" local R_PLC_VERSION = "alpha-v0.4.14"
local print = util.print local print = util.print
local println = util.println local println = util.println

View File

@ -169,9 +169,11 @@ function thread__main(smem, init)
-- check for termination request -- check for termination request
if event == "terminate" or ppm.should_terminate() then if event == "terminate" or ppm.should_terminate() then
log._info("terminate requested, main thread exiting")
-- iss handles reactor shutdown -- iss handles reactor shutdown
plc_state.shutdown = true plc_state.shutdown = true
log._info("terminate requested, main thread exiting") -- close connection
plc_comms.close()
break break
end end
end end
@ -195,6 +197,7 @@ function thread__iss(smem)
local iss_queue = smem.q.mq_iss local iss_queue = smem.q.mq_iss
local was_closed = true
local last_update = util.time() local last_update = util.time()
-- thread loop -- thread loop
@ -203,6 +206,19 @@ function thread__iss(smem)
-- ISS checks -- ISS checks
if plc_state.init_ok then if plc_state.init_ok then
-- SCRAM if no open connection
if networked and plc_comms.is_closed() then
plc_state.scram = true
if not was_closed then
was_closed = true
iss.trip_timeout()
println_ts("server connection closed by remote host")
log._warning("server connection closed by remote host")
end
else
was_closed = false
end
-- if we tried to SCRAM but failed, keep trying -- if we tried to SCRAM but failed, keep trying
-- in that case, SCRAM won't be called until it reconnects (this is the expected use of this check) -- in that case, SCRAM won't be called until it reconnects (this is the expected use of this check)
if not plc_state.no_reactor and plc_state.scram and reactor.getStatus() then if not plc_state.no_reactor and plc_state.scram and reactor.getStatus() then
@ -217,13 +233,13 @@ function thread__iss(smem)
end end
-- check safety (SCRAM occurs if tripped) -- check safety (SCRAM occurs if tripped)
if not plc_state.degraded then if not plc_state.no_reactor then
local iss_tripped, iss_status_string, iss_first = iss.check() local iss_tripped, iss_status_string, iss_first = iss.check()
plc_state.scram = plc_state.scram or iss_tripped plc_state.scram = plc_state.scram or iss_tripped
if iss_first then if iss_first then
println_ts("[ISS] SCRAM! safety trip: " .. iss_status_string) println_ts("[ISS] SCRAM! safety trip: " .. iss_status_string)
if networked then if networked and not plc_state.no_modem then
plc_comms.send_iss_alarm(iss_status_string) plc_comms.send_iss_alarm(iss_status_string)
end end
end end