#184 RTU and pocket lists on supervisor front panel, element delete() bugfix

This commit is contained in:
Mikayla Fischler
2023-06-03 14:33:08 -04:00
parent 153a83e569
commit 69df5edbeb
15 changed files with 335 additions and 54 deletions

View File

@ -1,7 +1,8 @@
local comms = require("scada-common.comms")
local log = require("scada-common.log")
local mqueue = require("scada-common.mqueue")
local util = require("scada-common.util")
local comms = require("scada-common.comms")
local log = require("scada-common.log")
local mqueue = require("scada-common.mqueue")
local util = require("scada-common.util")
local databus = require("supervisor.databus")
local pocket = {}
@ -35,7 +36,7 @@ local PERIODICS = {
---@param out_queue mqueue out message queue
---@param timeout number communications timeout
function pocket.new_session(id, in_queue, out_queue, timeout)
local log_header = "diag_session(" .. id .. "): "
local log_header = "pdg_session(" .. id .. "): "
local self = {
-- connection properties
@ -56,18 +57,19 @@ function pocket.new_session(id, in_queue, out_queue, timeout)
acks = {
},
-- session database
---@class diag_db
---@class pdg_db
sDB = {
}
}
---@class diag_session
---@class pdg_session
local public = {}
-- mark this diagnostics session as closed, stop watchdog
local function _close()
self.conn_watchdog.cancel()
self.connected = false
databus.tx_pdg_disconnected(id)
end
-- send a SCADA management packet
@ -107,16 +109,18 @@ function pocket.new_session(id, in_queue, out_queue, timeout)
-- keep alive reply
if pkt.length == 2 then
local srv_start = pkt.data[1]
-- local diag_send = pkt.data[2]
-- local pdg_send = pkt.data[2]
local srv_now = util.time()
self.last_rtt = srv_now - srv_start
if self.last_rtt > 750 then
log.warning(log_header .. "DIAG KEEP_ALIVE round trip time > 750ms (" .. self.last_rtt .. "ms)")
log.warning(log_header .. "PDG KEEP_ALIVE round trip time > 750ms (" .. self.last_rtt .. "ms)")
end
-- log.debug(log_header .. "DIAG RTT = " .. self.last_rtt .. "ms")
-- log.debug(log_header .. "DIAG TT = " .. (srv_now - diag_send) .. "ms")
-- log.debug(log_header .. "PDG RTT = " .. self.last_rtt .. "ms")
-- log.debug(log_header .. "PDG TT = " .. (srv_now - pdg_send) .. "ms")
databus.tx_pdg_rtt(id, self.last_rtt)
else
log.debug(log_header .. "SCADA keep alive packet length mismatch")
end

View File

@ -4,6 +4,8 @@ local mqueue = require("scada-common.mqueue")
local types = require("scada-common.types")
local util = require("scada-common.util")
local databus = require("supervisor.databus")
local svqtypes = require("supervisor.session.svqtypes")
-- supervisor rtu sessions (svrs)
@ -67,6 +69,8 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
-- parse the recorded advertisement and create unit sub-sessions
local function _handle_advertisement()
local unit_count = 0
_reset_config()
for i = 1, #self.fac_units do
@ -173,18 +177,22 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
if unit ~= nil then
self.units[i] = unit
unit_count = unit_count + 1
elseif u_type ~= RTU_UNIT_TYPE.VIRTUAL then
_reset_config()
log.error(util.c(log_header, "bad advertisement: error occured while creating a unit (type is ", type_string, ")"))
break
end
end
databus.tx_rtu_units(id, unit_count)
end
-- mark this RTU session as closed, stop watchdog
local function _close()
self.conn_watchdog.cancel()
self.connected = false
databus.tx_rtu_disconnected(id)
-- mark all RTU unit sessions as closed so the reactor unit knows
for _, unit in pairs(self.units) do unit.close() end
@ -255,6 +263,8 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
-- log.debug(log_header .. "RTU RTT = " .. self.last_rtt .. "ms")
-- log.debug(log_header .. "RTU TT = " .. (srv_now - rtu_send) .. "ms")
databus.tx_rtu_rtt(id, self.last_rtt)
else
log.debug(log_header .. "SCADA keep alive packet length mismatch")
end

View File

@ -28,7 +28,7 @@ local SESSION_TYPE = {
RTU_SESSION = 0, -- RTU gateway
PLC_SESSION = 1, -- reactor PLC
COORD_SESSION = 2, -- coordinator
DIAG_SESSION = 3 -- pocket diagnostics
PDG_SESSION = 3 -- pocket diagnostics
}
svsessions.SESSION_TYPE = SESSION_TYPE
@ -37,11 +37,11 @@ local self = {
modem = nil, ---@type table|nil
num_reactors = 0,
facility = nil, ---@type facility|nil
sessions = { rtu = {}, plc = {}, coord = {}, diag = {} },
next_ids = { rtu = 0, plc = 0, coord = 0, diag = 0 }
sessions = { rtu = {}, plc = {}, coord = {}, pdg = {} },
next_ids = { rtu = 0, plc = 0, coord = 0, pdg = 0 }
}
---@alias sv_session_structs plc_session_struct|rtu_session_struct|coord_session_struct|diag_session_struct
---@alias sv_session_structs plc_session_struct|rtu_session_struct|coord_session_struct|pdg_session_struct
-- PRIVATE FUNCTIONS --
@ -251,14 +251,14 @@ end
-- find a coordinator or diagnostic access session by the remote port
---@nodiscard
---@param remote_port integer
---@return coord_session_struct|diag_session_struct|nil
---@return coord_session_struct|pdg_session_struct|nil
function svsessions.find_svctl_session(remote_port)
-- check coordinator sessions
local session = _find_session(self.sessions.coord, remote_port)
-- check diagnostic sessions
if session == nil then session = _find_session(self.sessions.diag, remote_port) end
---@cast session coord_session_struct|diag_session_struct|nil
if session == nil then session = _find_session(self.sessions.pdg, remote_port) end
---@cast session coord_session_struct|pdg_session_struct|nil
return session
end
@ -316,10 +316,10 @@ function svsessions.establish_plc_session(local_port, remote_port, for_reactor,
log.debug(util.c("established new PLC session to ", remote_port, " with ID ", self.next_ids.plc, " for reactor ", for_reactor))
self.next_ids.plc = self.next_ids.plc + 1
databus.tx_plc_connected(for_reactor, version, remote_port)
self.next_ids.plc = self.next_ids.plc + 1
-- success
return plc_s.instance.get_id()
else
@ -353,6 +353,8 @@ function svsessions.establish_rtu_session(local_port, remote_port, advertisement
log.debug("established new RTU session to " .. remote_port .. " with ID " .. self.next_ids.rtu)
databus.tx_rtu_connected(self.next_ids.rtu, version, remote_port)
self.next_ids.rtu = self.next_ids.rtu + 1
-- success
@ -384,10 +386,10 @@ function svsessions.establish_coord_session(local_port, remote_port, version)
log.debug("established new coordinator session to " .. remote_port .. " with ID " .. self.next_ids.coord)
self.next_ids.coord = self.next_ids.coord + 1
databus.tx_crd_connected(version, remote_port)
self.next_ids.coord = self.next_ids.coord + 1
-- success
return coord_s.instance.get_id()
else
@ -402,9 +404,9 @@ end
---@param remote_port integer
---@param version string
---@return integer|false session_id
function svsessions.establish_diag_session(local_port, remote_port, version)
---@class diag_session_struct
local diag_s = {
function svsessions.establish_pdg_session(local_port, remote_port, version)
---@class pdg_session_struct
local pdg_s = {
s_type = "pkt",
open = true,
version = version,
@ -412,18 +414,20 @@ function svsessions.establish_diag_session(local_port, remote_port, version)
r_port = remote_port,
in_queue = mqueue.new(),
out_queue = mqueue.new(),
instance = nil ---@type diag_session
instance = nil ---@type pdg_session
}
diag_s.instance = pocket.new_session(self.next_ids.diag, diag_s.in_queue, diag_s.out_queue, config.PKT_TIMEOUT)
table.insert(self.sessions.diag, diag_s)
pdg_s.instance = pocket.new_session(self.next_ids.pdg, pdg_s.in_queue, pdg_s.out_queue, config.PKT_TIMEOUT)
table.insert(self.sessions.pdg, pdg_s)
log.debug("established new pocket diagnostics session to " .. remote_port .. " with ID " .. self.next_ids.diag)
log.debug("established new pocket diagnostics session to " .. remote_port .. " with ID " .. self.next_ids.pdg)
self.next_ids.diag = self.next_ids.diag + 1
databus.tx_pdg_connected(self.next_ids.pdg, version, remote_port)
self.next_ids.pdg = self.next_ids.pdg + 1
-- success
return diag_s.instance.get_id()
return pdg_s.instance.get_id()
end
-- attempt to identify which session's watchdog timer fired