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:
@ -3,6 +3,7 @@
|
|||||||
--
|
--
|
||||||
|
|
||||||
local core = require("graphics.core")
|
local core = require("graphics.core")
|
||||||
|
local log = require("scada-common.log")
|
||||||
|
|
||||||
local element = {}
|
local element = {}
|
||||||
|
|
||||||
@ -46,12 +47,18 @@ local element = {}
|
|||||||
---|colormap_args
|
---|colormap_args
|
||||||
---|displaybox_args
|
---|displaybox_args
|
||||||
---|div_args
|
---|div_args
|
||||||
|
---|listbox_args
|
||||||
---|multipane_args
|
---|multipane_args
|
||||||
---|pipenet_args
|
---|pipenet_args
|
||||||
---|rectangle_args
|
---|rectangle_args
|
||||||
---|textbox_args
|
---|textbox_args
|
||||||
---|tiling_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
|
-- a base graphics element, should not be created on its own
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param args graphics_args arguments
|
---@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
|
bounds = { x1 = 1, y1 = 1, x2 = 1, y2 = 1 }, ---@class element_bounds
|
||||||
next_y = 1,
|
next_y = 1,
|
||||||
children = {},
|
children = {},
|
||||||
|
subscriptions = {},
|
||||||
mt = {}
|
mt = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,6 +191,17 @@ function element.new(args)
|
|||||||
-- luacheck: push ignore
|
-- luacheck: push ignore
|
||||||
---@diagnostic disable: unused-local, unused-vararg
|
---@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
|
-- handle a mouse event
|
||||||
---@param event mouse_interaction mouse interaction event
|
---@param event mouse_interaction mouse interaction event
|
||||||
function protected.handle_mouse(event)
|
function protected.handle_mouse(event)
|
||||||
@ -281,7 +300,25 @@ function element.new(args)
|
|||||||
---@nodiscard
|
---@nodiscard
|
||||||
function public.window() return protected.window end
|
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
|
-- add a child element
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
@ -311,12 +348,18 @@ function element.new(args)
|
|||||||
|
|
||||||
-- get a child element
|
-- get a child element
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
|
---@param id element_id
|
||||||
---@return graphics_element
|
---@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
|
-- remove a child element
|
||||||
---@param key string|integer
|
---@param id element_id
|
||||||
function public.remove(key) self.children[key] = nil end
|
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)
|
-- attempt to get a child element by ID (does not include this element itself)
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
@ -335,6 +378,25 @@ function element.new(args)
|
|||||||
return nil
|
return nil
|
||||||
end
|
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 --
|
-- AUTO-PLACEMENT --
|
||||||
|
|
||||||
-- skip a line for automatically placed elements
|
-- skip a line for automatically placed elements
|
||||||
@ -460,6 +522,16 @@ function element.new(args)
|
|||||||
protected.response_callback(result)
|
protected.response_callback(result)
|
||||||
end
|
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 --
|
-- VISIBILITY --
|
||||||
|
|
||||||
-- show the element
|
-- show the element
|
||||||
|
@ -7,9 +7,8 @@ local util = require("scada-common.util")
|
|||||||
|
|
||||||
local databus = {}
|
local databus = {}
|
||||||
|
|
||||||
local dbus_iface = {
|
-- databus PSIL
|
||||||
ps = psil.create()
|
databus.ps = psil.create()
|
||||||
}
|
|
||||||
|
|
||||||
---@enum RTU_UNIT_HW_STATE
|
---@enum RTU_UNIT_HW_STATE
|
||||||
local 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
|
databus.RTU_UNIT_HW_STATE = RTU_UNIT_HW_STATE
|
||||||
|
|
||||||
-- call to toggle heartbeat signal
|
-- 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
|
-- transmit firmware versions across the bus
|
||||||
---@param rtu_v string RTU version
|
---@param rtu_v string RTU version
|
||||||
---@param comms_v string comms version
|
---@param comms_v string comms version
|
||||||
function databus.tx_versions(rtu_v, comms_v)
|
function databus.tx_versions(rtu_v, comms_v)
|
||||||
dbus_iface.ps.publish("version", rtu_v)
|
databus.ps.publish("version", rtu_v)
|
||||||
dbus_iface.ps.publish("comms_version", comms_v)
|
databus.ps.publish("comms_version", comms_v)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- transmit hardware status for modem connection state
|
-- transmit hardware status for modem connection state
|
||||||
---@param has_modem boolean
|
---@param has_modem boolean
|
||||||
function databus.tx_hw_modem(has_modem)
|
function databus.tx_hw_modem(has_modem)
|
||||||
dbus_iface.ps.publish("has_modem", has_modem)
|
databus.ps.publish("has_modem", has_modem)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- transmit unit hardware type across the bus
|
-- transmit unit hardware type across the bus
|
||||||
---@param uid integer unit ID
|
---@param uid integer unit ID
|
||||||
---@param type RTU_UNIT_TYPE
|
---@param type RTU_UNIT_TYPE
|
||||||
function databus.tx_unit_hw_type(uid, 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
|
end
|
||||||
|
|
||||||
-- transmit unit hardware status across the bus
|
-- transmit unit hardware status across the bus
|
||||||
---@param uid integer unit ID
|
---@param uid integer unit ID
|
||||||
---@param status RTU_UNIT_HW_STATE
|
---@param status RTU_UNIT_HW_STATE
|
||||||
function databus.tx_unit_hw_status(uid, status)
|
function databus.tx_unit_hw_status(uid, status)
|
||||||
dbus_iface.ps.publish("unit_hw_" .. uid, status)
|
databus.ps.publish("unit_hw_" .. uid, status)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- transmit thread (routine) statuses
|
-- transmit thread (routine) statuses
|
||||||
---@param thread string thread name
|
---@param thread string thread name
|
||||||
---@param ok boolean thread state
|
---@param ok boolean thread state
|
||||||
function databus.tx_rt_status(thread, ok)
|
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
|
end
|
||||||
|
|
||||||
-- transmit supervisor link state across the bus
|
-- transmit supervisor link state across the bus
|
||||||
---@param state integer
|
---@param state integer
|
||||||
function databus.tx_link_state(state)
|
function databus.tx_link_state(state)
|
||||||
dbus_iface.ps.publish("link_state", state)
|
databus.ps.publish("link_state", state)
|
||||||
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
|
||||||
function databus.rx_field(field, func)
|
function databus.rx_field(field, func)
|
||||||
dbus_iface.ps.subscribe(field, func)
|
databus.ps.subscribe(field, func)
|
||||||
end
|
end
|
||||||
|
|
||||||
return databus
|
return databus
|
||||||
|
@ -49,22 +49,22 @@ local function init(panel, units)
|
|||||||
on.update(true)
|
on.update(true)
|
||||||
system.line_break()
|
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 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}}
|
local network = RGBLED{parent=system,label="NETWORK",colors={colors.green,colors.red,colors.orange,colors.yellow,colors.gray}}
|
||||||
network.update(5)
|
network.update(5)
|
||||||
system.line_break()
|
system.line_break()
|
||||||
|
|
||||||
databus.rx_field("has_modem", modem.update)
|
modem.register(databus.ps, "has_modem", modem.update)
|
||||||
databus.rx_field("link_state", network.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_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)}
|
local rt_comm = LED{parent=system,label="RT COMMS",colors=cpair(colors.green,colors.green_off)}
|
||||||
system.line_break()
|
system.line_break()
|
||||||
|
|
||||||
databus.rx_field("routine__main", rt_main.update)
|
rt_main.register(databus.ps, "routine__main", rt_main.update)
|
||||||
databus.rx_field("routine__comms", rt_comm.update)
|
rt_comm.register(databus.ps, "routine__comms", rt_comm.update)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- about label
|
-- 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 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}
|
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)
|
fw_v.register(databus.ps, "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)
|
comms_v.register(databus.ps, "comms_version", function (version) comms_v.set_value(util.c("NT: v", version)) end)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- unit status list
|
-- unit status list
|
||||||
@ -90,7 +90,7 @@ local function init(panel, units)
|
|||||||
for i = 1, list_length do
|
for i = 1, list_length do
|
||||||
TextBox{parent=threads,x=1,y=i,text=util.sprintf("%02d",i),height=1}
|
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)}
|
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
|
end
|
||||||
|
|
||||||
local unit_hw_statuses = Div{parent=panel,height=18,x=25,y=3}
|
local unit_hw_statuses = Div{parent=panel,height=18,x=25,y=3}
|
||||||
@ -102,13 +102,13 @@ local function init(panel, units)
|
|||||||
-- hardware status
|
-- hardware status
|
||||||
local unit_hw = RGBLED{parent=unit_hw_statuses,y=i,label="",colors={colors.red,colors.orange,colors.yellow,colors.green}}
|
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)
|
-- unit name identifier (type + index)
|
||||||
local name = util.c(UNIT_TYPE_LABELS[unit.type + 1], " ", unit.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}
|
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))
|
name_box.set_value(util.c(UNIT_TYPE_LABELS[t + 1], " ", unit.index))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -45,10 +45,8 @@ function renderer.close_ui()
|
|||||||
-- stop blinking indicators
|
-- stop blinking indicators
|
||||||
flasher.clear()
|
flasher.clear()
|
||||||
|
|
||||||
-- hide to stop animation callbacks
|
-- delete element tree
|
||||||
ui.display.hide()
|
ui.display.delete()
|
||||||
|
|
||||||
-- clear root UI elements
|
|
||||||
ui.display = nil
|
ui.display = nil
|
||||||
|
|
||||||
-- restore colors
|
-- restore colors
|
||||||
|
@ -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.1.0"
|
local RTU_VERSION = "v1.2.0"
|
||||||
|
|
||||||
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
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
-- Publisher-Subscriber Interconnect Layer
|
-- Publisher-Subscriber Interconnect Layer
|
||||||
--
|
--
|
||||||
|
|
||||||
|
local util = require("scada-common.util")
|
||||||
|
|
||||||
local psil = {}
|
local psil = {}
|
||||||
|
|
||||||
-- instantiate a new PSI layer
|
-- instantiate a new PSI layer
|
||||||
@ -36,6 +38,15 @@ function psil.create()
|
|||||||
table.insert(self.ic[key].subscribers, { notify = func })
|
table.insert(self.ic[key].subscribers, { notify = func })
|
||||||
end
|
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
|
-- publish data to a given key, passing it to all subscribers if it has changed
|
||||||
---@param key string data key
|
---@param key string data key
|
||||||
---@param value any data value
|
---@param value any data value
|
||||||
@ -64,6 +75,9 @@ function psil.create()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- clear the contents of the interconnect
|
||||||
|
function public.purge() self.ic = nil end
|
||||||
|
|
||||||
return public
|
return public
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user