mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
#229 element PSIL register/deletion, changes for RTU to use new PSIL register
This commit is contained in:
parent
36bd2c5e08
commit
b2115fd077
@ -3,6 +3,7 @@
|
||||
--
|
||||
|
||||
local core = require("graphics.core")
|
||||
local log = require("scada-common.log")
|
||||
|
||||
local element = {}
|
||||
|
||||
@ -46,12 +47,18 @@ local element = {}
|
||||
---|colormap_args
|
||||
---|displaybox_args
|
||||
---|div_args
|
||||
---|listbox_args
|
||||
---|multipane_args
|
||||
---|pipenet_args
|
||||
---|rectangle_args
|
||||
---|textbox_args
|
||||
---|tiling_args
|
||||
|
||||
---@class element_subscription
|
||||
---@field ps psil ps used
|
||||
---@field key string data key
|
||||
---@field func function callback
|
||||
|
||||
-- a base graphics element, should not be created on its own
|
||||
---@nodiscard
|
||||
---@param args graphics_args arguments
|
||||
@ -66,6 +73,7 @@ function element.new(args)
|
||||
bounds = { x1 = 1, y1 = 1, x2 = 1, y2 = 1 }, ---@class element_bounds
|
||||
next_y = 1,
|
||||
children = {},
|
||||
subscriptions = {},
|
||||
mt = {}
|
||||
}
|
||||
|
||||
@ -183,6 +191,17 @@ function element.new(args)
|
||||
-- luacheck: push ignore
|
||||
---@diagnostic disable: unused-local, unused-vararg
|
||||
|
||||
-- dynamically insert a child element
|
||||
---@param id string|integer element identifier
|
||||
---@param elem graphics_element element
|
||||
function protected.insert(id, elem)
|
||||
end
|
||||
|
||||
-- dynamically remove a child element
|
||||
---@param id string|integer element identifier
|
||||
function protected.remove(id)
|
||||
end
|
||||
|
||||
-- handle a mouse event
|
||||
---@param event mouse_interaction mouse interaction event
|
||||
function protected.handle_mouse(event)
|
||||
@ -281,7 +300,25 @@ function element.new(args)
|
||||
---@nodiscard
|
||||
function public.window() return protected.window end
|
||||
|
||||
-- CHILD ELEMENTS --
|
||||
-- delete this element (hide and unsubscribe from PSIL)
|
||||
function public.delete()
|
||||
-- hide + stop animations
|
||||
public.hide()
|
||||
|
||||
-- unsubscribe from PSIL
|
||||
for i = 1, #self.subscriptions do
|
||||
local s = self.subscriptions[i] ---@type element_subscription
|
||||
s.ps.unsubscribe(s.key, s.func)
|
||||
end
|
||||
|
||||
-- delete all children
|
||||
for k, v in pairs(self.children) do
|
||||
v.delete()
|
||||
self.children[k] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- ELEMENT TREE --
|
||||
|
||||
-- add a child element
|
||||
---@nodiscard
|
||||
@ -311,12 +348,18 @@ function element.new(args)
|
||||
|
||||
-- get a child element
|
||||
---@nodiscard
|
||||
---@param id element_id
|
||||
---@return graphics_element
|
||||
function public.get_child(key) return self.children[key] end
|
||||
function public.get_child(id) return self.children[id] end
|
||||
|
||||
-- remove child
|
||||
---@param key string|integer
|
||||
function public.remove(key) self.children[key] = nil end
|
||||
-- remove a child element
|
||||
---@param id element_id
|
||||
function public.remove(id)
|
||||
if self.children[id] ~= nil then
|
||||
self.children[id].delete()
|
||||
self.children[id] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- attempt to get a child element by ID (does not include this element itself)
|
||||
---@nodiscard
|
||||
@ -335,6 +378,25 @@ function element.new(args)
|
||||
return nil
|
||||
end
|
||||
|
||||
-- DYNAMIC CHILD ELEMENTS --
|
||||
|
||||
-- insert an element as a contained child<br>
|
||||
-- this is intended to be used dynamically, and depends on the target element type.<br>
|
||||
-- not all elements support dynamic children.
|
||||
---@param id string|integer element identifier
|
||||
---@param elem graphics_element element
|
||||
function public.insert_element(id, elem)
|
||||
protected.insert(id, elem)
|
||||
end
|
||||
|
||||
-- remove an element from contained children<br>
|
||||
-- this is intended to be used dynamically, and depends on the target element type.<br>
|
||||
-- not all elements support dynamic children.
|
||||
---@param id string|integer element identifier
|
||||
function public.remove_element(id)
|
||||
protected.remove(id)
|
||||
end
|
||||
|
||||
-- AUTO-PLACEMENT --
|
||||
|
||||
-- skip a line for automatically placed elements
|
||||
@ -460,6 +522,16 @@ function element.new(args)
|
||||
protected.response_callback(result)
|
||||
end
|
||||
|
||||
-- register a callback with a PSIL, allowing for automatic unregister on delete<br>
|
||||
-- do not use graphics elements directly with PSIL subscribe()
|
||||
---@param ps psil PSIL to subscribe to
|
||||
---@param key string key to subscribe to
|
||||
---@param func function function to link
|
||||
function public.register(ps, key, func)
|
||||
table.insert(self.subscriptions, { ps = ps, key = key, func = func })
|
||||
ps.subscribe(key, func)
|
||||
end
|
||||
|
||||
-- VISIBILITY --
|
||||
|
||||
-- show the element
|
||||
|
@ -7,9 +7,8 @@ local util = require("scada-common.util")
|
||||
|
||||
local databus = {}
|
||||
|
||||
local dbus_iface = {
|
||||
ps = psil.create()
|
||||
}
|
||||
-- databus PSIL
|
||||
databus.ps = psil.create()
|
||||
|
||||
---@enum RTU_UNIT_HW_STATE
|
||||
local RTU_UNIT_HW_STATE = {
|
||||
@ -22,54 +21,54 @@ local RTU_UNIT_HW_STATE = {
|
||||
databus.RTU_UNIT_HW_STATE = RTU_UNIT_HW_STATE
|
||||
|
||||
-- call to toggle heartbeat signal
|
||||
function databus.heartbeat() dbus_iface.ps.toggle("heartbeat") end
|
||||
function databus.heartbeat() databus.ps.toggle("heartbeat") end
|
||||
|
||||
-- transmit firmware versions across the bus
|
||||
---@param rtu_v string RTU version
|
||||
---@param comms_v string comms version
|
||||
function databus.tx_versions(rtu_v, comms_v)
|
||||
dbus_iface.ps.publish("version", rtu_v)
|
||||
dbus_iface.ps.publish("comms_version", comms_v)
|
||||
databus.ps.publish("version", rtu_v)
|
||||
databus.ps.publish("comms_version", comms_v)
|
||||
end
|
||||
|
||||
-- transmit hardware status for modem connection state
|
||||
---@param has_modem boolean
|
||||
function databus.tx_hw_modem(has_modem)
|
||||
dbus_iface.ps.publish("has_modem", has_modem)
|
||||
databus.ps.publish("has_modem", has_modem)
|
||||
end
|
||||
|
||||
-- transmit unit hardware type across the bus
|
||||
---@param uid integer unit ID
|
||||
---@param type RTU_UNIT_TYPE
|
||||
function databus.tx_unit_hw_type(uid, type)
|
||||
dbus_iface.ps.publish("unit_type_" .. uid, type)
|
||||
databus.ps.publish("unit_type_" .. uid, type)
|
||||
end
|
||||
|
||||
-- transmit unit hardware status across the bus
|
||||
---@param uid integer unit ID
|
||||
---@param status RTU_UNIT_HW_STATE
|
||||
function databus.tx_unit_hw_status(uid, status)
|
||||
dbus_iface.ps.publish("unit_hw_" .. uid, status)
|
||||
databus.ps.publish("unit_hw_" .. uid, status)
|
||||
end
|
||||
|
||||
-- transmit thread (routine) statuses
|
||||
---@param thread string thread name
|
||||
---@param ok boolean thread state
|
||||
function databus.tx_rt_status(thread, ok)
|
||||
dbus_iface.ps.publish(util.c("routine__", thread), ok)
|
||||
databus.ps.publish(util.c("routine__", thread), ok)
|
||||
end
|
||||
|
||||
-- transmit supervisor link state across the bus
|
||||
---@param state integer
|
||||
function databus.tx_link_state(state)
|
||||
dbus_iface.ps.publish("link_state", state)
|
||||
databus.ps.publish("link_state", state)
|
||||
end
|
||||
|
||||
-- link a function to receive data from the bus
|
||||
---@param field string field name
|
||||
---@param func function function to link
|
||||
function databus.rx_field(field, func)
|
||||
dbus_iface.ps.subscribe(field, func)
|
||||
databus.ps.subscribe(field, func)
|
||||
end
|
||||
|
||||
return databus
|
||||
|
@ -49,22 +49,22 @@ local function init(panel, units)
|
||||
on.update(true)
|
||||
system.line_break()
|
||||
|
||||
databus.rx_field("heartbeat", heartbeat.update)
|
||||
heartbeat.register(databus.ps, "heartbeat", heartbeat.update)
|
||||
|
||||
local modem = LED{parent=system,label="MODEM",colors=cpair(colors.green,colors.green_off)}
|
||||
local network = RGBLED{parent=system,label="NETWORK",colors={colors.green,colors.red,colors.orange,colors.yellow,colors.gray}}
|
||||
network.update(5)
|
||||
system.line_break()
|
||||
|
||||
databus.rx_field("has_modem", modem.update)
|
||||
databus.rx_field("link_state", network.update)
|
||||
modem.register(databus.ps, "has_modem", modem.update)
|
||||
network.register(databus.ps, "link_state", network.update)
|
||||
|
||||
local rt_main = LED{parent=system,label="RT MAIN",colors=cpair(colors.green,colors.green_off)}
|
||||
local rt_comm = LED{parent=system,label="RT COMMS",colors=cpair(colors.green,colors.green_off)}
|
||||
system.line_break()
|
||||
|
||||
databus.rx_field("routine__main", rt_main.update)
|
||||
databus.rx_field("routine__comms", rt_comm.update)
|
||||
rt_main.register(databus.ps, "routine__main", rt_main.update)
|
||||
rt_comm.register(databus.ps, "routine__comms", rt_comm.update)
|
||||
|
||||
--
|
||||
-- about label
|
||||
@ -74,8 +74,8 @@ local function init(panel, units)
|
||||
local fw_v = TextBox{parent=about,x=1,y=1,text="FW: v00.00.00",alignment=TEXT_ALIGN.LEFT,height=1}
|
||||
local comms_v = TextBox{parent=about,x=1,y=2,text="NT: v00.00.00",alignment=TEXT_ALIGN.LEFT,height=1}
|
||||
|
||||
databus.rx_field("version", function (version) fw_v.set_value(util.c("FW: ", version)) end)
|
||||
databus.rx_field("comms_version", function (version) comms_v.set_value(util.c("NT: v", version)) end)
|
||||
fw_v.register(databus.ps, "version", function (version) fw_v.set_value(util.c("FW: ", version)) end)
|
||||
comms_v.register(databus.ps, "comms_version", function (version) comms_v.set_value(util.c("NT: v", version)) end)
|
||||
|
||||
--
|
||||
-- unit status list
|
||||
@ -90,7 +90,7 @@ local function init(panel, units)
|
||||
for i = 1, list_length do
|
||||
TextBox{parent=threads,x=1,y=i,text=util.sprintf("%02d",i),height=1}
|
||||
local rt_unit = LED{parent=threads,x=4,y=i,label="RT",colors=cpair(colors.green,colors.green_off)}
|
||||
databus.rx_field("routine__unit_" .. i, rt_unit.update)
|
||||
rt_unit.register(databus.ps, "routine__unit_" .. i, rt_unit.update)
|
||||
end
|
||||
|
||||
local unit_hw_statuses = Div{parent=panel,height=18,x=25,y=3}
|
||||
@ -102,13 +102,13 @@ local function init(panel, units)
|
||||
-- hardware status
|
||||
local unit_hw = RGBLED{parent=unit_hw_statuses,y=i,label="",colors={colors.red,colors.orange,colors.yellow,colors.green}}
|
||||
|
||||
databus.rx_field("unit_hw_" .. i, unit_hw.update)
|
||||
unit_hw.register(databus.ps, "unit_hw_" .. i, unit_hw.update)
|
||||
|
||||
-- unit name identifier (type + index)
|
||||
local name = util.c(UNIT_TYPE_LABELS[unit.type + 1], " ", unit.index)
|
||||
local name_box = TextBox{parent=unit_hw_statuses,y=i,x=3,text=name,height=1}
|
||||
|
||||
databus.rx_field("unit_type_" .. i, function (t)
|
||||
name_box.register(databus.ps, "unit_type_" .. i, function (t)
|
||||
name_box.set_value(util.c(UNIT_TYPE_LABELS[t + 1], " ", unit.index))
|
||||
end)
|
||||
|
||||
|
@ -45,10 +45,8 @@ function renderer.close_ui()
|
||||
-- stop blinking indicators
|
||||
flasher.clear()
|
||||
|
||||
-- hide to stop animation callbacks
|
||||
ui.display.hide()
|
||||
|
||||
-- clear root UI elements
|
||||
-- delete element tree
|
||||
ui.display.delete()
|
||||
ui.display = nil
|
||||
|
||||
-- restore colors
|
||||
|
@ -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.1.0"
|
||||
local RTU_VERSION = "v1.2.0"
|
||||
|
||||
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
|
||||
local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE
|
||||
|
@ -2,6 +2,8 @@
|
||||
-- Publisher-Subscriber Interconnect Layer
|
||||
--
|
||||
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local psil = {}
|
||||
|
||||
-- instantiate a new PSI layer
|
||||
@ -36,6 +38,15 @@ function psil.create()
|
||||
table.insert(self.ic[key].subscribers, { notify = func })
|
||||
end
|
||||
|
||||
-- unsubscribe a function from a given key
|
||||
---@param key string data key
|
||||
---@param func function function to unsubscribe
|
||||
function public.unsubscribe(key, func)
|
||||
if self.ic[key] ~= nil then
|
||||
util.filter_table(self.ic[key].subscribers, function (s) return s.notify ~= func end)
|
||||
end
|
||||
end
|
||||
|
||||
-- publish data to a given key, passing it to all subscribers if it has changed
|
||||
---@param key string data key
|
||||
---@param value any data value
|
||||
@ -64,6 +75,9 @@ function psil.create()
|
||||
end
|
||||
end
|
||||
|
||||
-- clear the contents of the interconnect
|
||||
function public.purge() self.ic = nil end
|
||||
|
||||
return public
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user