mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
#184 RTU and pocket lists on supervisor front panel, element delete() bugfix
This commit is contained in:
parent
153a83e569
commit
69df5edbeb
@ -20,7 +20,7 @@ local sounder = require("coordinator.sounder")
|
|||||||
|
|
||||||
local apisessions = require("coordinator.session.apisessions")
|
local apisessions = require("coordinator.session.apisessions")
|
||||||
|
|
||||||
local COORDINATOR_VERSION = "v0.15.5"
|
local COORDINATOR_VERSION = "v0.15.6"
|
||||||
|
|
||||||
local println = util.println
|
local println = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
|
@ -323,7 +323,10 @@ function element.new(args)
|
|||||||
protected.children[k] = nil
|
protected.children[k] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
args.parent.__remove_child(self.id)
|
if args.parent ~= nil then
|
||||||
|
-- remove self from parent
|
||||||
|
args.parent.__remove_child(self.id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ELEMENT TREE --
|
-- ELEMENT TREE --
|
||||||
|
@ -17,7 +17,7 @@ local coreio = require("pocket.coreio")
|
|||||||
local pocket = require("pocket.pocket")
|
local pocket = require("pocket.pocket")
|
||||||
local renderer = require("pocket.renderer")
|
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 = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
|
@ -18,7 +18,7 @@ local plc = require("reactor-plc.plc")
|
|||||||
local renderer = require("reactor-plc.renderer")
|
local renderer = require("reactor-plc.renderer")
|
||||||
local threads = require("reactor-plc.threads")
|
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 = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
|
@ -28,7 +28,7 @@ local sna_rtu = require("rtu.dev.sna_rtu")
|
|||||||
local sps_rtu = require("rtu.dev.sps_rtu")
|
local sps_rtu = require("rtu.dev.sps_rtu")
|
||||||
local turbinev_rtu = require("rtu.dev.turbinev_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_TYPE = types.RTU_UNIT_TYPE
|
||||||
local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE
|
local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE
|
||||||
|
@ -4,15 +4,13 @@
|
|||||||
|
|
||||||
local psil = require("scada-common.psil")
|
local psil = require("scada-common.psil")
|
||||||
|
|
||||||
|
local pgi = require("supervisor.panel.pgi")
|
||||||
|
|
||||||
local databus = {}
|
local databus = {}
|
||||||
|
|
||||||
-- databus PSIL
|
-- databus PSIL
|
||||||
databus.ps = psil.create()
|
databus.ps = psil.create()
|
||||||
|
|
||||||
local dbus_iface = {
|
|
||||||
session_entries = { rtu = {}, diag = {} }
|
|
||||||
}
|
|
||||||
|
|
||||||
-- call to toggle heartbeat signal
|
-- call to toggle heartbeat signal
|
||||||
function databus.heartbeat() databus.ps.toggle("heartbeat") end
|
function databus.heartbeat() databus.ps.toggle("heartbeat") end
|
||||||
|
|
||||||
@ -65,6 +63,44 @@ function databus.tx_plc_rtt(reactor_id, rtt)
|
|||||||
end
|
end
|
||||||
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
|
-- transmit coordinator firmware version and session connection state
|
||||||
---@param fw string firmware version
|
---@param fw string firmware version
|
||||||
---@param channel integer coordinator remote port
|
---@param channel integer coordinator remote port
|
||||||
@ -97,6 +133,37 @@ function databus.tx_crd_rtt(rtt)
|
|||||||
end
|
end
|
||||||
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
|
-- link a function to receive data from the bus
|
||||||
---@param field string field name
|
---@param field string field name
|
||||||
---@param func function function to link
|
---@param func function function to link
|
||||||
|
48
supervisor/panel/components/pdg_entry.lua
Normal file
48
supervisor/panel/components/pdg_entry.lua
Normal file
@ -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
|
52
supervisor/panel/components/rtu_entry.lua
Normal file
52
supervisor/panel/components/rtu_entry.lua
Normal file
@ -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
|
@ -7,8 +7,12 @@ local util = require("scada-common.util")
|
|||||||
local config = require("supervisor.config")
|
local config = require("supervisor.config")
|
||||||
local databus = require("supervisor.databus")
|
local databus = require("supervisor.databus")
|
||||||
|
|
||||||
|
local pgi = require("supervisor.panel.pgi")
|
||||||
local style = require("supervisor.panel.style")
|
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 core = require("graphics.core")
|
||||||
|
|
||||||
local Div = require("graphics.elements.div")
|
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 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)}
|
local heartbeat = LED{parent=system,label="HEARTBEAT",colors=cpair(colors.green,colors.green_off)}
|
||||||
on.update(true)
|
on.update(true)
|
||||||
system.line_break()
|
system.line_break()
|
||||||
@ -107,14 +111,8 @@ local function init(panel)
|
|||||||
-- rtu page
|
-- rtu page
|
||||||
|
|
||||||
local rtu_page = Div{parent=page_div,x=1,y=1,hidden=true}
|
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 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
|
||||||
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}
|
|
||||||
|
|
||||||
-- coordinator page
|
-- 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", crd_rtt.update)
|
||||||
crd_rtt.register(databus.ps, "crd_rtt_color", crd_rtt.recolor)
|
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_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 }
|
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)}
|
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
|
end
|
||||||
|
|
||||||
return init
|
return init
|
||||||
|
85
supervisor/panel/pgi.lua
Normal file
85
supervisor/panel/pgi.lua
Normal file
@ -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
|
@ -1,7 +1,8 @@
|
|||||||
local comms = require("scada-common.comms")
|
local comms = require("scada-common.comms")
|
||||||
local log = require("scada-common.log")
|
local log = require("scada-common.log")
|
||||||
local mqueue = require("scada-common.mqueue")
|
local mqueue = require("scada-common.mqueue")
|
||||||
local util = require("scada-common.util")
|
local util = require("scada-common.util")
|
||||||
|
local databus = require("supervisor.databus")
|
||||||
|
|
||||||
local pocket = {}
|
local pocket = {}
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ local PERIODICS = {
|
|||||||
---@param out_queue mqueue out message queue
|
---@param out_queue mqueue out message queue
|
||||||
---@param timeout number communications timeout
|
---@param timeout number communications timeout
|
||||||
function pocket.new_session(id, in_queue, out_queue, 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 = {
|
local self = {
|
||||||
-- connection properties
|
-- connection properties
|
||||||
@ -56,18 +57,19 @@ function pocket.new_session(id, in_queue, out_queue, timeout)
|
|||||||
acks = {
|
acks = {
|
||||||
},
|
},
|
||||||
-- session database
|
-- session database
|
||||||
---@class diag_db
|
---@class pdg_db
|
||||||
sDB = {
|
sDB = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
---@class diag_session
|
---@class pdg_session
|
||||||
local public = {}
|
local public = {}
|
||||||
|
|
||||||
-- mark this diagnostics session as closed, stop watchdog
|
-- mark this diagnostics session as closed, stop watchdog
|
||||||
local function _close()
|
local function _close()
|
||||||
self.conn_watchdog.cancel()
|
self.conn_watchdog.cancel()
|
||||||
self.connected = false
|
self.connected = false
|
||||||
|
databus.tx_pdg_disconnected(id)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send a SCADA management packet
|
-- send a SCADA management packet
|
||||||
@ -107,16 +109,18 @@ function pocket.new_session(id, in_queue, out_queue, timeout)
|
|||||||
-- keep alive reply
|
-- keep alive reply
|
||||||
if pkt.length == 2 then
|
if pkt.length == 2 then
|
||||||
local srv_start = pkt.data[1]
|
local srv_start = pkt.data[1]
|
||||||
-- local diag_send = pkt.data[2]
|
-- local pdg_send = pkt.data[2]
|
||||||
local srv_now = util.time()
|
local srv_now = util.time()
|
||||||
self.last_rtt = srv_now - srv_start
|
self.last_rtt = srv_now - srv_start
|
||||||
|
|
||||||
if self.last_rtt > 750 then
|
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
|
end
|
||||||
|
|
||||||
-- log.debug(log_header .. "DIAG RTT = " .. self.last_rtt .. "ms")
|
-- log.debug(log_header .. "PDG RTT = " .. self.last_rtt .. "ms")
|
||||||
-- log.debug(log_header .. "DIAG TT = " .. (srv_now - diag_send) .. "ms")
|
-- log.debug(log_header .. "PDG TT = " .. (srv_now - pdg_send) .. "ms")
|
||||||
|
|
||||||
|
databus.tx_pdg_rtt(id, self.last_rtt)
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
|
@ -4,6 +4,8 @@ local mqueue = require("scada-common.mqueue")
|
|||||||
local types = require("scada-common.types")
|
local types = require("scada-common.types")
|
||||||
local util = require("scada-common.util")
|
local util = require("scada-common.util")
|
||||||
|
|
||||||
|
local databus = require("supervisor.databus")
|
||||||
|
|
||||||
local svqtypes = require("supervisor.session.svqtypes")
|
local svqtypes = require("supervisor.session.svqtypes")
|
||||||
|
|
||||||
-- supervisor rtu sessions (svrs)
|
-- 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
|
-- parse the recorded advertisement and create unit sub-sessions
|
||||||
local function _handle_advertisement()
|
local function _handle_advertisement()
|
||||||
|
local unit_count = 0
|
||||||
|
|
||||||
_reset_config()
|
_reset_config()
|
||||||
|
|
||||||
for i = 1, #self.fac_units do
|
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
|
if unit ~= nil then
|
||||||
self.units[i] = unit
|
self.units[i] = unit
|
||||||
|
unit_count = unit_count + 1
|
||||||
elseif u_type ~= RTU_UNIT_TYPE.VIRTUAL then
|
elseif u_type ~= RTU_UNIT_TYPE.VIRTUAL then
|
||||||
_reset_config()
|
_reset_config()
|
||||||
log.error(util.c(log_header, "bad advertisement: error occured while creating a unit (type is ", type_string, ")"))
|
log.error(util.c(log_header, "bad advertisement: error occured while creating a unit (type is ", type_string, ")"))
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
databus.tx_rtu_units(id, unit_count)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- mark this RTU session as closed, stop watchdog
|
-- mark this RTU session as closed, stop watchdog
|
||||||
local function _close()
|
local function _close()
|
||||||
self.conn_watchdog.cancel()
|
self.conn_watchdog.cancel()
|
||||||
self.connected = false
|
self.connected = false
|
||||||
|
databus.tx_rtu_disconnected(id)
|
||||||
|
|
||||||
-- mark all RTU unit sessions as closed so the reactor unit knows
|
-- mark all RTU unit sessions as closed so the reactor unit knows
|
||||||
for _, unit in pairs(self.units) do unit.close() end
|
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 RTT = " .. self.last_rtt .. "ms")
|
||||||
-- log.debug(log_header .. "RTU TT = " .. (srv_now - rtu_send) .. "ms")
|
-- log.debug(log_header .. "RTU TT = " .. (srv_now - rtu_send) .. "ms")
|
||||||
|
|
||||||
|
databus.tx_rtu_rtt(id, self.last_rtt)
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
|
@ -28,7 +28,7 @@ local SESSION_TYPE = {
|
|||||||
RTU_SESSION = 0, -- RTU gateway
|
RTU_SESSION = 0, -- RTU gateway
|
||||||
PLC_SESSION = 1, -- reactor PLC
|
PLC_SESSION = 1, -- reactor PLC
|
||||||
COORD_SESSION = 2, -- coordinator
|
COORD_SESSION = 2, -- coordinator
|
||||||
DIAG_SESSION = 3 -- pocket diagnostics
|
PDG_SESSION = 3 -- pocket diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
svsessions.SESSION_TYPE = SESSION_TYPE
|
svsessions.SESSION_TYPE = SESSION_TYPE
|
||||||
@ -37,11 +37,11 @@ local self = {
|
|||||||
modem = nil, ---@type table|nil
|
modem = nil, ---@type table|nil
|
||||||
num_reactors = 0,
|
num_reactors = 0,
|
||||||
facility = nil, ---@type facility|nil
|
facility = nil, ---@type facility|nil
|
||||||
sessions = { rtu = {}, plc = {}, coord = {}, diag = {} },
|
sessions = { rtu = {}, plc = {}, coord = {}, pdg = {} },
|
||||||
next_ids = { rtu = 0, plc = 0, coord = 0, diag = 0 }
|
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 --
|
-- PRIVATE FUNCTIONS --
|
||||||
|
|
||||||
@ -251,14 +251,14 @@ end
|
|||||||
-- find a coordinator or diagnostic access session by the remote port
|
-- find a coordinator or diagnostic access session by the remote port
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param remote_port integer
|
---@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)
|
function svsessions.find_svctl_session(remote_port)
|
||||||
-- check coordinator sessions
|
-- check coordinator sessions
|
||||||
local session = _find_session(self.sessions.coord, remote_port)
|
local session = _find_session(self.sessions.coord, remote_port)
|
||||||
|
|
||||||
-- check diagnostic sessions
|
-- check diagnostic sessions
|
||||||
if session == nil then session = _find_session(self.sessions.diag, remote_port) end
|
if session == nil then session = _find_session(self.sessions.pdg, remote_port) end
|
||||||
---@cast session coord_session_struct|diag_session_struct|nil
|
---@cast session coord_session_struct|pdg_session_struct|nil
|
||||||
|
|
||||||
return session
|
return session
|
||||||
end
|
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))
|
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)
|
databus.tx_plc_connected(for_reactor, version, remote_port)
|
||||||
|
|
||||||
|
self.next_ids.plc = self.next_ids.plc + 1
|
||||||
|
|
||||||
-- success
|
-- success
|
||||||
return plc_s.instance.get_id()
|
return plc_s.instance.get_id()
|
||||||
else
|
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)
|
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
|
self.next_ids.rtu = self.next_ids.rtu + 1
|
||||||
|
|
||||||
-- success
|
-- 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)
|
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)
|
databus.tx_crd_connected(version, remote_port)
|
||||||
|
|
||||||
|
self.next_ids.coord = self.next_ids.coord + 1
|
||||||
|
|
||||||
-- success
|
-- success
|
||||||
return coord_s.instance.get_id()
|
return coord_s.instance.get_id()
|
||||||
else
|
else
|
||||||
@ -402,9 +404,9 @@ end
|
|||||||
---@param remote_port integer
|
---@param remote_port integer
|
||||||
---@param version string
|
---@param version string
|
||||||
---@return integer|false session_id
|
---@return integer|false session_id
|
||||||
function svsessions.establish_diag_session(local_port, remote_port, version)
|
function svsessions.establish_pdg_session(local_port, remote_port, version)
|
||||||
---@class diag_session_struct
|
---@class pdg_session_struct
|
||||||
local diag_s = {
|
local pdg_s = {
|
||||||
s_type = "pkt",
|
s_type = "pkt",
|
||||||
open = true,
|
open = true,
|
||||||
version = version,
|
version = version,
|
||||||
@ -412,18 +414,20 @@ function svsessions.establish_diag_session(local_port, remote_port, version)
|
|||||||
r_port = remote_port,
|
r_port = remote_port,
|
||||||
in_queue = mqueue.new(),
|
in_queue = mqueue.new(),
|
||||||
out_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)
|
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.diag, diag_s)
|
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
|
-- success
|
||||||
return diag_s.instance.get_id()
|
return pdg_s.instance.get_id()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- attempt to identify which session's watchdog timer fired
|
-- attempt to identify which session's watchdog timer fired
|
||||||
|
@ -8,6 +8,7 @@ local crash = require("scada-common.crash")
|
|||||||
local comms = require("scada-common.comms")
|
local comms = require("scada-common.comms")
|
||||||
local log = require("scada-common.log")
|
local log = require("scada-common.log")
|
||||||
local ppm = require("scada-common.ppm")
|
local ppm = require("scada-common.ppm")
|
||||||
|
local tcd = require("scada-common.tcallbackdsp")
|
||||||
local util = require("scada-common.util")
|
local util = require("scada-common.util")
|
||||||
|
|
||||||
local core = require("graphics.core")
|
local core = require("graphics.core")
|
||||||
@ -19,7 +20,7 @@ local supervisor = require("supervisor.supervisor")
|
|||||||
|
|
||||||
local svsessions = require("supervisor.session.svsessions")
|
local svsessions = require("supervisor.session.svsessions")
|
||||||
|
|
||||||
local SUPERVISOR_VERSION = "v0.16.5"
|
local SUPERVISOR_VERSION = "v0.16.6"
|
||||||
|
|
||||||
local println = util.println
|
local println = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
@ -169,6 +170,9 @@ local function main()
|
|||||||
elseif event == "timer" then
|
elseif event == "timer" then
|
||||||
-- a non-clock timer event, check watchdogs
|
-- a non-clock timer event, check watchdogs
|
||||||
svsessions.check_all_watchdogs(param1)
|
svsessions.check_all_watchdogs(param1)
|
||||||
|
|
||||||
|
-- notify timer callback dispatcher
|
||||||
|
tcd.handle(param1)
|
||||||
elseif event == "modem_message" then
|
elseif event == "modem_message" then
|
||||||
-- got a packet
|
-- got a packet
|
||||||
local packet = superv_comms.parse_packet(param1, param2, param3, param4, param5)
|
local packet = superv_comms.parse_packet(param1, param2, param3, param4, param5)
|
||||||
|
@ -305,9 +305,9 @@ function supervisor.comms(_version, num_reactors, cooling_conf, modem, dev_liste
|
|||||||
end
|
end
|
||||||
elseif dev_type == DEVICE_TYPE.PKT then
|
elseif dev_type == DEVICE_TYPE.PKT then
|
||||||
-- this is an attempt to establish a new pocket diagnostic session
|
-- 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))
|
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 })
|
_send_svctl_establish(next_seq_id, r_port, { ESTABLISH_ACK.ALLOW })
|
||||||
|
Loading…
Reference in New Issue
Block a user