From 69df5edbeb0f77f87d0ebacce881a48ba6bae59c Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 3 Jun 2023 14:33:08 -0400 Subject: [PATCH] #184 RTU and pocket lists on supervisor front panel, element delete() bugfix --- coordinator/startup.lua | 2 +- graphics/element.lua | 5 +- pocket/startup.lua | 2 +- reactor-plc/startup.lua | 2 +- rtu/startup.lua | 2 +- supervisor/databus.lua | 75 ++++++++++++++++++-- supervisor/panel/components/pdg_entry.lua | 48 +++++++++++++ supervisor/panel/components/rtu_entry.lua | 52 ++++++++++++++ supervisor/panel/front_panel.lua | 26 ++++--- supervisor/panel/pgi.lua | 85 +++++++++++++++++++++++ supervisor/session/pocket.lua | 26 ++++--- supervisor/session/rtu.lua | 10 +++ supervisor/session/svsessions.lua | 44 ++++++------ supervisor/startup.lua | 6 +- supervisor/supervisor.lua | 4 +- 15 files changed, 335 insertions(+), 54 deletions(-) create mode 100644 supervisor/panel/components/pdg_entry.lua create mode 100644 supervisor/panel/components/rtu_entry.lua create mode 100644 supervisor/panel/pgi.lua diff --git a/coordinator/startup.lua b/coordinator/startup.lua index 0faf0fb..c0addf1 100644 --- a/coordinator/startup.lua +++ b/coordinator/startup.lua @@ -20,7 +20,7 @@ local sounder = require("coordinator.sounder") local apisessions = require("coordinator.session.apisessions") -local COORDINATOR_VERSION = "v0.15.5" +local COORDINATOR_VERSION = "v0.15.6" local println = util.println local println_ts = util.println_ts diff --git a/graphics/element.lua b/graphics/element.lua index d537171..ae2daee 100644 --- a/graphics/element.lua +++ b/graphics/element.lua @@ -323,7 +323,10 @@ function element.new(args) protected.children[k] = nil end - args.parent.__remove_child(self.id) + if args.parent ~= nil then + -- remove self from parent + args.parent.__remove_child(self.id) + end end -- ELEMENT TREE -- diff --git a/pocket/startup.lua b/pocket/startup.lua index 2a48042..50862d1 100644 --- a/pocket/startup.lua +++ b/pocket/startup.lua @@ -17,7 +17,7 @@ local coreio = require("pocket.coreio") local pocket = require("pocket.pocket") local renderer = require("pocket.renderer") -local POCKET_VERSION = "alpha-v0.3.5" +local POCKET_VERSION = "alpha-v0.3.6" local println = util.println local println_ts = util.println_ts diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index cf3b08a..3e8861b 100644 --- a/reactor-plc/startup.lua +++ b/reactor-plc/startup.lua @@ -18,7 +18,7 @@ local plc = require("reactor-plc.plc") local renderer = require("reactor-plc.renderer") local threads = require("reactor-plc.threads") -local R_PLC_VERSION = "v1.3.5" +local R_PLC_VERSION = "v1.3.6" local println = util.println local println_ts = util.println_ts diff --git a/rtu/startup.lua b/rtu/startup.lua index 1ae38ed..86c3db2 100644 --- a/rtu/startup.lua +++ b/rtu/startup.lua @@ -28,7 +28,7 @@ local sna_rtu = require("rtu.dev.sna_rtu") local sps_rtu = require("rtu.dev.sps_rtu") local turbinev_rtu = require("rtu.dev.turbinev_rtu") -local RTU_VERSION = "v1.2.5" +local RTU_VERSION = "v1.2.6" local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE diff --git a/supervisor/databus.lua b/supervisor/databus.lua index 082a71e..88e4ed3 100644 --- a/supervisor/databus.lua +++ b/supervisor/databus.lua @@ -4,15 +4,13 @@ local psil = require("scada-common.psil") +local pgi = require("supervisor.panel.pgi") + local databus = {} -- databus PSIL databus.ps = psil.create() -local dbus_iface = { - session_entries = { rtu = {}, diag = {} } -} - -- call to toggle heartbeat signal function databus.heartbeat() databus.ps.toggle("heartbeat") end @@ -65,6 +63,44 @@ function databus.tx_plc_rtt(reactor_id, rtt) end end +-- transmit RTU firmware version and session connection state +---@param session_id integer RTU session +---@param fw string firmware version +---@param channel integer RTU remote port +function databus.tx_rtu_connected(session_id, fw, channel) + databus.ps.publish("rtu_" .. session_id .. "_fw", fw) + databus.ps.publish("rtu_" .. session_id .. "_chan", tostring(channel)) + pgi.create_rtu_entry(session_id) +end + +-- transmit RTU disconnected +---@param session_id integer RTU session +function databus.tx_rtu_disconnected(session_id) + pgi.delete_rtu_entry(session_id) +end + +-- transmit RTU session RTT +---@param session_id integer RTU session +---@param rtt integer round trip time +function databus.tx_rtu_rtt(session_id, rtt) + databus.ps.publish("rtu_" .. session_id .. "_rtt", rtt) + + if rtt > 700 then + databus.ps.publish("rtu_" .. session_id .. "_rtt_color", colors.red) + elseif rtt > 300 then + databus.ps.publish("rtu_" .. session_id .. "_rtt_color", colors.yellow_hc) + else + databus.ps.publish("rtu_" .. session_id .. "_rtt_color", colors.green) + end +end + +-- transmit RTU session unit count +---@param session_id integer RTU session +---@param units integer unit count +function databus.tx_rtu_units(session_id, units) + databus.ps.publish("rtu_" .. session_id .. "_units", units) +end + -- transmit coordinator firmware version and session connection state ---@param fw string firmware version ---@param channel integer coordinator remote port @@ -97,6 +133,37 @@ function databus.tx_crd_rtt(rtt) end end +-- transmit PDG firmware version and session connection state +---@param session_id integer PDG session +---@param fw string firmware version +---@param channel integer PDG remote port +function databus.tx_pdg_connected(session_id, fw, channel) + databus.ps.publish("pdg_" .. session_id .. "_fw", fw) + databus.ps.publish("pdg_" .. session_id .. "_chan", tostring(channel)) + pgi.create_pdg_entry(session_id) +end + +-- transmit PDG disconnected +---@param session_id integer PDG session +function databus.tx_pdg_disconnected(session_id) + pgi.delete_pdg_entry(session_id) +end + +-- transmit PDG session RTT +---@param session_id integer PDG session +---@param rtt integer round trip time +function databus.tx_pdg_rtt(session_id, rtt) + databus.ps.publish("pdg_" .. session_id .. "_rtt", rtt) + + if rtt > 700 then + databus.ps.publish("pdg_" .. session_id .. "_rtt_color", colors.red) + elseif rtt > 300 then + databus.ps.publish("pdg_" .. session_id .. "_rtt_color", colors.yellow_hc) + else + databus.ps.publish("pdg_" .. session_id .. "_rtt_color", colors.green) + end +end + -- link a function to receive data from the bus ---@param field string field name ---@param func function function to link diff --git a/supervisor/panel/components/pdg_entry.lua b/supervisor/panel/components/pdg_entry.lua new file mode 100644 index 0000000..94cd385 --- /dev/null +++ b/supervisor/panel/components/pdg_entry.lua @@ -0,0 +1,48 @@ +-- +-- Pocket Diagnostics Connection Entry +-- + +local util = require("scada-common.util") + +local databus = require("supervisor.databus") + +local core = require("graphics.core") + +local Div = require("graphics.elements.div") +local TextBox = require("graphics.elements.textbox") + +local DataIndicator = require("graphics.elements.indicators.data") + +local TEXT_ALIGN = core.TEXT_ALIGN + +local cpair = core.cpair + +-- create a pocket diagnostics list entry +---@param parent graphics_element parent +---@param id integer PDG session ID +local function init(parent, id) + -- root div + local root = Div{parent=parent,x=2,y=2,height=4,width=parent.get_width()-2,hidden=true} + local entry = Div{parent=root,x=2,y=1,height=3,fg_bg=cpair(colors.black,colors.white)} + + local ps_prefix = "pdg_" .. id .. "_" + + TextBox{parent=entry,x=1,y=1,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)} + local pdg_chan = TextBox{parent=entry,x=1,y=2,text=" :00000",alignment=TEXT_ALIGN.CENTER,width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray),nav_active=cpair(colors.gray,colors.black)} + TextBox{parent=entry,x=1,y=3,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)} + pdg_chan.register(databus.ps, ps_prefix .. "chan", function (channel) pdg_chan.set_value(util.sprintf(" :%05d", channel)) end) + + TextBox{parent=entry,x=10,y=2,text="FW:",width=3,height=1} + local pdg_fw_v = TextBox{parent=entry,x=14,y=2,text=" ------- ",width=20,height=1,fg_bg=cpair(colors.lightGray,colors.white)} + pdg_fw_v.register(databus.ps, ps_prefix .. "fw", pdg_fw_v.set_value) + + TextBox{parent=entry,x=35,y=2,text="RTT:",width=4,height=1} + local pdg_rtt = DataIndicator{parent=entry,x=40,y=2,label="",unit="",format="%5d",value=0,width=5,fg_bg=cpair(colors.lightGray,colors.white)} + TextBox{parent=entry,x=46,y=2,text="ms",width=4,height=1,fg_bg=cpair(colors.lightGray,colors.white)} + pdg_rtt.register(databus.ps, ps_prefix .. "rtt", pdg_rtt.update) + pdg_rtt.register(databus.ps, ps_prefix .. "rtt_color", pdg_rtt.recolor) + + return root +end + +return init diff --git a/supervisor/panel/components/rtu_entry.lua b/supervisor/panel/components/rtu_entry.lua new file mode 100644 index 0000000..a4a5a4e --- /dev/null +++ b/supervisor/panel/components/rtu_entry.lua @@ -0,0 +1,52 @@ +-- +-- RTU Connection Entry +-- + +local util = require("scada-common.util") + +local databus = require("supervisor.databus") + +local core = require("graphics.core") + +local Div = require("graphics.elements.div") +local TextBox = require("graphics.elements.textbox") + +local DataIndicator = require("graphics.elements.indicators.data") + +local TEXT_ALIGN = core.TEXT_ALIGN + +local cpair = core.cpair + +-- create an RTU list entry +---@param parent graphics_element parent +---@param id integer RTU session ID +local function init(parent, id) + -- root div + local root = Div{parent=parent,x=2,y=2,height=4,width=parent.get_width()-2,hidden=true} + local entry = Div{parent=root,x=2,y=1,height=3,fg_bg=cpair(colors.black,colors.white)} + + local ps_prefix = "rtu_" .. id .. "_" + + TextBox{parent=entry,x=1,y=1,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)} + local rtu_chan = TextBox{parent=entry,x=1,y=2,text=" :00000",alignment=TEXT_ALIGN.CENTER,width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray),nav_active=cpair(colors.gray,colors.black)} + TextBox{parent=entry,x=1,y=3,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)} + rtu_chan.register(databus.ps, ps_prefix .. "chan", function (channel) rtu_chan.set_value(util.sprintf(" :%05d", channel)) end) + + TextBox{parent=entry,x=10,y=2,text="UNITS:",width=7,height=1} + local unit_count = DataIndicator{parent=entry,x=17,y=2,label="",unit="",format="%2d",value=0,width=2,fg_bg=cpair(colors.gray,colors.white)} + unit_count.register(databus.ps, ps_prefix .. "units", unit_count.set_value) + + TextBox{parent=entry,x=21,y=2,text="FW:",width=3,height=1} + local rtu_fw_v = TextBox{parent=entry,x=25,y=2,text=" ------- ",width=9,height=1,fg_bg=cpair(colors.lightGray,colors.white)} + rtu_fw_v.register(databus.ps, ps_prefix .. "fw", rtu_fw_v.set_value) + + TextBox{parent=entry,x=36,y=2,text="RTT:",width=4,height=1} + local rtu_rtt = DataIndicator{parent=entry,x=40,y=2,label="",unit="",format="%5d",value=0,width=5,fg_bg=cpair(colors.lightGray,colors.white)} + TextBox{parent=entry,x=46,y=2,text="ms",width=4,height=1,fg_bg=cpair(colors.lightGray,colors.white)} + rtu_rtt.register(databus.ps, ps_prefix .. "rtt", rtu_rtt.update) + rtu_rtt.register(databus.ps, ps_prefix .. "rtt_color", rtu_rtt.recolor) + + return root +end + +return init diff --git a/supervisor/panel/front_panel.lua b/supervisor/panel/front_panel.lua index 940a116..86d9839 100644 --- a/supervisor/panel/front_panel.lua +++ b/supervisor/panel/front_panel.lua @@ -7,8 +7,12 @@ local util = require("scada-common.util") local config = require("supervisor.config") local databus = require("supervisor.databus") +local pgi = require("supervisor.panel.pgi") local style = require("supervisor.panel.style") +local pdg_entry = require("supervisor.panel.components.pdg_entry") +local rtu_entry = require("supervisor.panel.components.rtu_entry") + local core = require("graphics.core") local Div = require("graphics.elements.div") @@ -45,7 +49,7 @@ local function init(panel) local system = Div{parent=main_page,width=14,height=17,x=2,y=2} - local on = LED{parent=system,label="POWER",colors=cpair(colors.green,colors.red)} + local on = LED{parent=system,label="STATUS",colors=cpair(colors.green,colors.red)} local heartbeat = LED{parent=system,label="HEARTBEAT",colors=cpair(colors.green,colors.green_off)} on.update(true) system.line_break() @@ -107,14 +111,8 @@ local function init(panel) -- rtu page local rtu_page = Div{parent=page_div,x=1,y=1,hidden=true} - local rtu_list = ListBox{parent=rtu_page,x=2,y=2,height=15,width=49,scroll_height=1000,item_pad=1,fg_bg=cpair(colors.black,colors.white)} - - local item_1 = Div{parent=rtu_list,height=3,fg_bg=cpair(colors.black,colors.red),hidden=true} - local item_2 = Div{parent=rtu_list,height=3,fg_bg=cpair(colors.black,colors.orange),hidden=true} - local item_3 = Div{parent=rtu_list,height=3,fg_bg=cpair(colors.black,colors.yellow),hidden=true} - local item_4 = Div{parent=rtu_list,height=3,fg_bg=cpair(colors.black,colors.green),hidden=true} - local item_5 = Div{parent=rtu_list,height=3,fg_bg=cpair(colors.black,colors.blue),hidden=true} - local item_6 = Div{parent=rtu_list,height=3,fg_bg=cpair(colors.black,colors.purple),hidden=true} + local rtu_list = ListBox{parent=rtu_page,x=1,y=1,height=17,width=51,scroll_height=1000,fg_bg=cpair(colors.black,colors.ivory),nav_fg_bg=cpair(colors.gray,colors.lightGray),nav_active=cpair(colors.black,colors.gray)} + local _ = Div{parent=rtu_list,height=1,hidden=true} -- padding -- coordinator page @@ -138,10 +136,13 @@ local function init(panel) crd_rtt.register(databus.ps, "crd_rtt", crd_rtt.update) crd_rtt.register(databus.ps, "crd_rtt_color", crd_rtt.recolor) - -- pocket page + -- pocket diagnostics page local pkt_page = Div{parent=page_div,x=1,y=1,hidden=true} - local pkt_box = Div{parent=pkt_page,x=2,y=2,width=49} + local pdg_list = ListBox{parent=pkt_page,x=1,y=1,height=17,width=51,scroll_height=1000,fg_bg=cpair(colors.black,colors.ivory),nav_fg_bg=cpair(colors.gray,colors.lightGray),nav_active=cpair(colors.black,colors.gray)} + local _ = Div{parent=pdg_list,height=1,hidden=true} -- padding + + -- assemble page panes local panes = { main_page, plc_page, rtu_page, crd_page, pkt_page } @@ -156,6 +157,9 @@ local function init(panel) } TabBar{parent=panel,y=2,tabs=tabs,min_width=9,callback=page_pane.set_value,fg_bg=cpair(colors.black,colors.white)} + + -- link RTU/PDG list management to PGI + pgi.link_elements(rtu_list, rtu_entry, pdg_list, pdg_entry) end return init diff --git a/supervisor/panel/pgi.lua b/supervisor/panel/pgi.lua new file mode 100644 index 0000000..4126dee --- /dev/null +++ b/supervisor/panel/pgi.lua @@ -0,0 +1,85 @@ +-- +-- Protected Graphics Interface +-- + +local log = require("scada-common.log") +local util = require("scada-common.util") + +local pgi = {} + +local data = { + rtu_list = nil, ---@type nil|graphics_element + pdg_list = nil, ---@type nil|graphics_element + rtu_entry = nil, ---@type function + pdg_entry = nil, ---@type function + -- session entries + s_entries = { rtu = {}, pdg = {} } +} + +-- link list boxes +---@param rtu_list graphics_element RTU list element +---@param rtu_entry function RTU entry constructor +---@param pdg_list graphics_element pocket diagnostics list element +---@param pdg_entry function pocket diagnostics entry constructor +function pgi.link_elements(rtu_list, rtu_entry, pdg_list, pdg_entry) + data.rtu_list = rtu_list + data.pdg_list = pdg_list + data.rtu_entry = rtu_entry + data.pdg_entry = pdg_entry +end + +-- add an RTU entry to the RTU list +---@param session_id integer RTU session +function pgi.create_rtu_entry(session_id) + if data.rtu_list ~= nil and data.rtu_entry ~= nil then + local success, result = pcall(data.rtu_entry, data.rtu_list, session_id) + + if success then + data.s_entries.rtu[session_id] = result + else + log.error(util.c("PGI: failed to create RTU entry (", result, ")"), true) + end + end +end + +-- delete an RTU entry from the RTU list +---@param session_id integer RTU session +function pgi.delete_rtu_entry(session_id) + if data.s_entries.rtu[session_id] ~= nil then + local success, result = pcall(data.s_entries.rtu[session_id].delete) + data.s_entries.rtu[session_id] = nil + + if not success then + log.error(util.c("PGI: failed to delete RTU entry (", result, ")"), true) + end + end +end + +-- add a PDG entry to the PDG list +---@param session_id integer pocket diagnostics session +function pgi.create_pdg_entry(session_id) + if data.pdg_list ~= nil and data.pdg_entry ~= nil then + local success, result = pcall(data.pdg_entry, data.pdg_list, session_id) + + if success then + data.s_entries.pdg[session_id] = result + else + log.error(util.c("PGI: failed to create PDG entry (", result, ")"), true) + end + end +end + +-- delete a PDG entry from the PDG list +---@param session_id integer pocket diagnostics session +function pgi.delete_pdg_entry(session_id) + if data.s_entries.pdg[session_id] ~= nil then + local success, result = pcall(data.s_entries.pdg[session_id].delete) + data.s_entries.pdg[session_id] = nil + + if not success then + log.error(util.c("PGI: failed to delete PDG entry (", result, ")"), true) + end + end +end + +return pgi diff --git a/supervisor/session/pocket.lua b/supervisor/session/pocket.lua index 5693e02..175a235 100644 --- a/supervisor/session/pocket.lua +++ b/supervisor/session/pocket.lua @@ -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 diff --git a/supervisor/session/rtu.lua b/supervisor/session/rtu.lua index a38e240..40b47ed 100644 --- a/supervisor/session/rtu.lua +++ b/supervisor/session/rtu.lua @@ -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 diff --git a/supervisor/session/svsessions.lua b/supervisor/session/svsessions.lua index 8c56419..ecd8928 100644 --- a/supervisor/session/svsessions.lua +++ b/supervisor/session/svsessions.lua @@ -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 diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 6e2dd95..cdae63e 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -8,6 +8,7 @@ local crash = require("scada-common.crash") local comms = require("scada-common.comms") local log = require("scada-common.log") local ppm = require("scada-common.ppm") +local tcd = require("scada-common.tcallbackdsp") local util = require("scada-common.util") local core = require("graphics.core") @@ -19,7 +20,7 @@ local supervisor = require("supervisor.supervisor") local svsessions = require("supervisor.session.svsessions") -local SUPERVISOR_VERSION = "v0.16.5" +local SUPERVISOR_VERSION = "v0.16.6" local println = util.println local println_ts = util.println_ts @@ -169,6 +170,9 @@ local function main() elseif event == "timer" then -- a non-clock timer event, check watchdogs svsessions.check_all_watchdogs(param1) + + -- notify timer callback dispatcher + tcd.handle(param1) elseif event == "modem_message" then -- got a packet local packet = superv_comms.parse_packet(param1, param2, param3, param4, param5) diff --git a/supervisor/supervisor.lua b/supervisor/supervisor.lua index 4fba85c..0424b53 100644 --- a/supervisor/supervisor.lua +++ b/supervisor/supervisor.lua @@ -305,9 +305,9 @@ function supervisor.comms(_version, num_reactors, cooling_conf, modem, dev_liste end elseif dev_type == DEVICE_TYPE.PKT then -- this is an attempt to establish a new pocket diagnostic session - local s_id = svsessions.establish_diag_session(l_port, r_port, firmware_v) + local s_id = svsessions.establish_pdg_session(l_port, r_port, firmware_v) - println(util.c("PKT (", firmware_v, ") [:", r_port, "] \xbb connected")) + println(util.c("PDG (", firmware_v, ") [:", r_port, "] \xbb connected")) log.info(util.c("SVCTL_ESTABLISH: pocket (", firmware_v, ") [:", r_port, "] connected with session ID ", s_id)) _send_svctl_establish(next_seq_id, r_port, { ESTABLISH_ACK.ALLOW })