From 81005d3e2c789428d7e340af4ac29f84441caac2 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 29 Apr 2023 23:48:50 -0400 Subject: [PATCH 01/14] pocket cleanup --- pocket/startup.lua | 80 +++++++++---------- pocket/ui/main.lua | 10 +-- .../ui/{components => pages}/boiler_page.lua | 0 pocket/ui/{components => pages}/home_page.lua | 0 .../ui/{components => pages}/reactor_page.lua | 0 .../ui/{components => pages}/turbine_page.lua | 0 pocket/ui/{components => pages}/unit_page.lua | 0 7 files changed, 45 insertions(+), 45 deletions(-) rename pocket/ui/{components => pages}/boiler_page.lua (100%) rename pocket/ui/{components => pages}/home_page.lua (100%) rename pocket/ui/{components => pages}/reactor_page.lua (100%) rename pocket/ui/{components => pages}/turbine_page.lua (100%) rename pocket/ui/{components => pages}/unit_page.lua (100%) diff --git a/pocket/startup.lua b/pocket/startup.lua index 9516340..8397437 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.2.6" +local POCKET_VERSION = "alpha-v0.2.7" local println = util.println local println_ts = util.println_ts @@ -120,54 +120,54 @@ local function main() conn_wd.sv.feed() conn_wd.api.feed() log.debug("startup> conn watchdog started") - end - -- main event loop - while ui_ok do - local event, param1, param2, param3, param4, param5 = util.pull_event() + -- main event loop + while true do + local event, param1, param2, param3, param4, param5 = util.pull_event() - -- handle event - if event == "timer" then - if loop_clock.is_clock(param1) then - -- main loop tick + -- handle event + if event == "timer" then + if loop_clock.is_clock(param1) then + -- main loop tick - -- relink if necessary - pocket_comms.link_update() + -- relink if necessary + pocket_comms.link_update() - loop_clock.start() - elseif conn_wd.sv.is_timer(param1) then - -- supervisor watchdog timeout - log.info("supervisor server timeout") - pocket_comms.close_sv() - elseif conn_wd.api.is_timer(param1) then - -- coordinator watchdog timeout - log.info("coordinator api server timeout") - pocket_comms.close_api() - else - -- a non-clock/main watchdog timer event - -- notify timer callback dispatcher - tcallbackdsp.handle(param1) + loop_clock.start() + elseif conn_wd.sv.is_timer(param1) then + -- supervisor watchdog timeout + log.info("supervisor server timeout") + pocket_comms.close_sv() + elseif conn_wd.api.is_timer(param1) then + -- coordinator watchdog timeout + log.info("coordinator api server timeout") + pocket_comms.close_api() + else + -- a non-clock/main watchdog timer event + -- notify timer callback dispatcher + tcallbackdsp.handle(param1) + end + elseif event == "modem_message" then + -- got a packet + local packet = pocket_comms.parse_packet(param1, param2, param3, param4, param5) + pocket_comms.handle_packet(packet) + elseif event == "mouse_click" then + -- handle a monitor touch event + renderer.handle_mouse(core.events.touch(param1, param2, param3)) + end + + -- check for termination request + if event == "terminate" or ppm.should_terminate() then + log.info("terminate requested, closing server connections...") + pocket_comms.close() + log.info("connections closed") + break end - elseif event == "modem_message" then - -- got a packet - local packet = pocket_comms.parse_packet(param1, param2, param3, param4, param5) - pocket_comms.handle_packet(packet) - elseif event == "mouse_click" then - -- handle a monitor touch event - renderer.handle_mouse(core.events.touch(param1, param2, param3)) end - -- check for termination request - if event == "terminate" or ppm.should_terminate() then - log.info("terminate requested, closing server connections...") - pocket_comms.close() - log.info("connections closed") - break - end + renderer.close_ui() end - renderer.close_ui() - println_ts("exited") log.info("exited") end diff --git a/pocket/ui/main.lua b/pocket/ui/main.lua index 5af9ce8..18302a3 100644 --- a/pocket/ui/main.lua +++ b/pocket/ui/main.lua @@ -8,11 +8,11 @@ local style = require("pocket.ui.style") local conn_waiting = require("pocket.ui.components.conn_waiting") -local home_page = require("pocket.ui.components.home_page") -local unit_page = require("pocket.ui.components.unit_page") -local reactor_page = require("pocket.ui.components.reactor_page") -local boiler_page = require("pocket.ui.components.boiler_page") -local turbine_page = require("pocket.ui.components.turbine_page") +local home_page = require("pocket.ui.pages.home_page") +local unit_page = require("pocket.ui.pages.unit_page") +local reactor_page = require("pocket.ui.pages.reactor_page") +local boiler_page = require("pocket.ui.pages.boiler_page") +local turbine_page = require("pocket.ui.pages.turbine_page") local core = require("graphics.core") diff --git a/pocket/ui/components/boiler_page.lua b/pocket/ui/pages/boiler_page.lua similarity index 100% rename from pocket/ui/components/boiler_page.lua rename to pocket/ui/pages/boiler_page.lua diff --git a/pocket/ui/components/home_page.lua b/pocket/ui/pages/home_page.lua similarity index 100% rename from pocket/ui/components/home_page.lua rename to pocket/ui/pages/home_page.lua diff --git a/pocket/ui/components/reactor_page.lua b/pocket/ui/pages/reactor_page.lua similarity index 100% rename from pocket/ui/components/reactor_page.lua rename to pocket/ui/pages/reactor_page.lua diff --git a/pocket/ui/components/turbine_page.lua b/pocket/ui/pages/turbine_page.lua similarity index 100% rename from pocket/ui/components/turbine_page.lua rename to pocket/ui/pages/turbine_page.lua diff --git a/pocket/ui/components/unit_page.lua b/pocket/ui/pages/unit_page.lua similarity index 100% rename from pocket/ui/components/unit_page.lua rename to pocket/ui/pages/unit_page.lua From ff9a18a019b4dab151a7308e6be434547e3c070a Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 29 Apr 2023 23:49:04 -0400 Subject: [PATCH 02/14] rtu log message cleanup --- rtu/startup.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtu/startup.lua b/rtu/startup.lua index e2d9d94..97832fa 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.0.5" +local RTU_VERSION = "v1.0.6" local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE @@ -457,9 +457,9 @@ local function main() if not rtu_state.fp_ok then renderer.close_ui() println_ts(util.c("UI error: ", message)) - println("init> running without front panel") + println("startup> running without front panel") log.error(util.c("GUI crashed with error ", message)) - log.info("init> running in headless mode without front panel") + log.info("startup> running in headless mode without front panel") end -- start connection watchdog From 2c7b98ba42e676588ee982d711f2159570bfdcc2 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Fri, 5 May 2023 13:04:13 -0400 Subject: [PATCH 03/14] #184 WIP supervisor front panel --- supervisor/databus.lua | 44 ++++++ supervisor/panel/components/plc_entry.lua | 0 supervisor/panel/front_panel.lua | 91 +++++++++++++ supervisor/panel/style.lua | 41 ++++++ supervisor/renderer.lua | 80 +++++++++++ supervisor/session/coordinator.lua | 3 +- supervisor/session/plc.lua | 3 +- supervisor/session/pocket.lua | 3 +- supervisor/session/rtu.lua | 3 +- supervisor/session/svsessions.lua | 1 + supervisor/startup.lua | 159 +++++++++++++--------- supervisor/supervisor.lua | 3 +- 12 files changed, 365 insertions(+), 66 deletions(-) create mode 100644 supervisor/databus.lua create mode 100644 supervisor/panel/components/plc_entry.lua create mode 100644 supervisor/panel/front_panel.lua create mode 100644 supervisor/panel/style.lua create mode 100644 supervisor/renderer.lua diff --git a/supervisor/databus.lua b/supervisor/databus.lua new file mode 100644 index 0000000..e6bbee7 --- /dev/null +++ b/supervisor/databus.lua @@ -0,0 +1,44 @@ +-- +-- Data Bus - Central Communication Linking for Supervisor Front Panel +-- + +local psil = require("scada-common.psil") + +local databus = {} + +local dbus_iface = { + ps = psil.create(), + session_entries = { rtu = {}, plc = {}, coord = {}, diag = {} } +} + +-- call to toggle heartbeat signal +function databus.heartbeat() dbus_iface.ps.toggle("heartbeat") end + +-- transmit firmware versions across the bus +---@param plc_v string supervisor version +---@param comms_v string comms version +function databus.tx_versions(plc_v, comms_v) + dbus_iface.ps.publish("version", plc_v) + dbus_iface.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) +end + +function databus.tx_svs_connection(type, data) +end + +function databus.tx_svs_disconnection(type, data) +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) +end + +return databus diff --git a/supervisor/panel/components/plc_entry.lua b/supervisor/panel/components/plc_entry.lua new file mode 100644 index 0000000..e69de29 diff --git a/supervisor/panel/front_panel.lua b/supervisor/panel/front_panel.lua new file mode 100644 index 0000000..0098a6e --- /dev/null +++ b/supervisor/panel/front_panel.lua @@ -0,0 +1,91 @@ +-- +-- Main SCADA Coordinator GUI +-- + +local util = require("scada-common.util") + +local databus = require("supervisor.databus") + +local style = require("supervisor.panel.style") + +local core = require("graphics.core") + +local Div = require("graphics.elements.div") +local MultiPane = require("graphics.elements.multipane") +local Rectangle = require("graphics.elements.rectangle") +local TextBox = require("graphics.elements.textbox") + +local PushButton = require("graphics.elements.controls.push_button") +local TabBar = require("graphics.elements.controls.tabbar") + +local LED = require("graphics.elements.indicators.led") +local LEDPair = require("graphics.elements.indicators.ledpair") +local RGBLED = require("graphics.elements.indicators.ledrgb") + +local TEXT_ALIGN = core.graphics.TEXT_ALIGN + +local cpair = core.graphics.cpair +local border = core.graphics.border + +-- create new main view +---@param panel graphics_element main displaybox +local function init(panel) + TextBox{parent=panel,y=1,text="SCADA SUPERVISOR",alignment=TEXT_ALIGN.CENTER,height=1,fg_bg=style.header} + + local page_div = Div{parent=panel,x=1,y=3} + + -- + -- system indicators + -- + + local main_page = Div{parent=page_div,x=1,y=1} + + 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 heartbeat = LED{parent=system,label="HEARTBEAT",colors=cpair(colors.green,colors.green_off)} + on.update(true) + system.line_break() + + databus.rx_field("heartbeat", heartbeat.update) + + local modem = LED{parent=system,label="MODEM",colors=cpair(colors.green,colors.green_off)} + system.line_break() + + databus.rx_field("has_modem", modem.update) + + -- + -- about footer + -- + + local about = Div{parent=main_page,width=15,height=3,x=1,y=16,fg_bg=cpair(colors.lightGray,colors.ivory)} + 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) + + -- + -- page handling + -- + + local plc_list = Div{parent=page_div,x=1,y=1} + + TextBox{parent=plc_list,x=2,y=2,text="v1.1.17 - PLC - UNIT 4 - :15004",alignment=TEXT_ALIGN.LEFT,height=1} + + local panes = { main_page, plc_list, main_page, main_page, main_page } + + local page_pane = MultiPane{parent=page_div,x=1,y=1,panes=panes} + + local tabs = { + { name = "Main", color = cpair(colors.black, colors.ivory) }, + { name = "PLCs", color = cpair(colors.black, colors.ivory) }, + { name = "RTUs", color = cpair(colors.black, colors.ivory) }, + { name = "CRDs", color = cpair(colors.black, colors.ivory) }, + { name = "PKTs", color = cpair(colors.black, colors.ivory) }, + } + + TabBar{parent=panel,y=2,tabs=tabs,min_width=10,callback=page_pane.set_value,fg_bg=cpair(colors.black,colors.white)} +end + +return init diff --git a/supervisor/panel/style.lua b/supervisor/panel/style.lua new file mode 100644 index 0000000..31039d4 --- /dev/null +++ b/supervisor/panel/style.lua @@ -0,0 +1,41 @@ +-- +-- Graphics Style Options +-- + +local core = require("graphics.core") + +local style = {} + +local cpair = core.graphics.cpair + +-- GLOBAL -- + +-- remap global colors +colors.ivory = colors.pink +colors.red_off = colors.brown +colors.yellow_off = colors.magenta +colors.green_off = colors.lime + +style.root = cpair(colors.black, colors.ivory) +style.header = cpair(colors.black, colors.lightGray) + +style.colors = { + { c = colors.red, hex = 0xdf4949 }, -- RED ON + { c = colors.orange, hex = 0xffb659 }, + { c = colors.yellow, hex = 0xf9fb53 }, -- YELLOW ON + { c = colors.lime, hex = 0x16665a }, -- GREEN OFF + { c = colors.green, hex = 0x6be551 }, -- GREEN ON + { c = colors.cyan, hex = 0x34bac8 }, + { c = colors.lightBlue, hex = 0x6cc0f2 }, + { c = colors.blue, hex = 0x0096ff }, + { c = colors.purple, hex = 0xb156ee }, + { c = colors.pink, hex = 0xdcd9ca }, -- IVORY + { c = colors.magenta, hex = 0x85862c }, -- YELLOW OFF + -- { c = colors.white, hex = 0xdcd9ca }, + { c = colors.lightGray, hex = 0xb1b8b3 }, + { c = colors.gray, hex = 0x575757 }, + -- { c = colors.black, hex = 0x191919 }, + { c = colors.brown, hex = 0x672223 } -- RED OFF +} + +return style diff --git a/supervisor/renderer.lua b/supervisor/renderer.lua new file mode 100644 index 0000000..ca49946 --- /dev/null +++ b/supervisor/renderer.lua @@ -0,0 +1,80 @@ +-- +-- Graphics Rendering Control +-- + +local panel_view = require("supervisor.panel.front_panel") +local style = require("supervisor.panel.style") + +local flasher = require("graphics.flasher") + +local DisplayBox = require("graphics.elements.displaybox") + +local renderer = {} + +local ui = { + display = nil +} + +-- start the UI +function renderer.start_ui() + if ui.display == nil then + -- reset terminal + term.setTextColor(colors.white) + term.setBackgroundColor(colors.black) + term.clear() + term.setCursorPos(1, 1) + + -- set overridden colors + for i = 1, #style.colors do + term.setPaletteColor(style.colors[i].c, style.colors[i].hex) + end + + -- init front panel view + ui.display = DisplayBox{window=term.current(),fg_bg=style.root} + panel_view(ui.display) + + -- start flasher callback task + flasher.run() + end +end + +-- close out the UI +function renderer.close_ui() + if ui.display ~= nil then + -- stop blinking indicators + flasher.clear() + + -- hide to stop animation callbacks + ui.display.hide() + + -- clear root UI elements + ui.display = nil + + -- restore colors + for i = 1, #style.colors do + local r, g, b = term.nativePaletteColor(style.colors[i].c) + term.setPaletteColor(style.colors[i].c, r, g, b) + end + + -- reset terminal + term.setTextColor(colors.white) + term.setBackgroundColor(colors.black) + term.clear() + term.setCursorPos(1, 1) + end +end + +-- is the UI ready? +---@nodiscard +---@return boolean ready +function renderer.ui_ready() return ui.display ~= nil end + +-- handle a mouse event +---@param event mouse_interaction +function renderer.handle_mouse(event) + if ui.display ~= nil then + ui.display.handle_mouse(event) + end +end + +return renderer diff --git a/supervisor/session/coordinator.lua b/supervisor/session/coordinator.lua index b093d87..b68d815 100644 --- a/supervisor/session/coordinator.lua +++ b/supervisor/session/coordinator.lua @@ -18,7 +18,8 @@ local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local SV_Q_DATA = svqtypes.SV_Q_DATA -local println = util.println +-- local println = util.println +local println = function (str) end -- retry time constants in ms -- local INITIAL_WAIT = 1500 diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index cca8a26..8c61221 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.lua @@ -14,7 +14,8 @@ local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE local PLC_AUTO_ACK = comms.PLC_AUTO_ACK local UNIT_COMMAND = comms.UNIT_COMMAND -local println = util.println +-- local println = util.println +local println = function (str) end -- retry time constants in ms local INITIAL_WAIT = 1500 diff --git a/supervisor/session/pocket.lua b/supervisor/session/pocket.lua index 9cf0a5d..5693e02 100644 --- a/supervisor/session/pocket.lua +++ b/supervisor/session/pocket.lua @@ -8,7 +8,8 @@ local pocket = {} local PROTOCOL = comms.PROTOCOL local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE -local println = util.println +-- local println = util.println +local println = function (str) end -- retry time constants in ms -- local INITIAL_WAIT = 1500 diff --git a/supervisor/session/rtu.lua b/supervisor/session/rtu.lua index 96309a0..5d0e5c2 100644 --- a/supervisor/session/rtu.lua +++ b/supervisor/session/rtu.lua @@ -22,7 +22,8 @@ local PROTOCOL = comms.PROTOCOL local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE -local println = util.println +-- local println = util.println +local println = function (str) end local PERIODICS = { KEEP_ALIVE = 2000 diff --git a/supervisor/session/svsessions.lua b/supervisor/session/svsessions.lua index 8ad3366..93b35b9 100644 --- a/supervisor/session/svsessions.lua +++ b/supervisor/session/svsessions.lua @@ -22,6 +22,7 @@ local CRD_S_DATA = coordinator.CRD_S_DATA local svsessions = {} +---@enum SESSION_TYPE local SESSION_TYPE = { RTU_SESSION = 0, -- RTU gateway PLC_SESSION = 1, -- reactor PLC diff --git a/supervisor/startup.lua b/supervisor/startup.lua index bf27e2e..c104e1b 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -5,16 +5,21 @@ require("/initenv").init_env() 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 util = require("scada-common.util") +local core = require("graphics.core") + local config = require("supervisor.config") +local databus = require("supervisor.databus") +local renderer = require("supervisor.renderer") local supervisor = require("supervisor.supervisor") local svsessions = require("supervisor.session.svsessions") -local SUPERVISOR_VERSION = "v0.15.5" +local SUPERVISOR_VERSION = "v0.16.0" local println = util.println local println_ts = util.println_ts @@ -79,6 +84,9 @@ local function main() -- startup ---------------------------------------- + -- record firmware versions and ID + databus.tx_versions(SUPERVISOR_VERSION, comms.version) + -- mount connected devices ppm.mount_all() @@ -89,84 +97,113 @@ local function main() return end - -- start comms, open all channels - local superv_comms = supervisor.comms(SUPERVISOR_VERSION, config.NUM_REACTORS, config.REACTOR_COOLING, modem, - config.SCADA_DEV_LISTEN, config.SCADA_SV_CTL_LISTEN, config.TRUSTED_RANGE) + databus.tx_hw_modem(true) - -- base loop clock (6.67Hz, 3 ticks) - local MAIN_CLOCK = 0.15 - local loop_clock = util.new_clock(MAIN_CLOCK) + -- start UI + local fp_ok, message = pcall(renderer.start_ui) - -- start clock - loop_clock.start() + if not fp_ok then + renderer.close_ui() + println_ts(util.c("UI error: ", message)) + log.error(util.c("GUI crashed with error ", message)) + else + -- start comms, open all channels + local superv_comms = supervisor.comms(SUPERVISOR_VERSION, config.NUM_REACTORS, config.REACTOR_COOLING, modem, + config.SCADA_DEV_LISTEN, config.SCADA_SV_CTL_LISTEN, config.TRUSTED_RANGE) - -- event loop - while true do - local event, param1, param2, param3, param4, param5 = util.pull_event() + -- base loop clock (6.67Hz, 3 ticks) + local MAIN_CLOCK = 0.15 + local loop_clock = util.new_clock(MAIN_CLOCK) - -- handle event - if event == "peripheral_detach" then - local type, device = ppm.handle_unmount(param1) + -- start clock + loop_clock.start() - if type ~= nil and device ~= nil then - if type == "modem" then - -- we only care if this is our wireless modem - if device == modem then - println_ts("wireless modem disconnected!") - log.warning("comms modem disconnected") - else - log.warning("non-comms modem disconnected") + -- event loop + while true do + local event, param1, param2, param3, param4, param5 = util.pull_event() + + -- handle event + if event == "peripheral_detach" then + local type, device = ppm.handle_unmount(param1) + + if type ~= nil and device ~= nil then + if type == "modem" then + -- we only care if this is our wireless modem + if device == modem then + log.warning("comms modem disconnected") + databus.tx_hw_modem(false) + else + log.warning("non-comms modem disconnected") + end end end - end - elseif event == "peripheral" then - local type, device = ppm.mount(param1) + elseif event == "peripheral" then + local type, device = ppm.mount(param1) - if type ~= nil and device ~= nil then - if type == "modem" then - if device.isWireless() then - -- reconnected modem - modem = device - superv_comms.reconnect_modem(modem) + if type ~= nil and device ~= nil then + if type == "modem" then + if device.isWireless() then + -- reconnected modem + modem = device + superv_comms.reconnect_modem(modem) - println_ts("wireless modem reconnected.") - log.info("comms modem reconnected") - else - log.info("wired modem reconnected") + log.info("comms modem reconnected") + + databus.tx_hw_modem(true) + else + log.info("wired modem reconnected") + end end end + elseif event == "timer" and loop_clock.is_clock(param1) then + -- main loop tick + databus.heartbeat() + + -- iterate sessions + svsessions.iterate_all() + + -- free any closed sessions + svsessions.free_all_closed() + + loop_clock.start() + elseif event == "timer" then + -- a non-clock timer event, check watchdogs + svsessions.check_all_watchdogs(param1) + elseif event == "modem_message" then + -- got a packet + local packet = superv_comms.parse_packet(param1, param2, param3, param4, param5) + superv_comms.handle_packet(packet) + elseif event == "mouse_click" then + -- handle a monitor touch event + renderer.handle_mouse(core.events.touch(param1, param2, param3)) + log.debug(util.sprintf("mouse_click: %s [%d, %d]", param1, param2, param3)) + elseif event == "mouse_drag" then + log.debug(util.sprintf("mouse_drag: %s [%d, %d]", param1, param2, param3)) + elseif event == "mouse_scroll" then + log.debug(util.sprintf("mouse_scroll: %s [%d, %d]", param1, param2, param3)) + elseif event == "mouse_up" then + log.debug(util.sprintf("mouse_up: %s [%d, %d]", param1, param2, param3)) end - elseif event == "timer" and loop_clock.is_clock(param1) then - -- main loop tick - -- iterate sessions - svsessions.iterate_all() - - -- free any closed sessions - svsessions.free_all_closed() - - loop_clock.start() - elseif event == "timer" then - -- a non-clock timer event, check watchdogs - svsessions.check_all_watchdogs(param1) - elseif event == "modem_message" then - -- got a packet - local packet = superv_comms.parse_packet(param1, param2, param3, param4, param5) - superv_comms.handle_packet(packet) + -- check for termination request + if event == "terminate" or ppm.should_terminate() then + log.info("terminate requested, closing sessions...") + svsessions.close_all() + log.info("sessions closed") + break + end end - -- check for termination request - if event == "terminate" or ppm.should_terminate() then - println_ts("closing sessions...") - log.info("terminate requested, closing sessions...") - svsessions.close_all() - log.info("sessions closed") - break - end + renderer.close_ui() end println_ts("exited") log.info("exited") end -if not xpcall(main, crash.handler) then crash.exit() else log.close() end +if not xpcall(main, crash.handler) then + pcall(renderer.close_ui) + crash.exit() +else + log.close() +end diff --git a/supervisor/supervisor.lua b/supervisor/supervisor.lua index 49cf482..076f0ac 100644 --- a/supervisor/supervisor.lua +++ b/supervisor/supervisor.lua @@ -11,7 +11,8 @@ local DEVICE_TYPE = comms.DEVICE_TYPE local ESTABLISH_ACK = comms.ESTABLISH_ACK local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE -local println = util.println +-- local println = util.println +local println = function (str) end -- supervisory controller communications ---@nodiscard From e159dbb85065cebb3c80a36d9faa5ce91d4cf760 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Thu, 11 May 2023 20:06:41 -0400 Subject: [PATCH 04/14] #184 updated supervisor for new mouse events --- supervisor/panel/front_panel.lua | 6 +++--- supervisor/panel/style.lua | 2 +- supervisor/renderer.lua | 4 ++-- supervisor/startup.lua | 13 +++---------- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/supervisor/panel/front_panel.lua b/supervisor/panel/front_panel.lua index 0098a6e..21d631b 100644 --- a/supervisor/panel/front_panel.lua +++ b/supervisor/panel/front_panel.lua @@ -22,10 +22,10 @@ local LED = require("graphics.elements.indicators.led") local LEDPair = require("graphics.elements.indicators.ledpair") local RGBLED = require("graphics.elements.indicators.ledrgb") -local TEXT_ALIGN = core.graphics.TEXT_ALIGN +local TEXT_ALIGN = core.TEXT_ALIGN -local cpair = core.graphics.cpair -local border = core.graphics.border +local cpair = core.cpair +local border = core.border -- create new main view ---@param panel graphics_element main displaybox diff --git a/supervisor/panel/style.lua b/supervisor/panel/style.lua index 31039d4..996453c 100644 --- a/supervisor/panel/style.lua +++ b/supervisor/panel/style.lua @@ -6,7 +6,7 @@ local core = require("graphics.core") local style = {} -local cpair = core.graphics.cpair +local cpair = core.cpair -- GLOBAL -- diff --git a/supervisor/renderer.lua b/supervisor/renderer.lua index ca49946..5dfb7d1 100644 --- a/supervisor/renderer.lua +++ b/supervisor/renderer.lua @@ -70,9 +70,9 @@ end function renderer.ui_ready() return ui.display ~= nil end -- handle a mouse event ----@param event mouse_interaction +---@param event mouse_interaction|nil function renderer.handle_mouse(event) - if ui.display ~= nil then + if ui.display ~= nil and event ~= nil then ui.display.handle_mouse(event) end end diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 57888e5..ce18670 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -174,16 +174,9 @@ local function main() -- got a packet local packet = superv_comms.parse_packet(param1, param2, param3, param4, param5) superv_comms.handle_packet(packet) - elseif event == "mouse_click" then - -- handle a monitor touch event - renderer.handle_mouse(core.events.touch(param1, param2, param3)) - log.debug(util.sprintf("mouse_click: %s [%d, %d]", param1, param2, param3)) - elseif event == "mouse_drag" then - log.debug(util.sprintf("mouse_drag: %s [%d, %d]", param1, param2, param3)) - elseif event == "mouse_scroll" then - log.debug(util.sprintf("mouse_scroll: %s [%d, %d]", param1, param2, param3)) - elseif event == "mouse_up" then - log.debug(util.sprintf("mouse_up: %s [%d, %d]", param1, param2, param3)) + elseif event == "mouse_click" or event == "mouse_up" or event == "mouse_drag" or event == "mouse_scroll" then + -- handle a mouse event + renderer.handle_mouse(core.events.new_mouse_event(event, param1, param2, param3)) end -- check for termination request From ece7c0fe9ac47c0b2782ffa03e8789f31c9538c9 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Tue, 23 May 2023 19:22:22 -0400 Subject: [PATCH 05/14] #184 supervisor graphics updates for new system, added PLC and CRD pages on supervisor front panel --- graphics/elements/indicators/data.lua | 11 ++- supervisor/databus.lua | 81 +++++++++++++-- supervisor/panel/components/plc_entry.lua | 0 supervisor/panel/front_panel.lua | 115 +++++++++++++++++----- supervisor/panel/style.lua | 5 +- supervisor/session/coordinator.lua | 5 + supervisor/session/plc.lua | 5 + supervisor/session/svsessions.lua | 5 + supervisor/startup.lua | 2 +- 9 files changed, 190 insertions(+), 39 deletions(-) delete mode 100644 supervisor/panel/components/plc_entry.lua diff --git a/graphics/elements/indicators/data.lua b/graphics/elements/indicators/data.lua index 66d45dc..748c17a 100644 --- a/graphics/elements/indicators/data.lua +++ b/graphics/elements/indicators/data.lua @@ -52,6 +52,8 @@ local function data(args) clear_width = args.width - (label_len + 1) end + local value_color = e.fg_bg.fgd + -- on state change ---@param value any new value function e.on_update(value) @@ -64,7 +66,7 @@ local function data(args) -- write data local data_str = util.sprintf(args.format, value) e.window.setCursorPos(data_start, 1) - e.window.setTextColor(e.fg_bg.fgd) + e.window.setTextColor(value_color) if args.commas then e.window.write(util.comma_format(data_str)) else @@ -84,6 +86,13 @@ local function data(args) ---@param val any new value function e.set_value(val) e.on_update(val) end + -- change the foreground color of the value, or all text if no label/unit colors provided + ---@param c color + function e.recolor(c) + value_color = c + e.on_update(e.value) + end + -- initial value draw e.on_update(args.value) diff --git a/supervisor/databus.lua b/supervisor/databus.lua index e6bbee7..082a71e 100644 --- a/supervisor/databus.lua +++ b/supervisor/databus.lua @@ -6,39 +6,102 @@ local psil = require("scada-common.psil") local databus = {} +-- databus PSIL +databus.ps = psil.create() + local dbus_iface = { - ps = psil.create(), - session_entries = { rtu = {}, plc = {}, coord = {}, diag = {} } + session_entries = { rtu = {}, diag = {} } } -- 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 plc_v string supervisor version ---@param comms_v string comms version function databus.tx_versions(plc_v, comms_v) - dbus_iface.ps.publish("version", plc_v) - dbus_iface.ps.publish("comms_version", comms_v) + databus.ps.publish("version", plc_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 -function databus.tx_svs_connection(type, data) +-- transmit PLC firmware version and session connection state +---@param reactor_id integer reactor unit ID +---@param fw string firmware version +---@param channel integer PLC remote port +function databus.tx_plc_connected(reactor_id, fw, channel) + databus.ps.publish("plc_" .. reactor_id .. "_fw", fw) + databus.ps.publish("plc_" .. reactor_id .. "_conn", true) + databus.ps.publish("plc_" .. reactor_id .. "_chan", tostring(channel)) end -function databus.tx_svs_disconnection(type, data) +-- transmit PLC session connection state +---@param reactor_id integer reactor unit ID +function databus.tx_plc_disconnected(reactor_id) + databus.ps.publish("plc_" .. reactor_id .. "_fw", " ------- ") + databus.ps.publish("plc_" .. reactor_id .. "_conn", false) + databus.ps.publish("plc_" .. reactor_id .. "_chan", " --- ") + databus.ps.publish("plc_" .. reactor_id .. "_rtt", 0) + databus.ps.publish("plc_" .. reactor_id .. "_rtt_color", colors.lightGray) +end + +-- transmit PLC session RTT +---@param reactor_id integer reactor unit ID +---@param rtt integer round trip time +function databus.tx_plc_rtt(reactor_id, rtt) + databus.ps.publish("plc_" .. reactor_id .. "_rtt", rtt) + + if rtt > 700 then + databus.ps.publish("plc_" .. reactor_id .. "_rtt_color", colors.red) + elseif rtt > 300 then + databus.ps.publish("plc_" .. reactor_id .. "_rtt_color", colors.yellow_hc) + else + databus.ps.publish("plc_" .. reactor_id .. "_rtt_color", colors.green) + end +end + +-- transmit coordinator firmware version and session connection state +---@param fw string firmware version +---@param channel integer coordinator remote port +function databus.tx_crd_connected(fw, channel) + databus.ps.publish("crd_fw", fw) + databus.ps.publish("crd_conn", true) + databus.ps.publish("crd_chan", tostring(channel)) +end + +-- transmit coordinator session connection state +function databus.tx_crd_disconnected() + databus.ps.publish("crd_fw", " ------- ") + databus.ps.publish("crd_conn", false) + databus.ps.publish("crd_chan", "---") + databus.ps.publish("crd_rtt", 0) + databus.ps.publish("crd_rtt_color", colors.lightGray) +end + +-- transmit coordinator session RTT +---@param rtt integer round trip time +function databus.tx_crd_rtt(rtt) + databus.ps.publish("crd_rtt", rtt) + + if rtt > 700 then + databus.ps.publish("crd_rtt_color", colors.red) + elseif rtt > 300 then + databus.ps.publish("crd_rtt_color", colors.yellow_hc) + else + databus.ps.publish("crd_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 function databus.rx_field(field, func) - dbus_iface.ps.subscribe(field, func) + databus.ps.subscribe(field, func) end return databus diff --git a/supervisor/panel/components/plc_entry.lua b/supervisor/panel/components/plc_entry.lua deleted file mode 100644 index e69de29..0000000 diff --git a/supervisor/panel/front_panel.lua b/supervisor/panel/front_panel.lua index 21d631b..bf95c6b 100644 --- a/supervisor/panel/front_panel.lua +++ b/supervisor/panel/front_panel.lua @@ -2,25 +2,28 @@ -- Main SCADA Coordinator GUI -- -local util = require("scada-common.util") +local util = require("scada-common.util") -local databus = require("supervisor.databus") +local config = require("supervisor.config") +local databus = require("supervisor.databus") -local style = require("supervisor.panel.style") +local style = require("supervisor.panel.style") -local core = require("graphics.core") +local core = require("graphics.core") -local Div = require("graphics.elements.div") -local MultiPane = require("graphics.elements.multipane") -local Rectangle = require("graphics.elements.rectangle") -local TextBox = require("graphics.elements.textbox") +local Div = require("graphics.elements.div") +local ListBox = require("graphics.elements.listbox") +local MultiPane = require("graphics.elements.multipane") +local Rectangle = require("graphics.elements.rectangle") +local TextBox = require("graphics.elements.textbox") -local PushButton = require("graphics.elements.controls.push_button") -local TabBar = require("graphics.elements.controls.tabbar") +local PushButton = require("graphics.elements.controls.push_button") +local TabBar = require("graphics.elements.controls.tabbar") -local LED = require("graphics.elements.indicators.led") -local LEDPair = require("graphics.elements.indicators.ledpair") -local RGBLED = require("graphics.elements.indicators.ledrgb") +local LED = require("graphics.elements.indicators.led") +local LEDPair = require("graphics.elements.indicators.ledpair") +local RGBLED = require("graphics.elements.indicators.ledrgb") +local DataIndicator = require("graphics.elements.indicators.data") local TEXT_ALIGN = core.TEXT_ALIGN @@ -47,12 +50,12 @@ local function init(panel) 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)} system.line_break() - databus.rx_field("has_modem", modem.update) + modem.register(databus.ps, "has_modem", modem.update) -- -- about footer @@ -62,30 +65,90 @@ local function init(panel) 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) -- -- page handling -- - local plc_list = Div{parent=page_div,x=1,y=1} + -- plc page - TextBox{parent=plc_list,x=2,y=2,text="v1.1.17 - PLC - UNIT 4 - :15004",alignment=TEXT_ALIGN.LEFT,height=1} + local plc_page = Div{parent=page_div,x=1,y=1} + local plc_list = Div{parent=plc_page,x=2,y=2,width=49} - local panes = { main_page, plc_list, main_page, main_page, main_page } + for i = 1, config.NUM_REACTORS do + local ps_prefix = "plc_" .. i .. "_" + local plc_entry = Div{parent=plc_list,height=3,fg_bg=cpair(colors.black,colors.white)} + + TextBox{parent=plc_entry,x=1,y=1,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)} + TextBox{parent=plc_entry,x=1,y=2,text="UNIT "..i,alignment=TEXT_ALIGN.CENTER,width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)} + TextBox{parent=plc_entry,x=1,y=3,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)} + + local conn = LED{parent=plc_entry,x=10,y=2,label="CONN",colors=cpair(colors.green,colors.green_off)} + conn.register(databus.ps, ps_prefix .. "conn", conn.update) + + local plc_chan = TextBox{parent=plc_entry,x=17,y=2,text=" --- ",width=5,height=1,fg_bg=cpair(colors.gray,colors.white)} + plc_chan.register(databus.ps, ps_prefix .. "chan", plc_chan.set_value) + + TextBox{parent=plc_entry,x=23,y=2,text="FW:",width=3,height=1} + local plc_fw_v = TextBox{parent=plc_entry,x=27,y=2,text=" ------- ",width=9,height=1,fg_bg=cpair(colors.lightGray,colors.white)} + plc_fw_v.register(databus.ps, ps_prefix .. "fw", plc_fw_v.set_value) + + TextBox{parent=plc_entry,x=37,y=2,text="RTT:",width=4,height=1} + local plc_rtt = DataIndicator{parent=plc_entry,x=42,y=2,label="",unit="",format="%4d",value=0,width=4,fg_bg=cpair(colors.lightGray,colors.white)} + TextBox{parent=plc_entry,x=47,y=2,text="ms",width=4,height=1,fg_bg=cpair(colors.lightGray,colors.white)} + plc_rtt.register(databus.ps, ps_prefix .. "rtt", plc_rtt.update) + plc_rtt.register(databus.ps, ps_prefix .. "rtt_color", plc_rtt.recolor) + + plc_list.line_break() + end + + -- rtu page + + local rtu_page = Div{parent=page_div,x=1,y=1} + local rtu_list = Div{parent=rtu_page,x=2,y=2,width=49} + + -- coordinator page + + local crd_page = Div{parent=page_div,x=1,y=1} + local crd_box = Div{parent=crd_page,x=2,y=2,width=49,height=4,fg_bg=cpair(colors.black,colors.white)} + + local crd_conn = LED{parent=crd_box,x=2,y=2,label="CONNECTION",colors=cpair(colors.green,colors.green_off)} + crd_conn.register(databus.ps, "crd_conn", crd_conn.update) + + TextBox{parent=crd_box,x=4,y=3,text="CHANNEL ",width=8,height=1,fg_bg=cpair(colors.gray,colors.white)} + local crd_chan = TextBox{parent=crd_box,x=12,y=3,text="---",width=5,height=1,fg_bg=cpair(colors.gray,colors.white)} + crd_chan.register(databus.ps, "crd_chan", crd_chan.set_value) + + TextBox{parent=crd_box,x=22,y=2,text="FW:",width=3,height=1} + local crd_fw_v = TextBox{parent=crd_box,x=26,y=2,text=" ------- ",width=9,height=1,fg_bg=cpair(colors.lightGray,colors.white)} + crd_fw_v.register(databus.ps, "crd_fw", crd_fw_v.set_value) + + TextBox{parent=crd_box,x=36,y=2,text="RTT:",width=4,height=1} + local crd_rtt = DataIndicator{parent=crd_box,x=41,y=2,label="",unit="",format="%5d",value=0,width=5,fg_bg=cpair(colors.lightGray,colors.white)} + TextBox{parent=crd_box,x=47,y=2,text="ms",width=4,height=1,fg_bg=cpair(colors.lightGray,colors.white)} + crd_rtt.register(databus.ps, "crd_rtt", crd_rtt.update) + crd_rtt.register(databus.ps, "crd_rtt_color", crd_rtt.recolor) + + -- pocket page + + local pkt_page = Div{parent=page_div,x=1,y=1} + local pkt_box = Div{parent=pkt_page,x=2,y=2,width=49} + + local panes = { main_page, plc_page, rtu_page, crd_page, pkt_page } local page_pane = MultiPane{parent=page_div,x=1,y=1,panes=panes} local tabs = { - { name = "Main", color = cpair(colors.black, colors.ivory) }, - { name = "PLCs", color = cpair(colors.black, colors.ivory) }, - { name = "RTUs", color = cpair(colors.black, colors.ivory) }, - { name = "CRDs", color = cpair(colors.black, colors.ivory) }, - { name = "PKTs", color = cpair(colors.black, colors.ivory) }, + { name = "SVR", color = cpair(colors.black, colors.ivory) }, + { name = "PLC", color = cpair(colors.black, colors.ivory) }, + { name = "RTU", color = cpair(colors.black, colors.ivory) }, + { name = "CRD", color = cpair(colors.black, colors.ivory) }, + { name = "PKT", color = cpair(colors.black, colors.ivory) }, } - TabBar{parent=panel,y=2,tabs=tabs,min_width=10,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)} end return init diff --git a/supervisor/panel/style.lua b/supervisor/panel/style.lua index 996453c..0668ccc 100644 --- a/supervisor/panel/style.lua +++ b/supervisor/panel/style.lua @@ -12,6 +12,7 @@ local cpair = core.cpair -- remap global colors colors.ivory = colors.pink +colors.yellow_hc = colors.purple colors.red_off = colors.brown colors.yellow_off = colors.magenta colors.green_off = colors.lime @@ -27,8 +28,8 @@ style.colors = { { c = colors.green, hex = 0x6be551 }, -- GREEN ON { c = colors.cyan, hex = 0x34bac8 }, { c = colors.lightBlue, hex = 0x6cc0f2 }, - { c = colors.blue, hex = 0x0096ff }, - { c = colors.purple, hex = 0xb156ee }, + { c = colors.blue, hex = 0x0008fe }, -- LCD BLUE + { c = colors.purple, hex = 0xe3bc2a }, -- YELLOW HIGH CONTRAST { c = colors.pink, hex = 0xdcd9ca }, -- IVORY { c = colors.magenta, hex = 0x85862c }, -- YELLOW OFF -- { c = colors.white, hex = 0xdcd9ca }, diff --git a/supervisor/session/coordinator.lua b/supervisor/session/coordinator.lua index b68d815..03a579d 100644 --- a/supervisor/session/coordinator.lua +++ b/supervisor/session/coordinator.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") local coordinator = {} @@ -85,6 +87,7 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility) local function _close() self.conn_watchdog.cancel() self.connected = false + databus.tx_crd_disconnected() end -- send a CRDN packet @@ -206,6 +209,8 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility) -- log.debug(log_header .. "COORD RTT = " .. self.last_rtt .. "ms") -- log.debug(log_header .. "COORD TT = " .. (srv_now - coord_send) .. "ms") + + databus.tx_crd_rtt(self.last_rtt) else log.debug(log_header .. "SCADA keep alive packet length mismatch") end diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index 8c61221..0fb987a 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.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") local plc = {} @@ -236,6 +238,7 @@ function plc.new_session(id, reactor_id, in_queue, out_queue, timeout) local function _close() self.conn_watchdog.cancel() self.connected = false + databus.tx_plc_disconnected(reactor_id) end -- send an RPLC packet @@ -486,6 +489,8 @@ function plc.new_session(id, reactor_id, in_queue, out_queue, timeout) -- log.debug(log_header .. "PLC RTT = " .. self.last_rtt .. "ms") -- log.debug(log_header .. "PLC TT = " .. (srv_now - plc_send) .. "ms") + + databus.tx_plc_rtt(reactor_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 93b35b9..8c56419 100644 --- a/supervisor/session/svsessions.lua +++ b/supervisor/session/svsessions.lua @@ -3,6 +3,7 @@ local mqueue = require("scada-common.mqueue") local util = require("scada-common.util") local config = require("supervisor.config") +local databus = require("supervisor.databus") local facility = require("supervisor.facility") local svqtypes = require("supervisor.session.svqtypes") @@ -317,6 +318,8 @@ function svsessions.establish_plc_session(local_port, remote_port, for_reactor, self.next_ids.plc = self.next_ids.plc + 1 + databus.tx_plc_connected(for_reactor, version, remote_port) + -- success return plc_s.instance.get_id() else @@ -383,6 +386,8 @@ function svsessions.establish_coord_session(local_port, remote_port, version) self.next_ids.coord = self.next_ids.coord + 1 + databus.tx_crd_connected(version, remote_port) + -- success return coord_s.instance.get_id() else diff --git a/supervisor/startup.lua b/supervisor/startup.lua index c3d966a..1c3f84c 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -19,7 +19,7 @@ local supervisor = require("supervisor.supervisor") local svsessions = require("supervisor.session.svsessions") -local SUPERVISOR_VERSION = "v0.16.1" +local SUPERVISOR_VERSION = "v0.16.2" local println = util.println local println_ts = util.println_ts From f9aa75a1055e6a411ddc9eaa0e636f8aceeddc1a Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Thu, 25 May 2023 17:40:16 -0400 Subject: [PATCH 06/14] graphics element hidden on creation option, changed hide/show logic to only hide/show current element --- coordinator/startup.lua | 2 +- graphics/element.lua | 62 ++++++++++--------- graphics/elements/animations/waiting.lua | 1 + graphics/elements/colormap.lua | 1 + graphics/elements/controls/hazard_button.lua | 1 + graphics/elements/controls/multi_button.lua | 1 + graphics/elements/controls/push_button.lua | 1 + graphics/elements/controls/radio_button.lua | 1 + graphics/elements/controls/sidebar.lua | 1 + .../elements/controls/spinbox_numeric.lua | 1 + graphics/elements/controls/switch_button.lua | 1 + graphics/elements/controls/tabbar.lua | 1 + graphics/elements/displaybox.lua | 1 + graphics/elements/div.lua | 1 + graphics/elements/indicators/alight.lua | 1 + graphics/elements/indicators/data.lua | 1 + graphics/elements/indicators/hbar.lua | 1 + graphics/elements/indicators/icon.lua | 1 + graphics/elements/indicators/led.lua | 1 + graphics/elements/indicators/ledpair.lua | 1 + graphics/elements/indicators/ledrgb.lua | 1 + graphics/elements/indicators/light.lua | 1 + graphics/elements/indicators/power.lua | 1 + graphics/elements/indicators/rad.lua | 1 + graphics/elements/indicators/state.lua | 1 + graphics/elements/indicators/trilight.lua | 1 + graphics/elements/indicators/vbar.lua | 1 + graphics/elements/multipane.lua | 1 + graphics/elements/pipenet.lua | 1 + graphics/elements/rectangle.lua | 1 + graphics/elements/textbox.lua | 1 + graphics/elements/tiling.lua | 1 + pocket/startup.lua | 2 +- reactor-plc/startup.lua | 2 +- rtu/startup.lua | 2 +- supervisor/startup.lua | 2 +- 36 files changed, 69 insertions(+), 33 deletions(-) diff --git a/coordinator/startup.lua b/coordinator/startup.lua index 367c1ca..60a0c88 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.2" +local COORDINATOR_VERSION = "v0.15.3" local println = util.println local println_ts = util.println_ts diff --git a/graphics/element.lua b/graphics/element.lua index b865af0..c6dbaa7 100644 --- a/graphics/element.lua +++ b/graphics/element.lua @@ -18,6 +18,7 @@ local element = {} ---@field height? integer parent height if omitted ---@field gframe? graphics_frame frame instead of x/y/width/height ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw ---@alias graphics_args graphics_args_generic ---|waiting_args @@ -153,7 +154,7 @@ function element.new(args) assert(f.h >= 1, name_brief .. "frame height not >= 1") -- create window - protected.window = window.create(self.p_window, f.x, f.y, f.w, f.h, true) + protected.window = window.create(self.p_window, f.x, f.y, f.w, f.h, args.hidden ~= true) -- init colors if args.fg_bg ~= nil then @@ -385,25 +386,6 @@ function element.new(args) return nil end - -- DYNAMIC CHILD ELEMENTS -- - - -- insert an element as a contained child
- -- this is intended to be used dynamically, and depends on the target element type.
- -- 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
- -- this is intended to be used dynamically, and depends on the target element type.
- -- 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 @@ -545,22 +527,46 @@ function element.new(args) ps.subscribe(key, func) end - -- VISIBILITY -- + -- VISIBILITY & ANIMATIONS -- - -- show the element - function public.show() + -- show the element and enables animations by default + ---@param animate? boolean true (default) to automatically resume animations + function public.show(animate) protected.window.setVisible(true) - protected.start_anim() - for _, child in pairs(self.children) do child.show() end + if animate ~= false then public.animate_all() end end - -- hide the element + -- hide the element and disables animations function public.hide() - protected.stop_anim() - for _, child in pairs(self.children) do child.hide() end + public.freeze_all() -- stop animations for efficiency/performance protected.window.setVisible(false) end + -- start/resume animation(s) + function public.animate() + protected.start_anim() + end + + -- start/resume animation(s) for this element and all its children
+ -- only animates if a window is visible + function public.animate_all() + if protected.window.isVisible() then + public.animate() + for _, child in pairs(self.children) do child.animate_all() end + end + end + + -- freeze animation(s) + function public.freeze() + protected.stop_anim() + end + + -- freeze animation(s) for this element and all its children + function public.freeze_all() + public.freeze() + for _, child in pairs(self.children) do child.freeze_all() end + end + -- re-draw the element function public.redraw() protected.window.redraw() diff --git a/graphics/elements/animations/waiting.lua b/graphics/elements/animations/waiting.lua index a0d7b3e..9d88c91 100644 --- a/graphics/elements/animations/waiting.lua +++ b/graphics/elements/animations/waiting.lua @@ -10,6 +10,7 @@ local element = require("graphics.element") ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new waiting animation element ---@param args waiting_args diff --git a/graphics/elements/colormap.lua b/graphics/elements/colormap.lua index 4c7ba94..f494158 100644 --- a/graphics/elements/colormap.lua +++ b/graphics/elements/colormap.lua @@ -9,6 +9,7 @@ local element = require("graphics.element") ---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted +---@field hidden? boolean true to hide on initial draw -- new color map ---@param args colormap_args diff --git a/graphics/elements/controls/hazard_button.lua b/graphics/elements/controls/hazard_button.lua index 4dca5c4..844a6c8 100644 --- a/graphics/elements/controls/hazard_button.lua +++ b/graphics/elements/controls/hazard_button.lua @@ -16,6 +16,7 @@ local element = require("graphics.element") ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new hazard button ---@param args hazard_button_args diff --git a/graphics/elements/controls/multi_button.lua b/graphics/elements/controls/multi_button.lua index e44bad0..ca6600b 100644 --- a/graphics/elements/controls/multi_button.lua +++ b/graphics/elements/controls/multi_button.lua @@ -23,6 +23,7 @@ local element = require("graphics.element") ---@field y? integer 1 if omitted ---@field height? integer parent height if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new multi button (latch selection, exclusively one button at a time) ---@param args multi_button_args diff --git a/graphics/elements/controls/push_button.lua b/graphics/elements/controls/push_button.lua index 27be991..cfcd772 100644 --- a/graphics/elements/controls/push_button.lua +++ b/graphics/elements/controls/push_button.lua @@ -19,6 +19,7 @@ local CLICK_TYPE = core.events.CLICK_TYPE ---@field y? integer 1 if omitted ---@field height? integer parent height if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new push button ---@param args push_button_args diff --git a/graphics/elements/controls/radio_button.lua b/graphics/elements/controls/radio_button.lua index 050bf39..6fc5d56 100644 --- a/graphics/elements/controls/radio_button.lua +++ b/graphics/elements/controls/radio_button.lua @@ -15,6 +15,7 @@ local element = require("graphics.element") ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new radio button list (latch selection, exclusively one button at a time) ---@param args radio_button_args diff --git a/graphics/elements/controls/sidebar.lua b/graphics/elements/controls/sidebar.lua index 45771b2..7dae6ed 100644 --- a/graphics/elements/controls/sidebar.lua +++ b/graphics/elements/controls/sidebar.lua @@ -20,6 +20,7 @@ local CLICK_TYPE = core.events.CLICK_TYPE ---@field y? integer 1 if omitted ---@field height? integer parent height if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new sidebar tab selector ---@param args sidebar_args diff --git a/graphics/elements/controls/spinbox_numeric.lua b/graphics/elements/controls/spinbox_numeric.lua index 6b88c0e..bcdc9e5 100644 --- a/graphics/elements/controls/spinbox_numeric.lua +++ b/graphics/elements/controls/spinbox_numeric.lua @@ -18,6 +18,7 @@ local element = require("graphics.element") ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new spinbox control (minimum value is 0) ---@param args spinbox_args diff --git a/graphics/elements/controls/switch_button.lua b/graphics/elements/controls/switch_button.lua index 645bf8a..e02f506 100644 --- a/graphics/elements/controls/switch_button.lua +++ b/graphics/elements/controls/switch_button.lua @@ -15,6 +15,7 @@ local element = require("graphics.element") ---@field y? integer 1 if omitted ---@field height? integer parent height if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new switch button (latch high/low) ---@param args switch_button_args diff --git a/graphics/elements/controls/tabbar.lua b/graphics/elements/controls/tabbar.lua index 6249951..e188174 100644 --- a/graphics/elements/controls/tabbar.lua +++ b/graphics/elements/controls/tabbar.lua @@ -21,6 +21,7 @@ local element = require("graphics.element") ---@field y? integer 1 if omitted ---@field width? integer parent width if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new tab selector ---@param args tabbar_args diff --git a/graphics/elements/displaybox.lua b/graphics/elements/displaybox.lua index c7e5c9f..f6f520a 100644 --- a/graphics/elements/displaybox.lua +++ b/graphics/elements/displaybox.lua @@ -10,6 +10,7 @@ local element = require("graphics.element") ---@field height? integer parent height if omitted ---@field gframe? graphics_frame frame instead of x/y/width/height ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new root display box ---@nodiscard diff --git a/graphics/elements/div.lua b/graphics/elements/div.lua index 5eeef71..53e3e84 100644 --- a/graphics/elements/div.lua +++ b/graphics/elements/div.lua @@ -11,6 +11,7 @@ local element = require("graphics.element") ---@field height? integer parent height if omitted ---@field gframe? graphics_frame frame instead of x/y/width/height ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new div element ---@nodiscard diff --git a/graphics/elements/indicators/alight.lua b/graphics/elements/indicators/alight.lua index 8bb8fa6..2d933d6 100644 --- a/graphics/elements/indicators/alight.lua +++ b/graphics/elements/indicators/alight.lua @@ -18,6 +18,7 @@ local flasher = require("graphics.flasher") ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new alarm indicator light ---@nodiscard diff --git a/graphics/elements/indicators/data.lua b/graphics/elements/indicators/data.lua index 748c17a..a2b4ea9 100644 --- a/graphics/elements/indicators/data.lua +++ b/graphics/elements/indicators/data.lua @@ -17,6 +17,7 @@ local element = require("graphics.element") ---@field y? integer 1 if omitted ---@field width integer length ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new data indicator ---@nodiscard diff --git a/graphics/elements/indicators/hbar.lua b/graphics/elements/indicators/hbar.lua index 2d9b110..f69374e 100644 --- a/graphics/elements/indicators/hbar.lua +++ b/graphics/elements/indicators/hbar.lua @@ -15,6 +15,7 @@ local element = require("graphics.element") ---@field height? integer parent height if omitted ---@field gframe? graphics_frame frame instead of x/y/width/height ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new horizontal bar ---@nodiscard diff --git a/graphics/elements/indicators/icon.lua b/graphics/elements/indicators/icon.lua index f31479d..f079178 100644 --- a/graphics/elements/indicators/icon.lua +++ b/graphics/elements/indicators/icon.lua @@ -18,6 +18,7 @@ local element = require("graphics.element") ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new icon indicator ---@nodiscard diff --git a/graphics/elements/indicators/led.lua b/graphics/elements/indicators/led.lua index dd2264e..6a6f829 100644 --- a/graphics/elements/indicators/led.lua +++ b/graphics/elements/indicators/led.lua @@ -16,6 +16,7 @@ local flasher = require("graphics.flasher") ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new indicator LED ---@nodiscard diff --git a/graphics/elements/indicators/ledpair.lua b/graphics/elements/indicators/ledpair.lua index 727d4cd..94e6955 100644 --- a/graphics/elements/indicators/ledpair.lua +++ b/graphics/elements/indicators/ledpair.lua @@ -18,6 +18,7 @@ local flasher = require("graphics.flasher") ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new dual LED indicator light ---@nodiscard diff --git a/graphics/elements/indicators/ledrgb.lua b/graphics/elements/indicators/ledrgb.lua index 266e0ab..b66d102 100644 --- a/graphics/elements/indicators/ledrgb.lua +++ b/graphics/elements/indicators/ledrgb.lua @@ -11,6 +11,7 @@ local element = require("graphics.element") ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new RGB LED indicator light ---@nodiscard diff --git a/graphics/elements/indicators/light.lua b/graphics/elements/indicators/light.lua index e764ad9..8213439 100644 --- a/graphics/elements/indicators/light.lua +++ b/graphics/elements/indicators/light.lua @@ -16,6 +16,7 @@ local flasher = require("graphics.flasher") ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new indicator light ---@nodiscard diff --git a/graphics/elements/indicators/power.lua b/graphics/elements/indicators/power.lua index 1d727ae..b7137d7 100644 --- a/graphics/elements/indicators/power.lua +++ b/graphics/elements/indicators/power.lua @@ -16,6 +16,7 @@ local element = require("graphics.element") ---@field y? integer 1 if omitted ---@field width integer length ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new power indicator ---@nodiscard diff --git a/graphics/elements/indicators/rad.lua b/graphics/elements/indicators/rad.lua index 2e4ad56..c843cf4 100644 --- a/graphics/elements/indicators/rad.lua +++ b/graphics/elements/indicators/rad.lua @@ -17,6 +17,7 @@ local element = require("graphics.element") ---@field y? integer 1 if omitted ---@field width integer length ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new radiation indicator ---@nodiscard diff --git a/graphics/elements/indicators/state.lua b/graphics/elements/indicators/state.lua index 10d081b..3bb2831 100644 --- a/graphics/elements/indicators/state.lua +++ b/graphics/elements/indicators/state.lua @@ -18,6 +18,7 @@ local element = require("graphics.element") ---@field y? integer 1 if omitted ---@field height? integer 1 if omitted, must be an odd number ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new state indicator ---@nodiscard diff --git a/graphics/elements/indicators/trilight.lua b/graphics/elements/indicators/trilight.lua index 543ebf5..bbc7526 100644 --- a/graphics/elements/indicators/trilight.lua +++ b/graphics/elements/indicators/trilight.lua @@ -18,6 +18,7 @@ local flasher = require("graphics.flasher") ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new tri-state indicator light ---@nodiscard diff --git a/graphics/elements/indicators/vbar.lua b/graphics/elements/indicators/vbar.lua index fe7f9bc..9c8a8f4 100644 --- a/graphics/elements/indicators/vbar.lua +++ b/graphics/elements/indicators/vbar.lua @@ -13,6 +13,7 @@ local element = require("graphics.element") ---@field height? integer parent height if omitted ---@field gframe? graphics_frame frame instead of x/y/width/height ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new vertical bar ---@nodiscard diff --git a/graphics/elements/multipane.lua b/graphics/elements/multipane.lua index 8e25bab..20da7ed 100644 --- a/graphics/elements/multipane.lua +++ b/graphics/elements/multipane.lua @@ -12,6 +12,7 @@ local element = require("graphics.element") ---@field height? integer parent height if omitted ---@field gframe? graphics_frame frame instead of x/y/width/height ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new multipane element ---@nodiscard diff --git a/graphics/elements/pipenet.lua b/graphics/elements/pipenet.lua index 8a1d29b..8314fd2 100644 --- a/graphics/elements/pipenet.lua +++ b/graphics/elements/pipenet.lua @@ -12,6 +12,7 @@ local element = require("graphics.element") ---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted +---@field hidden? boolean true to hide on initial draw -- new pipe network ---@param args pipenet_args diff --git a/graphics/elements/rectangle.lua b/graphics/elements/rectangle.lua index 2f7a68d..b80b37c 100644 --- a/graphics/elements/rectangle.lua +++ b/graphics/elements/rectangle.lua @@ -16,6 +16,7 @@ local element = require("graphics.element") ---@field height? integer parent height if omitted ---@field gframe? graphics_frame frame instead of x/y/width/height ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new rectangle ---@param args rectangle_args diff --git a/graphics/elements/textbox.lua b/graphics/elements/textbox.lua index 9066deb..6e5717f 100644 --- a/graphics/elements/textbox.lua +++ b/graphics/elements/textbox.lua @@ -18,6 +18,7 @@ local TEXT_ALIGN = core.TEXT_ALIGN ---@field height? integer parent height if omitted ---@field gframe? graphics_frame frame instead of x/y/width/height ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new text box ---@param args textbox_args diff --git a/graphics/elements/tiling.lua b/graphics/elements/tiling.lua index a97438a..0dcaaf8 100644 --- a/graphics/elements/tiling.lua +++ b/graphics/elements/tiling.lua @@ -16,6 +16,7 @@ local element = require("graphics.element") ---@field height? integer parent height if omitted ---@field gframe? graphics_frame frame instead of x/y/width/height ---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw -- new tiling box ---@param args tiling_args diff --git a/pocket/startup.lua b/pocket/startup.lua index 2ea5958..9265558 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.2" +local POCKET_VERSION = "alpha-v0.3.3" local println = util.println local println_ts = util.println_ts diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index 1a7f550..89b5b6d 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.2" +local R_PLC_VERSION = "v1.3.3" local println = util.println local println_ts = util.println_ts diff --git a/rtu/startup.lua b/rtu/startup.lua index 27c7c14..0994261 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.2" +local RTU_VERSION = "v1.2.3" local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 1c3f84c..6dc7253 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -19,7 +19,7 @@ local supervisor = require("supervisor.supervisor") local svsessions = require("supervisor.session.svsessions") -local SUPERVISOR_VERSION = "v0.16.2" +local SUPERVISOR_VERSION = "v0.16.3" local println = util.println local println_ts = util.println_ts From de9cb3bd3a39aab670fca377c3decf315c8811eb Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Tue, 30 May 2023 19:51:10 -0400 Subject: [PATCH 07/14] #243 graphics core updates for content windows, redrawing, and handling of addition/removal of children --- coordinator/startup.lua | 2 +- coordinator/ui/components/processctl.lua | 2 +- coordinator/ui/components/unit_overview.lua | 2 +- coordinator/ui/layout/main_view.lua | 14 +-- graphics/element.lua | 99 +++++++++++++------ graphics/elements/animations/waiting.lua | 2 +- graphics/elements/colormap.lua | 2 +- graphics/elements/controls/hazard_button.lua | 2 +- graphics/elements/controls/multi_button.lua | 2 +- graphics/elements/controls/push_button.lua | 2 +- graphics/elements/controls/radio_button.lua | 2 +- graphics/elements/controls/sidebar.lua | 2 +- .../elements/controls/spinbox_numeric.lua | 2 +- graphics/elements/controls/switch_button.lua | 2 +- graphics/elements/controls/tabbar.lua | 2 +- graphics/elements/displaybox.lua | 2 +- graphics/elements/div.lua | 2 +- graphics/elements/indicators/alight.lua | 2 +- graphics/elements/indicators/coremap.lua | 2 +- graphics/elements/indicators/data.lua | 2 +- graphics/elements/indicators/hbar.lua | 2 +- graphics/elements/indicators/icon.lua | 2 +- graphics/elements/indicators/led.lua | 2 +- graphics/elements/indicators/ledpair.lua | 2 +- graphics/elements/indicators/ledrgb.lua | 2 +- graphics/elements/indicators/light.lua | 2 +- graphics/elements/indicators/power.lua | 2 +- graphics/elements/indicators/rad.lua | 2 +- graphics/elements/indicators/state.lua | 2 +- graphics/elements/indicators/trilight.lua | 2 +- graphics/elements/indicators/vbar.lua | 2 +- graphics/elements/multipane.lua | 2 +- graphics/elements/pipenet.lua | 2 +- graphics/elements/rectangle.lua | 2 +- graphics/elements/textbox.lua | 2 +- graphics/elements/tiling.lua | 2 +- pocket/startup.lua | 2 +- pocket/ui/components/conn_waiting.lua | 2 +- reactor-plc/startup.lua | 2 +- rtu/startup.lua | 2 +- supervisor/startup.lua | 2 +- 41 files changed, 113 insertions(+), 78 deletions(-) diff --git a/coordinator/startup.lua b/coordinator/startup.lua index 60a0c88..17fcc6f 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.3" +local COORDINATOR_VERSION = "v0.15.4" local println = util.println local println_ts = util.println_ts diff --git a/coordinator/ui/components/processctl.lua b/coordinator/ui/components/processctl.lua index a238a8c..7e0016a 100644 --- a/coordinator/ui/components/processctl.lua +++ b/coordinator/ui/components/processctl.lua @@ -33,7 +33,7 @@ local period = core.flasher.PERIOD ---@param x integer top left x ---@param y integer top left y local function new_view(root, x, y) - assert(root.height() >= (y + 24), "main display not of sufficient vertical resolution (add an additional row of monitors)") + assert(root.get_height() >= (y + 24), "main display not of sufficient vertical resolution (add an additional row of monitors)") local facility = iocontrol.get_db().facility local units = iocontrol.get_db().units diff --git a/coordinator/ui/components/unit_overview.lua b/coordinator/ui/components/unit_overview.lua index bd341bf..3af8c83 100644 --- a/coordinator/ui/components/unit_overview.lua +++ b/coordinator/ui/components/unit_overview.lua @@ -38,7 +38,7 @@ local function make(parent, x, y, unit) height = 17 end - assert(parent.height() >= (y + height), "main display not of sufficient vertical resolution (add an additional row of monitors)") + assert(parent.get_height() >= (y + height), "main display not of sufficient vertical resolution (add an additional row of monitors)") -- bounding box div local root = Div{parent=parent,x=x,y=y,width=80,height=height} diff --git a/coordinator/ui/layout/main_view.lua b/coordinator/ui/layout/main_view.lua index a758b24..a7b3c86 100644 --- a/coordinator/ui/layout/main_view.lua +++ b/coordinator/ui/layout/main_view.lua @@ -32,7 +32,7 @@ local function init(main) local header = TextBox{parent=main,y=1,text="Nuclear Generation Facility SCADA Coordinator",alignment=TEXT_ALIGN.CENTER,height=1,fg_bg=style.header} local ping = DataIndicator{parent=main,x=1,y=1,label="SVTT",format="%d",value=0,unit="ms",lu_colors=cpair(colors.lightGray, colors.white),width=12,fg_bg=style.header} -- max length example: "01:23:45 AM - Wednesday, September 28 2022" - local datetime = TextBox{parent=main,x=(header.width()-42),y=1,text="",alignment=TEXT_ALIGN.RIGHT,width=42,height=1,fg_bg=style.header} + local datetime = TextBox{parent=main,x=(header.get_width()-42),y=1,text="",alignment=TEXT_ALIGN.RIGHT,width=42,height=1,fg_bg=style.header} ping.register(facility.ps, "sv_ping", ping.update) datetime.register(facility.ps, "date_time", datetime.set_value) @@ -45,12 +45,12 @@ local function init(main) -- unit overviews if facility.num_units >= 1 then uo_1 = unit_overview(main, 2, 3, units[1]) - row_1_height = uo_1.height() + row_1_height = uo_1.get_height() end if facility.num_units >= 2 then uo_2 = unit_overview(main, 84, 3, units[2]) - row_1_height = math.max(row_1_height, uo_2.height()) + row_1_height = math.max(row_1_height, uo_2.get_height()) end cnc_y_start = cnc_y_start + row_1_height + 1 @@ -60,11 +60,11 @@ local function init(main) local row_2_offset = cnc_y_start uo_3 = unit_overview(main, 2, row_2_offset, units[3]) - cnc_y_start = row_2_offset + uo_3.height() + 1 + cnc_y_start = row_2_offset + uo_3.get_height() + 1 if facility.num_units == 4 then uo_4 = unit_overview(main, 84, row_2_offset, units[4]) - cnc_y_start = math.max(cnc_y_start, row_2_offset + uo_4.height() + 1) + cnc_y_start = math.max(cnc_y_start, row_2_offset + uo_4.get_height() + 1) end end @@ -73,11 +73,11 @@ local function init(main) cnc_y_start = cnc_y_start -- induction matrix and process control interfaces are 24 tall + space needed for divider - local cnc_bottom_align_start = main.height() - 26 + local cnc_bottom_align_start = main.get_height() - 26 assert(cnc_bottom_align_start >= cnc_y_start, "main display not of sufficient vertical resolution (add an additional row of monitors)") - TextBox{parent=main,y=cnc_bottom_align_start,text=util.strrep("\x8c", header.width()),alignment=TEXT_ALIGN.CENTER,height=1,fg_bg=cpair(colors.lightGray,colors.gray)} + TextBox{parent=main,y=cnc_bottom_align_start,text=util.strrep("\x8c", header.get_width()),alignment=TEXT_ALIGN.CENTER,height=1,fg_bg=cpair(colors.lightGray,colors.gray)} cnc_bottom_align_start = cnc_bottom_align_start + 2 diff --git a/graphics/element.lua b/graphics/element.lua index c6dbaa7..d0e6a3b 100644 --- a/graphics/element.lua +++ b/graphics/element.lua @@ -68,21 +68,22 @@ function element.new(args) define_completed = false, p_window = nil, ---@type table position = { x = 1, y = 1 }, ---@type coordinate_2d - child_offset = { x = 0, y = 0 }, + child_offset = { x = 0, y = 0 }, ---@type coordinate_2d bounds = { x1 = 1, y1 = 1, x2 = 1, y2 = 1 }, ---@class element_bounds next_y = 1, - children = {}, subscriptions = {}, mt = {} } - ---@class graphics_template + ---@class graphics_base local protected = { enabled = true, - value = nil, ---@type any - window = nil, ---@type table + value = nil, ---@type any + window = nil, ---@type table + content_window = nil, ---@type table|nil fg_bg = core.cpair(colors.white, colors.black), - frame = core.gframe(1, 1, 1, 1) + frame = core.gframe(1, 1, 1, 1), + children = {} } local name_brief = "graphics.element{" .. self.elem_type .. "}: " @@ -199,15 +200,15 @@ function element.new(args) -- luacheck: push ignore ---@diagnostic disable: unused-local, unused-vararg - -- dynamically insert a child element + -- handle a child element having been added ---@param id string|integer element identifier - ---@param elem graphics_element element - function protected.insert(id, elem) + ---@param child graphics_element child element + function protected.on_added(id, child) end - -- dynamically remove a child element + -- handle a child element having been removed ---@param id string|integer element identifier - function protected.remove(id) + function protected.on_removed(id) end -- handle a mouse event @@ -280,6 +281,14 @@ function element.new(args) ---@return graphics_element element, element_id id function protected.get() return public, self.id end + -- report completion of element instantiation and get the public interface + ---@nodiscard + ---@return graphics_element element, element_id id + function protected.complete() + if args.parent ~= nil then args.parent.__child_ready(self.id, public) end + return public, self.id + end + ----------- -- SETUP -- ----------- @@ -306,11 +315,19 @@ function element.new(args) -- get the window object ---@nodiscard - function public.window() return protected.window end + function public.window() return protected.content_window or protected.window end -- delete this element (hide and unsubscribe from PSIL) function public.delete() - -- hide + stop animations + -- grab parent fg/bg so we can clear cleanly + if args.parent ~= nil then + local fg_bg = args.parent.get_fg_bg() + protected.window.setBackgroundColor(fg_bg.bkg) + protected.window.setTextColor(fg_bg.fgd) + end + + -- clear, hide, and stop animations + protected.window.clear() public.hide() -- unsubscribe from PSIL @@ -320,9 +337,9 @@ function element.new(args) end -- delete all children - for k, v in pairs(self.children) do + for k, v in pairs(protected.children) do v.delete() - self.children[k] = nil + protected.children[k] = nil end end @@ -331,7 +348,7 @@ function element.new(args) -- add a child element ---@nodiscard ---@param key string|nil id - ---@param child graphics_template + ---@param child graphics_base ---@return integer|string key function public.__add_child(key, child) -- offset first automatic placement @@ -346,26 +363,34 @@ function element.new(args) local child_element = child.get() if key == nil then - table.insert(self.children, child_element) - return #self.children + table.insert(protected.children, child_element) + return #protected.children else - self.children[key] = child_element + protected.children[key] = child_element return key end end + -- actions to take upon a child element becoming ready (initial draw/construction completed) + ---@param key string|integer id + ---@param child graphics_element + function public.__child_ready(key, child) + protected.on_added(key, child) + end + -- get a child element ---@nodiscard ---@param id element_id ---@return graphics_element - function public.get_child(id) return self.children[id] end + function public.get_child(id) return protected.children[id] 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 + if protected.children[id] ~= nil then + protected.children[id].delete() + protected.children[id] = nil + protected.on_removed(id) end end @@ -374,13 +399,13 @@ function element.new(args) ---@param id element_id ---@return graphics_element|nil element function public.get_element_by_id(id) - if self.children[id] == nil then - for _, child in pairs(self.children) do + if protected.children[id] == nil then + for _, child in pairs(protected.children) do local elem = child.get_element_by_id(id) if elem ~= nil then return elem end end else - return self.children[id] + return protected.children[id] end return nil @@ -419,14 +444,14 @@ function element.new(args) -- get element width ---@nodiscard ---@return integer width - function public.width() + function public.get_width() return protected.frame.w end -- get element height ---@nodiscard ---@return integer height - function public.height() + function public.get_height() return protected.frame.h end @@ -501,7 +526,7 @@ function element.new(args) -- handle the mouse event then pass to children protected.handle_mouse(event_T) - for _, child in pairs(self.children) do child.handle_mouse(event_T) end + for _, child in pairs(protected.children) do child.handle_mouse(event_T) end end end @@ -536,7 +561,9 @@ function element.new(args) if animate ~= false then public.animate_all() end end - -- hide the element and disables animations + -- hide the element and disables animations
+ -- this alone does not cause an element to be fully hidden, it only prevents updates from being shown
+ ---@see graphics_element.content_redraw function public.hide() public.freeze_all() -- stop animations for efficiency/performance protected.window.setVisible(false) @@ -552,7 +579,7 @@ function element.new(args) function public.animate_all() if protected.window.isVisible() then public.animate() - for _, child in pairs(self.children) do child.animate_all() end + for _, child in pairs(protected.children) do child.animate_all() end end end @@ -564,7 +591,7 @@ function element.new(args) -- freeze animation(s) for this element and all its children function public.freeze_all() public.freeze() - for _, child in pairs(self.children) do child.freeze_all() end + for _, child in pairs(protected.children) do child.freeze_all() end end -- re-draw the element @@ -572,6 +599,14 @@ function element.new(args) protected.window.redraw() end + -- if a content window is set, clears it then re-draws all children + function public.content_redraw() + if protected.content_window ~= nil then + protected.content_window.clear() + for _, child in pairs(protected.children) do child.redraw() end + end + end + return protected end diff --git a/graphics/elements/animations/waiting.lua b/graphics/elements/animations/waiting.lua index 9d88c91..9dc089f 100644 --- a/graphics/elements/animations/waiting.lua +++ b/graphics/elements/animations/waiting.lua @@ -103,7 +103,7 @@ local function waiting(args) e.start_anim() - return e.get() + return e.complete() end return waiting diff --git a/graphics/elements/colormap.lua b/graphics/elements/colormap.lua index f494158..be92d83 100644 --- a/graphics/elements/colormap.lua +++ b/graphics/elements/colormap.lua @@ -28,7 +28,7 @@ local function colormap(args) e.window.setCursorPos(1, 1) e.window.blit(spaces, bkg, bkg) - return e.get() + return e.complete() end return colormap diff --git a/graphics/elements/controls/hazard_button.lua b/graphics/elements/controls/hazard_button.lua index 844a6c8..6ffe74d 100644 --- a/graphics/elements/controls/hazard_button.lua +++ b/graphics/elements/controls/hazard_button.lua @@ -199,7 +199,7 @@ local function hazard_button(args) -- initial draw of border draw_border(args.accent) - return e.get() + return e.complete() end return hazard_button diff --git a/graphics/elements/controls/multi_button.lua b/graphics/elements/controls/multi_button.lua index ca6600b..279c9a7 100644 --- a/graphics/elements/controls/multi_button.lua +++ b/graphics/elements/controls/multi_button.lua @@ -131,7 +131,7 @@ local function multi_button(args) -- initial draw draw() - return e.get() + return e.complete() end return multi_button diff --git a/graphics/elements/controls/push_button.lua b/graphics/elements/controls/push_button.lua index cfcd772..564ad3c 100644 --- a/graphics/elements/controls/push_button.lua +++ b/graphics/elements/controls/push_button.lua @@ -121,7 +121,7 @@ local function push_button(args) -- initial draw draw() - return e.get() + return e.complete() end return push_button diff --git a/graphics/elements/controls/radio_button.lua b/graphics/elements/controls/radio_button.lua index 6fc5d56..e3edf24 100644 --- a/graphics/elements/controls/radio_button.lua +++ b/graphics/elements/controls/radio_button.lua @@ -104,7 +104,7 @@ local function radio_button(args) -- initial draw draw() - return e.get() + return e.complete() end return radio_button diff --git a/graphics/elements/controls/sidebar.lua b/graphics/elements/controls/sidebar.lua index 7dae6ed..b3221b3 100644 --- a/graphics/elements/controls/sidebar.lua +++ b/graphics/elements/controls/sidebar.lua @@ -116,7 +116,7 @@ local function sidebar(args) -- initial draw draw(false) - return e.get() + return e.complete() end return sidebar diff --git a/graphics/elements/controls/spinbox_numeric.lua b/graphics/elements/controls/spinbox_numeric.lua index bcdc9e5..767d97b 100644 --- a/graphics/elements/controls/spinbox_numeric.lua +++ b/graphics/elements/controls/spinbox_numeric.lua @@ -189,7 +189,7 @@ local function spinbox(args) e.value = 0 set_digits() - return e.get() + return e.complete() end return spinbox diff --git a/graphics/elements/controls/switch_button.lua b/graphics/elements/controls/switch_button.lua index e02f506..6d2e09c 100644 --- a/graphics/elements/controls/switch_button.lua +++ b/graphics/elements/controls/switch_button.lua @@ -87,7 +87,7 @@ local function switch_button(args) draw_state() end - return e.get() + return e.complete() end return switch_button diff --git a/graphics/elements/controls/tabbar.lua b/graphics/elements/controls/tabbar.lua index e188174..da4738b 100644 --- a/graphics/elements/controls/tabbar.lua +++ b/graphics/elements/controls/tabbar.lua @@ -125,7 +125,7 @@ local function tabbar(args) -- initial draw draw() - return e.get() + return e.complete() end return tabbar diff --git a/graphics/elements/displaybox.lua b/graphics/elements/displaybox.lua index f6f520a..992f34b 100644 --- a/graphics/elements/displaybox.lua +++ b/graphics/elements/displaybox.lua @@ -17,7 +17,7 @@ local element = require("graphics.element") ---@param args displaybox_args local function displaybox(args) -- create new graphics element base object - return element.new(args).get() + return element.new(args).complete() end return displaybox diff --git a/graphics/elements/div.lua b/graphics/elements/div.lua index 53e3e84..4b6bd6a 100644 --- a/graphics/elements/div.lua +++ b/graphics/elements/div.lua @@ -19,7 +19,7 @@ local element = require("graphics.element") ---@return graphics_element element, element_id id local function div(args) -- create new graphics element base object - return element.new(args).get() + return element.new(args).complete() end return div diff --git a/graphics/elements/indicators/alight.lua b/graphics/elements/indicators/alight.lua index 2d933d6..ff9b1ad 100644 --- a/graphics/elements/indicators/alight.lua +++ b/graphics/elements/indicators/alight.lua @@ -109,7 +109,7 @@ local function alarm_indicator_light(args) e.on_update(1) e.window.write(args.label) - return e.get() + return e.complete() end return alarm_indicator_light diff --git a/graphics/elements/indicators/coremap.lua b/graphics/elements/indicators/coremap.lua index 05434a3..127a8a3 100644 --- a/graphics/elements/indicators/coremap.lua +++ b/graphics/elements/indicators/coremap.lua @@ -163,7 +163,7 @@ local function core_map(args) -- initial draw e.on_update(0) - return e.get() + return e.complete() end return core_map diff --git a/graphics/elements/indicators/data.lua b/graphics/elements/indicators/data.lua index a2b4ea9..6aa052a 100644 --- a/graphics/elements/indicators/data.lua +++ b/graphics/elements/indicators/data.lua @@ -97,7 +97,7 @@ local function data(args) -- initial value draw e.on_update(args.value) - return e.get() + return e.complete() end return data diff --git a/graphics/elements/indicators/hbar.lua b/graphics/elements/indicators/hbar.lua index f69374e..9bee59f 100644 --- a/graphics/elements/indicators/hbar.lua +++ b/graphics/elements/indicators/hbar.lua @@ -120,7 +120,7 @@ local function hbar(args) -- initialize to 0 e.on_update(0) - return e.get() + return e.complete() end return hbar diff --git a/graphics/elements/indicators/icon.lua b/graphics/elements/indicators/icon.lua index f079178..03c88fb 100644 --- a/graphics/elements/indicators/icon.lua +++ b/graphics/elements/indicators/icon.lua @@ -69,7 +69,7 @@ local function icon(args) -- initial icon draw e.on_update(args.value or 1) - return e.get() + return e.complete() end return icon diff --git a/graphics/elements/indicators/led.lua b/graphics/elements/indicators/led.lua index 6a6f829..077cab3 100644 --- a/graphics/elements/indicators/led.lua +++ b/graphics/elements/indicators/led.lua @@ -95,7 +95,7 @@ local function indicator_led(args) e.window.write(args.label) end - return e.get() + return e.complete() end return indicator_led diff --git a/graphics/elements/indicators/ledpair.lua b/graphics/elements/indicators/ledpair.lua index 94e6955..47c9a0a 100644 --- a/graphics/elements/indicators/ledpair.lua +++ b/graphics/elements/indicators/ledpair.lua @@ -109,7 +109,7 @@ local function indicator_led_pair(args) e.window.write(args.label) end - return e.get() + return e.complete() end return indicator_led_pair diff --git a/graphics/elements/indicators/ledrgb.lua b/graphics/elements/indicators/ledrgb.lua index b66d102..dbcb947 100644 --- a/graphics/elements/indicators/ledrgb.lua +++ b/graphics/elements/indicators/ledrgb.lua @@ -54,7 +54,7 @@ local function indicator_led_rgb(args) e.window.write(args.label) end - return e.get() + return e.complete() end return indicator_led_rgb diff --git a/graphics/elements/indicators/light.lua b/graphics/elements/indicators/light.lua index 8213439..d4e8b09 100644 --- a/graphics/elements/indicators/light.lua +++ b/graphics/elements/indicators/light.lua @@ -93,7 +93,7 @@ local function indicator_light(args) e.window.setCursorPos(3, 1) e.window.write(args.label) - return e.get() + return e.complete() end return indicator_light diff --git a/graphics/elements/indicators/power.lua b/graphics/elements/indicators/power.lua index b7137d7..323fe58 100644 --- a/graphics/elements/indicators/power.lua +++ b/graphics/elements/indicators/power.lua @@ -80,7 +80,7 @@ local function power(args) -- initial value draw e.on_update(args.value) - return e.get() + return e.complete() end return power diff --git a/graphics/elements/indicators/rad.lua b/graphics/elements/indicators/rad.lua index c843cf4..fc89044 100644 --- a/graphics/elements/indicators/rad.lua +++ b/graphics/elements/indicators/rad.lua @@ -85,7 +85,7 @@ local function rad(args) -- initial value draw e.on_update(types.new_zero_radiation_reading()) - return e.get() + return e.complete() end return rad diff --git a/graphics/elements/indicators/state.lua b/graphics/elements/indicators/state.lua index 3bb2831..d0e57b5 100644 --- a/graphics/elements/indicators/state.lua +++ b/graphics/elements/indicators/state.lua @@ -75,7 +75,7 @@ local function state_indicator(args) -- initial draw e.on_update(args.value or 1) - return e.get() + return e.complete() end return state_indicator diff --git a/graphics/elements/indicators/trilight.lua b/graphics/elements/indicators/trilight.lua index bbc7526..ef8a8b6 100644 --- a/graphics/elements/indicators/trilight.lua +++ b/graphics/elements/indicators/trilight.lua @@ -106,7 +106,7 @@ local function tristate_indicator_light(args) e.on_update(1) e.window.write(args.label) - return e.get() + return e.complete() end return tristate_indicator_light diff --git a/graphics/elements/indicators/vbar.lua b/graphics/elements/indicators/vbar.lua index 9c8a8f4..4cfb6e7 100644 --- a/graphics/elements/indicators/vbar.lua +++ b/graphics/elements/indicators/vbar.lua @@ -100,7 +100,7 @@ local function vbar(args) ---@param val number 0.0 to 1.0 function e.set_value(val) e.on_update(val) end - return e.get() + return e.complete() end return vbar diff --git a/graphics/elements/multipane.lua b/graphics/elements/multipane.lua index 20da7ed..790b595 100644 --- a/graphics/elements/multipane.lua +++ b/graphics/elements/multipane.lua @@ -37,7 +37,7 @@ local function multipane(args) e.set_value(1) - return e.get() + return e.complete() end return multipane diff --git a/graphics/elements/pipenet.lua b/graphics/elements/pipenet.lua index 8314fd2..5ca4745 100644 --- a/graphics/elements/pipenet.lua +++ b/graphics/elements/pipenet.lua @@ -142,7 +142,7 @@ local function pipenet(args) end - return e.get() + return e.complete() end return pipenet diff --git a/graphics/elements/rectangle.lua b/graphics/elements/rectangle.lua index b80b37c..72f9739 100644 --- a/graphics/elements/rectangle.lua +++ b/graphics/elements/rectangle.lua @@ -178,7 +178,7 @@ local function rectangle(args) end end - return e.get() + return e.complete() end return rectangle diff --git a/graphics/elements/textbox.lua b/graphics/elements/textbox.lua index 6e5717f..e72571b 100644 --- a/graphics/elements/textbox.lua +++ b/graphics/elements/textbox.lua @@ -65,7 +65,7 @@ local function textbox(args) display_text(val) end - return e.get() + return e.complete() end return textbox diff --git a/graphics/elements/tiling.lua b/graphics/elements/tiling.lua index 0dcaaf8..536ed45 100644 --- a/graphics/elements/tiling.lua +++ b/graphics/elements/tiling.lua @@ -82,7 +82,7 @@ local function tiling(args) if inner_width % 2 == 0 then alternator = not alternator end end - return e.get() + return e.complete() end return tiling diff --git a/pocket/startup.lua b/pocket/startup.lua index 9265558..c1a924c 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.3" +local POCKET_VERSION = "alpha-v0.3.4" local println = util.println local println_ts = util.println_ts diff --git a/pocket/ui/components/conn_waiting.lua b/pocket/ui/components/conn_waiting.lua index 9bbbfc0..114d165 100644 --- a/pocket/ui/components/conn_waiting.lua +++ b/pocket/ui/components/conn_waiting.lua @@ -25,7 +25,7 @@ local function init(parent, y, is_api) -- bounding box div local box = Div{parent=root,x=1,y=y,height=5} - local waiting_x = math.floor(parent.width() / 2) - 1 + local waiting_x = math.floor(parent.get_width() / 2) - 1 if is_api then WaitingAnim{parent=box,x=waiting_x,y=1,fg_bg=cpair(colors.blue,style.root.bkg)} diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index 89b5b6d..687c022 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.3" +local R_PLC_VERSION = "v1.3.4" local println = util.println local println_ts = util.println_ts diff --git a/rtu/startup.lua b/rtu/startup.lua index 0994261..c7f3a66 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.3" +local RTU_VERSION = "v1.2.4" local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 6dc7253..cf7c8fe 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -19,7 +19,7 @@ local supervisor = require("supervisor.supervisor") local svsessions = require("supervisor.session.svsessions") -local SUPERVISOR_VERSION = "v0.16.3" +local SUPERVISOR_VERSION = "v0.16.4" local println = util.println local println_ts = util.println_ts From 4c35233289c52a847a25227d7dbc97f3805b30cd Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Tue, 30 May 2023 20:43:33 -0400 Subject: [PATCH 08/14] #243 changed rectangle to use content window, significant simplification of offset logic, improved delete rendering --- coordinator/startup.lua | 2 +- graphics/element.lua | 47 ++++++++------------------------ graphics/elements/displaybox.lua | 2 ++ graphics/elements/rectangle.lua | 18 ++++++++---- pocket/startup.lua | 2 +- reactor-plc/startup.lua | 2 +- rtu/startup.lua | 2 +- supervisor/startup.lua | 2 +- 8 files changed, 31 insertions(+), 46 deletions(-) diff --git a/coordinator/startup.lua b/coordinator/startup.lua index 17fcc6f..0faf0fb 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.4" +local COORDINATOR_VERSION = "v0.15.5" local println = util.println local println_ts = util.println_ts diff --git a/graphics/element.lua b/graphics/element.lua index d0e6a3b..a775eb7 100644 --- a/graphics/element.lua +++ b/graphics/element.lua @@ -12,8 +12,6 @@ local element = {} ---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer next line if omitted ----@field offset_x? integer 0 if omitted ----@field offset_y? integer 0 if omitted ---@field width? integer parent width if omitted ---@field height? integer parent height if omitted ---@field gframe? graphics_frame frame instead of x/y/width/height @@ -103,10 +101,8 @@ function element.new(args) ------------------------- -- prepare the template - ---@param offset_x integer x offset - ---@param offset_y integer y offset ---@param next_y integer next line if no y was provided - function protected.prepare_template(offset_x, offset_y, next_y) + function protected.prepare_template(next_y) -- get frame coordinates/size if args.gframe ~= nil then protected.frame.x = args.gframe.x @@ -116,36 +112,18 @@ function element.new(args) else local w, h = self.p_window.getSize() protected.frame.x = args.x or 1 - - if args.parent ~= nil then - protected.frame.y = args.y or (next_y - offset_y) - else protected.frame.y = args.y or next_y - end - protected.frame.w = args.width or w protected.frame.h = args.height or h end - -- inner offsets - if args.offset_x ~= nil then self.child_offset.x = args.offset_x end - if args.offset_y ~= nil then self.child_offset.y = args.offset_y end - -- adjust window frame if applicable local f = protected.frame - local x = f.x - local y = f.y - - -- apply offsets if args.parent ~= nil then -- constrain to parent inner width/height local w, h = self.p_window.getSize() - f.w = math.min(f.w, w - ((2 * offset_x) + (f.x - 1))) - f.h = math.min(f.h, h - ((2 * offset_y) + (f.y - 1))) - - -- offset x/y - f.x = x + offset_x - f.y = y + offset_y + f.w = math.min(f.w, w - (f.x - 1)) + f.h = math.min(f.h, h - (f.y - 1)) end -- check frame @@ -304,7 +282,7 @@ function element.new(args) -- prepare the template if args.parent == nil then - protected.prepare_template(0, 0, 1) + protected.prepare_template(1) else self.id = args.parent.__add_child(args.id, protected) end @@ -319,14 +297,16 @@ function element.new(args) -- delete this element (hide and unsubscribe from PSIL) function public.delete() - -- grab parent fg/bg so we can clear cleanly + local fg_bg = protected.fg_bg + if args.parent ~= nil then - local fg_bg = args.parent.get_fg_bg() - protected.window.setBackgroundColor(fg_bg.bkg) - protected.window.setTextColor(fg_bg.fgd) + -- grab parent fg/bg so we can clear cleanly as a child element + fg_bg = args.parent.get_fg_bg() end -- clear, hide, and stop animations + protected.window.setBackgroundColor(fg_bg.bkg) + protected.window.setTextColor(fg_bg.fgd) protected.window.clear() public.hide() @@ -351,12 +331,7 @@ function element.new(args) ---@param child graphics_base ---@return integer|string key function public.__add_child(key, child) - -- offset first automatic placement - if self.next_y <= self.child_offset.y then - self.next_y = self.child_offset.y + 1 - end - - child.prepare_template(self.child_offset.x, self.child_offset.y, self.next_y) + child.prepare_template(self.next_y) self.next_y = child.frame.y + child.frame.h diff --git a/graphics/elements/displaybox.lua b/graphics/elements/displaybox.lua index 992f34b..3578a63 100644 --- a/graphics/elements/displaybox.lua +++ b/graphics/elements/displaybox.lua @@ -4,6 +4,7 @@ local element = require("graphics.element") ---@class displaybox_args ---@field window table +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field width? integer parent width if omitted @@ -15,6 +16,7 @@ local element = require("graphics.element") -- new root display box ---@nodiscard ---@param args displaybox_args +---@return graphics_element element, element_id id local function displaybox(args) -- create new graphics element base object return element.new(args).complete() diff --git a/graphics/elements/rectangle.lua b/graphics/elements/rectangle.lua index 72f9739..cd4b8cf 100644 --- a/graphics/elements/rectangle.lua +++ b/graphics/elements/rectangle.lua @@ -31,27 +31,35 @@ local function rectangle(args) end -- offset children + local offset_x = 0 + local offset_y = 0 if args.border ~= nil then - args.offset_x = args.border.width - args.offset_y = args.border.width + offset_x = args.border.width + offset_y = args.border.width -- slightly different y offset if the border is set to even if args.border.even then local width_x2 = (2 * args.border.width) - args.offset_y = math.floor(width_x2 / 3) + util.trinary(width_x2 % 3 > 0, 1, 0) + offset_y = math.floor(width_x2 / 3) + util.trinary(width_x2 % 3 > 0, 1, 0) end end -- create new graphics element base object local e = element.new(args) + -- create content window for child elements + e.content_window = window.create(e.window, 1 + offset_x, 1 + offset_y, e.frame.w - (2 * offset_x), e.frame.h - (2 * offset_y)) + e.content_window.setBackgroundColor(e.fg_bg.bkg) + e.content_window.setTextColor(e.fg_bg.fgd) + e.content_window.clear() + -- draw bordered box if requested -- element constructor will have drawn basic colored rectangle regardless if args.border ~= nil then e.window.setCursorPos(1, 1) - local border_width = args.offset_x - local border_height = args.offset_y + local border_width = offset_x + local border_height = offset_y local border_blit = colors.toBlit(args.border.color) local width_x2 = border_width * 2 local inner_width = e.frame.w - width_x2 diff --git a/pocket/startup.lua b/pocket/startup.lua index c1a924c..2a48042 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.4" +local POCKET_VERSION = "alpha-v0.3.5" local println = util.println local println_ts = util.println_ts diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index 687c022..cf3b08a 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.4" +local R_PLC_VERSION = "v1.3.5" local println = util.println local println_ts = util.println_ts diff --git a/rtu/startup.lua b/rtu/startup.lua index c7f3a66..1ae38ed 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.4" +local RTU_VERSION = "v1.2.5" local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE diff --git a/supervisor/startup.lua b/supervisor/startup.lua index cf7c8fe..6e2dd95 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -19,7 +19,7 @@ local supervisor = require("supervisor.supervisor") local svsessions = require("supervisor.session.svsessions") -local SUPERVISOR_VERSION = "v0.16.4" +local SUPERVISOR_VERSION = "v0.16.5" local println = util.println local println_ts = util.println_ts From ef1ec220a40ea05fdeccd7dc0af7c6957e7bcf2f Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Wed, 31 May 2023 11:44:41 -0400 Subject: [PATCH 09/14] #184 initial draft of listbox element and associated supervisor front panel test example --- graphics/element.lua | 4 +- graphics/elements/listbox.lua | 190 +++++++++++++++++++++++++++++++ supervisor/panel/front_panel.lua | 17 ++- 3 files changed, 204 insertions(+), 7 deletions(-) create mode 100644 graphics/elements/listbox.lua diff --git a/graphics/element.lua b/graphics/element.lua index a775eb7..bfeb0a5 100644 --- a/graphics/element.lua +++ b/graphics/element.lua @@ -45,6 +45,7 @@ local element = {} ---|colormap_args ---|displaybox_args ---|div_args +---|listbox_args ---|multipane_args ---|pipenet_args ---|rectangle_args @@ -66,7 +67,6 @@ function element.new(args) define_completed = false, p_window = nil, ---@type table position = { x = 1, y = 1 }, ---@type coordinate_2d - child_offset = { x = 0, y = 0 }, ---@type coordinate_2d bounds = { x1 = 1, y1 = 1, x2 = 1, y2 = 1 }, ---@class element_bounds next_y = 1, subscriptions = {}, @@ -112,7 +112,7 @@ function element.new(args) else local w, h = self.p_window.getSize() protected.frame.x = args.x or 1 - protected.frame.y = args.y or next_y + protected.frame.y = args.y or next_y protected.frame.w = args.width or w protected.frame.h = args.height or h end diff --git a/graphics/elements/listbox.lua b/graphics/elements/listbox.lua new file mode 100644 index 0000000..105c3ee --- /dev/null +++ b/graphics/elements/listbox.lua @@ -0,0 +1,190 @@ +-- Scroll-able List Box Display Graphics Element + +-- local log = require("scada-common.log") + +local core = require("graphics.core") +local element = require("graphics.element") + +local CLICK_TYPE = core.events.CLICK_TYPE + +---@class listbox_args +---@field scroll_height integer height of internal scrolling container (must fit all elements vertically tiled) +---@field item_pad? integer spacing (lines) between items in the list (default 0) +---@field parent graphics_element +---@field id? string element id +---@field x? integer 1 if omitted +---@field y? integer 1 if omitted +---@field width? integer parent width if omitted +---@field height? integer parent height if omitted +---@field gframe? graphics_frame frame instead of x/y/width/height +---@field fg_bg? cpair foreground/background colors +---@field hidden? boolean true to hide on initial draw + +---@class listbox_item +---@field id string|integer element ID +---@field e graphics_element element +---@field y integer y position +---@field h integer element height + +-- new listbox element +---@nodiscard +---@param args listbox_args +---@return graphics_element element, element_id id +local function listbox(args) + -- create new graphics element base object + local e = element.new(args) + + -- create content window for child elements + local scroll_frame = window.create(e.window, 1, 1, e.frame.w - 1, args.scroll_height, false) + e.content_window = scroll_frame + + -- item list and scroll management + local list = {} + local item_pad = args.item_pad or 0 + local scroll_offset = 0 + local content_height = 0 + local max_down_scroll = 0 + + -- bar control/tracking variables + local bar_height = 0 -- full height of bar + local bar_bounds = { 0, 0 } -- top and bottom of bar + local holding_bar = false -- bar is being held by mouse + local bar_grip_pos = 0 -- where the bar was gripped by mouse down + local mouse_last_y = 0 -- last reported y coordinate of drag + + -- draw up/down arrows + e.window.setCursorPos(e.frame.w, 1) + e.window.write("\x1e") + e.window.setCursorPos(e.frame.w, e.frame.h) + e.window.write("\x1f") + + -- render the scroll bar and re-cacluate height & bounds + local function draw_bar() + local offset = 2 + math.abs(scroll_offset) + + bar_height = math.max(math.min(e.frame.h - 2 + max_down_scroll, e.frame.h - 2), 1) + bar_bounds = { offset, (bar_height + offset) - 1 } + + for i = 2, e.frame.h - 1 do + if i >= offset and i < (bar_height + offset) then + e.window.setBackgroundColor(e.fg_bg.fgd) + else + e.window.setBackgroundColor(e.fg_bg.bkg) + end + + e.window.setCursorPos(e.frame.w, i) + e.window.write(" ") + end + + e.window.setBackgroundColor(e.fg_bg.bkg) + end + + -- update item y positions and move elements + local function update_positions() + local next_y = 1 + + scroll_frame.setVisible(false) + scroll_frame.setBackgroundColor(e.fg_bg.bkg) + scroll_frame.setTextColor(e.fg_bg.fgd) + scroll_frame.clear() + + for i = 1, #list do + local item = list[i] ---@type listbox_item + item.y = next_y + next_y = next_y + item.h + item_pad + item.e.reposition(1, item.y) + item.e.show() + end + + content_height = next_y + max_down_scroll = math.min(-1 * (content_height - (e.frame.h + 1 + item_pad)), 0) + if scroll_offset < max_down_scroll then scroll_offset = max_down_scroll end + + scroll_frame.reposition(1, 1 + scroll_offset) + scroll_frame.setVisible(true) + + draw_bar() + + -- log.info("content_height[" .. content_height .. "] max_down_scroll[" .. max_down_scroll .. "] scroll_offset[" .. scroll_offset .. "] bar_height[" .. bar_height .. "]") + end + + -- scroll down the list + local function scroll_down() + if scroll_offset > max_down_scroll then + scroll_offset = scroll_offset - 1 + update_positions() + end + end + + -- scroll up the list + local function scroll_up() + if scroll_offset < 0 then + scroll_offset = scroll_offset + 1 + update_positions() + end + end + + -- handle a child element having been added to the list + ---@param id string|integer element identifier + ---@param child graphics_element child element + function e.on_added(id, child) + table.insert(list, { id = id, e = child, y = 0, h = child.get_height() }) + update_positions() + end + + -- handle a child element having been removed from the list + ---@param id string|integer element identifier + function e.on_removed(id) + for idx, elem in ipairs(list) do + if elem.id == id then + table.remove(list, idx) + update_positions() + return + end + end + end + + -- handle mouse interaction + ---@param event mouse_interaction mouse event + function e.handle_mouse(event) + if e.enabled then + if event.type == CLICK_TYPE.TAP or event.type == CLICK_TYPE.DOWN then + if event.current.x == e.frame.w then + if event.current.y == 1 or event.current.y < bar_bounds[1] then + scroll_up() + elseif event.current.y == e.frame.h or event.current.y > bar_bounds[2] then + scroll_down() + else + -- clicked on bar + holding_bar = true + bar_grip_pos = event.current.y - bar_bounds[1] + mouse_last_y = event.current.y + end + end + elseif event.type == CLICK_TYPE.UP then + holding_bar = false + elseif event.type == CLICK_TYPE.DRAG then + if holding_bar then + -- if mouse is within vertical frame, including the grip point + if event.current.y > (1 + bar_grip_pos) and event.current.y <= ((e.frame.h - bar_height) + bar_grip_pos) then + if event.current.y < mouse_last_y then + scroll_up() + elseif event.current.y > mouse_last_y then + scroll_down() + end + + mouse_last_y = event.current.y + end + end + elseif event.type == CLICK_TYPE.SCROLL_DOWN then + scroll_down() + elseif event.type == CLICK_TYPE.SCROLL_UP then + scroll_up() + end + end + end + + return e.complete() +end + +return listbox diff --git a/supervisor/panel/front_panel.lua b/supervisor/panel/front_panel.lua index bf95c6b..940a116 100644 --- a/supervisor/panel/front_panel.lua +++ b/supervisor/panel/front_panel.lua @@ -74,7 +74,7 @@ local function init(panel) -- plc page - local plc_page = Div{parent=page_div,x=1,y=1} + local plc_page = Div{parent=page_div,x=1,y=1,hidden=true} local plc_list = Div{parent=plc_page,x=2,y=2,width=49} for i = 1, config.NUM_REACTORS do @@ -106,12 +106,19 @@ local function init(panel) -- rtu page - local rtu_page = Div{parent=page_div,x=1,y=1} - local rtu_list = Div{parent=rtu_page,x=2,y=2,width=49} + 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} -- coordinator page - local crd_page = Div{parent=page_div,x=1,y=1} + local crd_page = Div{parent=page_div,x=1,y=1,hidden=true} local crd_box = Div{parent=crd_page,x=2,y=2,width=49,height=4,fg_bg=cpair(colors.black,colors.white)} local crd_conn = LED{parent=crd_box,x=2,y=2,label="CONNECTION",colors=cpair(colors.green,colors.green_off)} @@ -133,7 +140,7 @@ local function init(panel) -- pocket page - local pkt_page = Div{parent=page_div,x=1,y=1} + 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 panes = { main_page, plc_page, rtu_page, crd_page, pkt_page } From 153a83e5693557a253acb87ebafa634297ba0d8f Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Thu, 1 Jun 2023 13:00:45 -0400 Subject: [PATCH 10/14] listbox improvements --- graphics/element.lua | 22 +++-- graphics/elements/listbox.lua | 149 +++++++++++++++++++++++++++------- 2 files changed, 138 insertions(+), 33 deletions(-) diff --git a/graphics/element.lua b/graphics/element.lua index bfeb0a5..d537171 100644 --- a/graphics/element.lua +++ b/graphics/element.lua @@ -62,7 +62,7 @@ local element = {} ---@param args graphics_args arguments function element.new(args) local self = { - id = -1, + id = nil, ---@type element_id|nil elem_type = debug.getinfo(2).name, define_completed = false, p_window = nil, ---@type table @@ -179,13 +179,13 @@ function element.new(args) ---@diagnostic disable: unused-local, unused-vararg -- handle a child element having been added - ---@param id string|integer element identifier + ---@param id element_id element identifier ---@param child graphics_element child element function protected.on_added(id, child) end -- handle a child element having been removed - ---@param id string|integer element identifier + ---@param id element_id element identifier function protected.on_removed(id) end @@ -282,6 +282,7 @@ function element.new(args) -- prepare the template if args.parent == nil then + self.id = args.id or "__ROOT__" protected.prepare_template(1) else self.id = args.parent.__add_child(args.id, protected) @@ -321,6 +322,8 @@ function element.new(args) v.delete() protected.children[k] = nil end + + args.parent.__remove_child(self.id) end -- ELEMENT TREE -- @@ -346,8 +349,17 @@ function element.new(args) end end + -- remove a child element + ---@param key element_id id + function public.__remove_child(key) + if protected.children[key] ~= nil then + protected.on_removed(key) + protected.children[key] = nil + end + end + -- actions to take upon a child element becoming ready (initial draw/construction completed) - ---@param key string|integer id + ---@param key element_id id ---@param child graphics_element function public.__child_ready(key, child) protected.on_added(key, child) @@ -364,8 +376,8 @@ function element.new(args) function public.remove(id) if protected.children[id] ~= nil then protected.children[id].delete() - protected.children[id] = nil protected.on_removed(id) + protected.children[id] = nil end end diff --git a/graphics/elements/listbox.lua b/graphics/elements/listbox.lua index 105c3ee..a5d5f20 100644 --- a/graphics/elements/listbox.lua +++ b/graphics/elements/listbox.lua @@ -1,6 +1,6 @@ -- Scroll-able List Box Display Graphics Element --- local log = require("scada-common.log") +local tcd = require("scada-common.tcallbackdsp") local core = require("graphics.core") local element = require("graphics.element") @@ -10,6 +10,8 @@ local CLICK_TYPE = core.events.CLICK_TYPE ---@class listbox_args ---@field scroll_height integer height of internal scrolling container (must fit all elements vertically tiled) ---@field item_pad? integer spacing (lines) between items in the list (default 0) +---@field nav_fg_bg? cpair foreground/background colors for scroll arrows and bar area +---@field nav_active? cpair active colors for bar held down or arrow held down ---@field parent graphics_element ---@field id? string element id ---@field x? integer 1 if omitted @@ -39,37 +41,90 @@ local function listbox(args) e.content_window = scroll_frame -- item list and scroll management - local list = {} - local item_pad = args.item_pad or 0 - local scroll_offset = 0 - local content_height = 0 + local list = {} + local item_pad = args.item_pad or 0 + local scroll_offset = 0 + local content_height = 0 local max_down_scroll = 0 - -- bar control/tracking variables - local bar_height = 0 -- full height of bar - local bar_bounds = { 0, 0 } -- top and bottom of bar - local holding_bar = false -- bar is being held by mouse - local bar_grip_pos = 0 -- where the bar was gripped by mouse down - local mouse_last_y = 0 -- last reported y coordinate of drag + local max_bar_height = e.frame.h - 2 + local bar_height = 0 -- full height of bar + local bar_bounds = { 0, 0 } -- top and bottom of bar + local bar_is_scaled = false -- if the scrollbar doesn't have a 1:1 ratio with lines + local holding_bar = false -- bar is being held by mouse + local bar_grip_pos = 0 -- where the bar was gripped by mouse down + local mouse_last_y = 0 -- last reported y coordinate of drag - -- draw up/down arrows - e.window.setCursorPos(e.frame.w, 1) - e.window.write("\x1e") - e.window.setCursorPos(e.frame.w, e.frame.h) - e.window.write("\x1f") + -- draw scroll bar arrows, optionally showing one of them as pressed + ---@param pressed_arrow? integer arrow to show as pressed (1 = scroll up, 0 = neither, -1 = scroll down) + local function draw_arrows(pressed_arrow) + local nav_fg_bg = args.nav_fg_bg or e.fg_bg + local active_fg_bg = args.nav_active or nav_fg_bg + + -- draw up/down arrows + if pressed_arrow == 1 then + e.window.setTextColor(active_fg_bg.fgd) + e.window.setBackgroundColor(active_fg_bg.bkg) + e.window.setCursorPos(e.frame.w, 1) + e.window.write("\x1e") + e.window.setTextColor(nav_fg_bg.fgd) + e.window.setBackgroundColor(nav_fg_bg.bkg) + e.window.setCursorPos(e.frame.w, e.frame.h) + e.window.write("\x1f") + elseif pressed_arrow == -1 then + e.window.setTextColor(nav_fg_bg.fgd) + e.window.setBackgroundColor(nav_fg_bg.bkg) + e.window.setCursorPos(e.frame.w, 1) + e.window.write("\x1e") + e.window.setTextColor(active_fg_bg.fgd) + e.window.setBackgroundColor(active_fg_bg.bkg) + e.window.setCursorPos(e.frame.w, e.frame.h) + e.window.write("\x1f") + else + e.window.setTextColor(nav_fg_bg.fgd) + e.window.setBackgroundColor(nav_fg_bg.bkg) + e.window.setCursorPos(e.frame.w, 1) + e.window.write("\x1e") + e.window.setCursorPos(e.frame.w, e.frame.h) + e.window.write("\x1f") + end + + e.window.setTextColor(e.fg_bg.fgd) + e.window.setBackgroundColor(e.fg_bg.bkg) + end -- render the scroll bar and re-cacluate height & bounds local function draw_bar() local offset = 2 + math.abs(scroll_offset) - bar_height = math.max(math.min(e.frame.h - 2 + max_down_scroll, e.frame.h - 2), 1) + bar_height = math.min(max_bar_height + max_down_scroll, max_bar_height) + + if bar_height < 1 then + bar_is_scaled = true + -- can't do a 1:1 ratio + -- use minimum size bar with scaled offset + local scroll_progress = scroll_offset / max_down_scroll + offset = 2 + math.floor(scroll_progress * (max_bar_height - 1)) + bar_height = 1 + else + bar_is_scaled = false + end + bar_bounds = { offset, (bar_height + offset) - 1 } for i = 2, e.frame.h - 1 do - if i >= offset and i < (bar_height + offset) then - e.window.setBackgroundColor(e.fg_bg.fgd) + if (i >= offset and i < (bar_height + offset)) and (bar_height ~= max_bar_height) then + if args.nav_fg_bg ~= nil then + e.window.setBackgroundColor(args.nav_fg_bg.fgd) + else + e.window.setBackgroundColor(e.fg_bg.fgd) + end else - e.window.setBackgroundColor(e.fg_bg.bkg) + if args.nav_fg_bg ~= nil then + e.window.setBackgroundColor(args.nav_fg_bg.bkg) + else + e.window.setBackgroundColor(e.fg_bg.bkg) + end end e.window.setCursorPos(e.frame.w, i) @@ -104,22 +159,42 @@ local function listbox(args) scroll_frame.setVisible(true) draw_bar() + end - -- log.info("content_height[" .. content_height .. "] max_down_scroll[" .. max_down_scroll .. "] scroll_offset[" .. scroll_offset .. "] bar_height[" .. bar_height .. "]") + -- determine where to scroll to based on a scrollbar being dragged without a 1:1 relationship + ---@param direction -1|1 negative 1 to scroll up by one, positive 1 to scroll down by one + local function scaled_bar_scroll(direction) + local scroll_progress = scroll_offset / max_down_scroll + local bar_position = math.floor(scroll_progress * (max_bar_height - 1)) + + -- check what moving the scroll bar up or down would mean for the scroll progress + scroll_progress = (bar_position + direction) / (max_bar_height - 1) + + return math.max(math.floor(scroll_progress * max_down_scroll), max_down_scroll) end -- scroll down the list - local function scroll_down() + local function scroll_down(scaled) if scroll_offset > max_down_scroll then - scroll_offset = scroll_offset - 1 + if scaled then + scroll_offset = scaled_bar_scroll(1) + else + scroll_offset = scroll_offset - 1 + end + update_positions() end end -- scroll up the list - local function scroll_up() + local function scroll_up(scaled) if scroll_offset < 0 then - scroll_offset = scroll_offset + 1 + if scaled then + scroll_offset = scaled_bar_scroll(-1) + else + scroll_offset = scroll_offset + 1 + end + update_positions() end end @@ -148,11 +223,25 @@ local function listbox(args) ---@param event mouse_interaction mouse event function e.handle_mouse(event) if e.enabled then - if event.type == CLICK_TYPE.TAP or event.type == CLICK_TYPE.DOWN then + if event.type == CLICK_TYPE.TAP then if event.current.x == e.frame.w then if event.current.y == 1 or event.current.y < bar_bounds[1] then + draw_arrows(1) + scroll_up() + if args.nav_active ~= nil then tcd.dispatch(0.25, function () draw_arrows(0) end) end + elseif event.current.y == e.frame.h or event.current.y > bar_bounds[2] then + draw_arrows(-1) + scroll_down() + if args.nav_active ~= nil then tcd.dispatch(0.25, function () draw_arrows(0) end) end + end + end + elseif event.type == CLICK_TYPE.DOWN then + if event.current.x == e.frame.w then + if event.current.y == 1 or event.current.y < bar_bounds[1] then + draw_arrows(1) scroll_up() elseif event.current.y == e.frame.h or event.current.y > bar_bounds[2] then + draw_arrows(-1) scroll_down() else -- clicked on bar @@ -163,14 +252,15 @@ local function listbox(args) end elseif event.type == CLICK_TYPE.UP then holding_bar = false + draw_arrows(0) elseif event.type == CLICK_TYPE.DRAG then if holding_bar then -- if mouse is within vertical frame, including the grip point if event.current.y > (1 + bar_grip_pos) and event.current.y <= ((e.frame.h - bar_height) + bar_grip_pos) then if event.current.y < mouse_last_y then - scroll_up() + scroll_up(bar_is_scaled) elseif event.current.y > mouse_last_y then - scroll_down() + scroll_down(bar_is_scaled) end mouse_last_y = event.current.y @@ -184,6 +274,9 @@ local function listbox(args) end end + draw_arrows(0) + draw_bar() + return e.complete() end From 69df5edbeb0f77f87d0ebacce881a48ba6bae59c Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 3 Jun 2023 14:33:08 -0400 Subject: [PATCH 11/14] #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 }) From 529371a0fda1341b622ce45d8340cd16acb1881b Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 3 Jun 2023 15:45:48 -0400 Subject: [PATCH 12/14] #184 support supervisor running without front panel, halved heartbeat blink rate --- install_manifest.json | 1 + supervisor/panel/front_panel.lua | 5 - supervisor/panel/pgi.lua | 8 ++ supervisor/renderer.lua | 4 + supervisor/session/coordinator.lua | 9 +- supervisor/session/plc.lua | 9 +- supervisor/session/pocket.lua | 9 +- supervisor/session/rtu.lua | 9 +- supervisor/session/svsessions.lua | 25 ++-- supervisor/startup.lua | 181 +++++++++++++++-------------- supervisor/supervisor.lua | 13 ++- 11 files changed, 152 insertions(+), 121 deletions(-) create mode 100644 install_manifest.json diff --git a/install_manifest.json b/install_manifest.json new file mode 100644 index 0000000..819e6ee --- /dev/null +++ b/install_manifest.json @@ -0,0 +1 @@ +{"versions": {"installer": "v1.2", "bootloader": "0.2", "comms": "1.4.1", "reactor-plc": "v1.3.6", "rtu": "v1.2.6", "supervisor": "v0.16.6", "coordinator": "v0.15.6", "pocket": "alpha-v0.3.6"}, "files": {"system": ["initenv.lua", "startup.lua"], "common": ["scada-common/crypto.lua", "scada-common/ppm.lua", "scada-common/comms.lua", "scada-common/psil.lua", "scada-common/tcallbackdsp.lua", "scada-common/rsio.lua", "scada-common/constants.lua", "scada-common/mqueue.lua", "scada-common/crash.lua", "scada-common/log.lua", "scada-common/types.lua", "scada-common/util.lua"], "graphics": ["graphics/element.lua", "graphics/events.lua", "graphics/flasher.lua", "graphics/core.lua", "graphics/elements/listbox.lua", "graphics/elements/textbox.lua", "graphics/elements/displaybox.lua", "graphics/elements/pipenet.lua", "graphics/elements/rectangle.lua", "graphics/elements/div.lua", "graphics/elements/multipane.lua", "graphics/elements/tiling.lua", "graphics/elements/colormap.lua", "graphics/elements/indicators/alight.lua", "graphics/elements/indicators/icon.lua", "graphics/elements/indicators/power.lua", "graphics/elements/indicators/rad.lua", "graphics/elements/indicators/state.lua", "graphics/elements/indicators/light.lua", "graphics/elements/indicators/vbar.lua", "graphics/elements/indicators/led.lua", "graphics/elements/indicators/coremap.lua", "graphics/elements/indicators/data.lua", "graphics/elements/indicators/ledpair.lua", "graphics/elements/indicators/hbar.lua", "graphics/elements/indicators/trilight.lua", "graphics/elements/indicators/ledrgb.lua", "graphics/elements/controls/switch_button.lua", "graphics/elements/controls/spinbox_numeric.lua", "graphics/elements/controls/hazard_button.lua", "graphics/elements/controls/push_button.lua", "graphics/elements/controls/radio_button.lua", "graphics/elements/controls/multi_button.lua", "graphics/elements/controls/tabbar.lua", "graphics/elements/controls/sidebar.lua", "graphics/elements/animations/waiting.lua"], "lockbox": ["lockbox/init.lua", "lockbox/LICENSE", "lockbox/kdf/pbkdf2.lua", "lockbox/util/bit.lua", "lockbox/util/array.lua", "lockbox/util/stream.lua", "lockbox/util/queue.lua", "lockbox/digest/sha2_224.lua", "lockbox/digest/sha1.lua", "lockbox/digest/sha2_256.lua", "lockbox/cipher/aes128.lua", "lockbox/cipher/aes256.lua", "lockbox/cipher/aes192.lua", "lockbox/cipher/mode/ofb.lua", "lockbox/cipher/mode/cbc.lua", "lockbox/cipher/mode/ctr.lua", "lockbox/cipher/mode/cfb.lua", "lockbox/mac/hmac.lua", "lockbox/padding/ansix923.lua", "lockbox/padding/pkcs7.lua", "lockbox/padding/zero.lua", "lockbox/padding/isoiec7816.lua"], "reactor-plc": ["reactor-plc/renderer.lua", "reactor-plc/threads.lua", "reactor-plc/databus.lua", "reactor-plc/plc.lua", "reactor-plc/config.lua", "reactor-plc/startup.lua", "reactor-plc/panel/front_panel.lua", "reactor-plc/panel/style.lua"], "rtu": ["rtu/renderer.lua", "rtu/threads.lua", "rtu/rtu.lua", "rtu/databus.lua", "rtu/modbus.lua", "rtu/config.lua", "rtu/startup.lua", "rtu/panel/front_panel.lua", "rtu/panel/style.lua", "rtu/dev/sps_rtu.lua", "rtu/dev/envd_rtu.lua", "rtu/dev/boilerv_rtu.lua", "rtu/dev/redstone_rtu.lua", "rtu/dev/sna_rtu.lua", "rtu/dev/imatrix_rtu.lua", "rtu/dev/turbinev_rtu.lua"], "supervisor": ["supervisor/renderer.lua", "supervisor/databus.lua", "supervisor/supervisor.lua", "supervisor/unit.lua", "supervisor/config.lua", "supervisor/startup.lua", "supervisor/unitlogic.lua", "supervisor/facility.lua", "supervisor/panel/pgi.lua", "supervisor/panel/front_panel.lua", "supervisor/panel/style.lua", "supervisor/panel/components/rtu_entry.lua", "supervisor/panel/components/pdg_entry.lua", "supervisor/session/coordinator.lua", "supervisor/session/svqtypes.lua", "supervisor/session/pocket.lua", "supervisor/session/svsessions.lua", "supervisor/session/rtu.lua", "supervisor/session/plc.lua", "supervisor/session/rsctl.lua", "supervisor/session/rtu/boilerv.lua", "supervisor/session/rtu/txnctrl.lua", "supervisor/session/rtu/unit_session.lua", "supervisor/session/rtu/turbinev.lua", "supervisor/session/rtu/envd.lua", "supervisor/session/rtu/imatrix.lua", "supervisor/session/rtu/sps.lua", "supervisor/session/rtu/qtypes.lua", "supervisor/session/rtu/sna.lua", "supervisor/session/rtu/redstone.lua"], "coordinator": ["coordinator/coordinator.lua", "coordinator/renderer.lua", "coordinator/iocontrol.lua", "coordinator/sounder.lua", "coordinator/config.lua", "coordinator/startup.lua", "coordinator/process.lua", "coordinator/ui/dialog.lua", "coordinator/ui/style.lua", "coordinator/ui/layout/main_view.lua", "coordinator/ui/layout/unit_view.lua", "coordinator/ui/components/reactor.lua", "coordinator/ui/components/processctl.lua", "coordinator/ui/components/unit_overview.lua", "coordinator/ui/components/boiler.lua", "coordinator/ui/components/unit_detail.lua", "coordinator/ui/components/imatrix.lua", "coordinator/ui/components/turbine.lua", "coordinator/session/api.lua", "coordinator/session/apisessions.lua"], "pocket": ["pocket/pocket.lua", "pocket/renderer.lua", "pocket/config.lua", "pocket/coreio.lua", "pocket/startup.lua", "pocket/ui/main.lua", "pocket/ui/style.lua", "pocket/ui/components/conn_waiting.lua", "pocket/ui/pages/turbine_page.lua", "pocket/ui/pages/reactor_page.lua", "pocket/ui/pages/home_page.lua", "pocket/ui/pages/unit_page.lua", "pocket/ui/pages/boiler_page.lua"]}, "depends": {"reactor-plc": ["system", "common", "graphics"], "rtu": ["system", "common", "graphics"], "supervisor": ["system", "common"], "coordinator": ["system", "common", "graphics"], "pocket": ["system", "common", "graphics"]}, "sizes": {"manifest": 5775, "system": 1991, "common": 91102, "graphics": 144089, "lockbox": 100797, "reactor-plc": 95896, "rtu": 100988, "supervisor": 310870, "coordinator": 197544, "pocket": 36338}} \ No newline at end of file diff --git a/supervisor/panel/front_panel.lua b/supervisor/panel/front_panel.lua index 86d9839..8ebc448 100644 --- a/supervisor/panel/front_panel.lua +++ b/supervisor/panel/front_panel.lua @@ -18,21 +18,16 @@ local core = require("graphics.core") local Div = require("graphics.elements.div") local ListBox = require("graphics.elements.listbox") local MultiPane = require("graphics.elements.multipane") -local Rectangle = require("graphics.elements.rectangle") local TextBox = require("graphics.elements.textbox") -local PushButton = require("graphics.elements.controls.push_button") local TabBar = require("graphics.elements.controls.tabbar") local LED = require("graphics.elements.indicators.led") -local LEDPair = require("graphics.elements.indicators.ledpair") -local RGBLED = require("graphics.elements.indicators.ledrgb") local DataIndicator = require("graphics.elements.indicators.data") local TEXT_ALIGN = core.TEXT_ALIGN local cpair = core.cpair -local border = core.border -- create new main view ---@param panel graphics_element main displaybox diff --git a/supervisor/panel/pgi.lua b/supervisor/panel/pgi.lua index 4126dee..9065f72 100644 --- a/supervisor/panel/pgi.lua +++ b/supervisor/panel/pgi.lua @@ -28,6 +28,14 @@ function pgi.link_elements(rtu_list, rtu_entry, pdg_list, pdg_entry) data.pdg_entry = pdg_entry end +-- unlink all fields, disabling the PGI +function pgi.unlink() + data.rtu_list = nil + data.pdg_list = nil + data.rtu_entry = nil + data.pdg_entry = nil +end + -- add an RTU entry to the RTU list ---@param session_id integer RTU session function pgi.create_rtu_entry(session_id) diff --git a/supervisor/renderer.lua b/supervisor/renderer.lua index 5dfb7d1..1bc70a4 100644 --- a/supervisor/renderer.lua +++ b/supervisor/renderer.lua @@ -3,6 +3,7 @@ -- local panel_view = require("supervisor.panel.front_panel") +local pgi = require("supervisor.panel.pgi") local style = require("supervisor.panel.style") local flasher = require("graphics.flasher") @@ -44,6 +45,9 @@ function renderer.close_ui() -- stop blinking indicators flasher.clear() + -- disable PGI + pgi.unlink() + -- hide to stop animation callbacks ui.display.hide() diff --git a/supervisor/session/coordinator.lua b/supervisor/session/coordinator.lua index 03a579d..36a5241 100644 --- a/supervisor/session/coordinator.lua +++ b/supervisor/session/coordinator.lua @@ -20,9 +20,6 @@ local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local SV_Q_DATA = svqtypes.SV_Q_DATA --- local println = util.println -local println = function (str) end - -- retry time constants in ms -- local INITIAL_WAIT = 1500 local RETRY_PERIOD = 1000 @@ -52,7 +49,11 @@ local PERIODICS = { ---@param out_queue mqueue out message queue ---@param timeout number communications timeout ---@param facility facility facility data table -function coordinator.new_session(id, in_queue, out_queue, timeout, facility) +---@param fp_ok boolean if the front panel UI is running +function coordinator.new_session(id, in_queue, out_queue, timeout, facility, fp_ok) + -- print a log message to the terminal as long as the UI isn't running + local function println(message) if not fp_ok then util.println_ts(message) end end + local log_header = "crdn_session(" .. id .. "): " local self = { diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index 0fb987a..1436534 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.lua @@ -16,9 +16,6 @@ local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE local PLC_AUTO_ACK = comms.PLC_AUTO_ACK local UNIT_COMMAND = comms.UNIT_COMMAND --- local println = util.println -local println = function (str) end - -- retry time constants in ms local INITIAL_WAIT = 1500 local INITIAL_AUTO_WAIT = 1000 @@ -52,7 +49,11 @@ local PERIODICS = { ---@param in_queue mqueue in message queue ---@param out_queue mqueue out message queue ---@param timeout number communications timeout -function plc.new_session(id, reactor_id, in_queue, out_queue, timeout) +---@param fp_ok boolean if the front panel UI is running +function plc.new_session(id, reactor_id, in_queue, out_queue, timeout, fp_ok) + -- print a log message to the terminal as long as the UI isn't running + local function println(message) if not fp_ok then util.println_ts(message) end end + local log_header = "plc_session(" .. id .. "): " local self = { diff --git a/supervisor/session/pocket.lua b/supervisor/session/pocket.lua index 175a235..ba6d179 100644 --- a/supervisor/session/pocket.lua +++ b/supervisor/session/pocket.lua @@ -9,9 +9,6 @@ local pocket = {} local PROTOCOL = comms.PROTOCOL local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE --- local println = util.println -local println = function (str) end - -- retry time constants in ms -- local INITIAL_WAIT = 1500 -- local RETRY_PERIOD = 1000 @@ -35,7 +32,11 @@ local PERIODICS = { ---@param in_queue mqueue in message queue ---@param out_queue mqueue out message queue ---@param timeout number communications timeout -function pocket.new_session(id, in_queue, out_queue, timeout) +---@param fp_ok boolean if the front panel UI is running +function pocket.new_session(id, in_queue, out_queue, timeout, fp_ok) + -- print a log message to the terminal as long as the UI isn't running + local function println(message) if not fp_ok then util.println_ts(message) end end + local log_header = "pdg_session(" .. id .. "): " local self = { diff --git a/supervisor/session/rtu.lua b/supervisor/session/rtu.lua index 40b47ed..2f7091c 100644 --- a/supervisor/session/rtu.lua +++ b/supervisor/session/rtu.lua @@ -24,9 +24,6 @@ local PROTOCOL = comms.PROTOCOL local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE --- local println = util.println -local println = function (str) end - local PERIODICS = { KEEP_ALIVE = 2000 } @@ -39,7 +36,11 @@ local PERIODICS = { ---@param timeout number communications timeout ---@param advertisement table RTU device advertisement ---@param facility facility facility data table -function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facility) +---@param fp_ok boolean if the front panel UI is running +function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facility, fp_ok) + -- print a log message to the terminal as long as the UI isn't running + local function println(message) if not fp_ok then util.println_ts(message) end end + local log_header = "rtu_session(" .. id .. "): " local self = { diff --git a/supervisor/session/svsessions.lua b/supervisor/session/svsessions.lua index ecd8928..a41658a 100644 --- a/supervisor/session/svsessions.lua +++ b/supervisor/session/svsessions.lua @@ -35,6 +35,7 @@ svsessions.SESSION_TYPE = SESSION_TYPE local self = { modem = nil, ---@type table|nil + fp_ok = false, num_reactors = 0, facility = nil, ---@type facility|nil sessions = { rtu = {}, plc = {}, coord = {}, pdg = {} }, @@ -196,11 +197,13 @@ end -- PUBLIC FUNCTIONS -- -- initialize svsessions ----@param modem table ----@param num_reactors integer ----@param cooling_conf table -function svsessions.init(modem, num_reactors, cooling_conf) +---@param modem table modem device +---@param fp_ok boolean front panel active +---@param num_reactors integer number of reactors +---@param cooling_conf table cooling configuration definition +function svsessions.init(modem, fp_ok, num_reactors, cooling_conf) self.modem = modem + self.fp_ok = fp_ok self.num_reactors = num_reactors self.facility = facility.new(num_reactors, cooling_conf) end @@ -308,13 +311,15 @@ function svsessions.establish_plc_session(local_port, remote_port, for_reactor, instance = nil ---@type plc_session } - plc_s.instance = plc.new_session(self.next_ids.plc, for_reactor, plc_s.in_queue, plc_s.out_queue, config.PLC_TIMEOUT) + plc_s.instance = plc.new_session(self.next_ids.plc, for_reactor, plc_s.in_queue, plc_s.out_queue, + config.PLC_TIMEOUT, self.fp_ok) table.insert(self.sessions.plc, plc_s) local units = self.facility.get_units() units[for_reactor].link_plc_session(plc_s) - 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)) databus.tx_plc_connected(for_reactor, version, remote_port) @@ -348,7 +353,8 @@ function svsessions.establish_rtu_session(local_port, remote_port, advertisement instance = nil ---@type rtu_session } - rtu_s.instance = rtu.new_session(self.next_ids.rtu, rtu_s.in_queue, rtu_s.out_queue, config.RTU_TIMEOUT, advertisement, self.facility) + rtu_s.instance = rtu.new_session(self.next_ids.rtu, rtu_s.in_queue, rtu_s.out_queue, config.RTU_TIMEOUT, advertisement, + self.facility, self.fp_ok) table.insert(self.sessions.rtu, rtu_s) log.debug("established new RTU session to " .. remote_port .. " with ID " .. self.next_ids.rtu) @@ -381,7 +387,8 @@ function svsessions.establish_coord_session(local_port, remote_port, version) instance = nil ---@type coord_session } - coord_s.instance = coordinator.new_session(self.next_ids.coord, coord_s.in_queue, coord_s.out_queue, config.CRD_TIMEOUT, self.facility) + coord_s.instance = coordinator.new_session(self.next_ids.coord, coord_s.in_queue, coord_s.out_queue, config.CRD_TIMEOUT, + self.facility, self.fp_ok) table.insert(self.sessions.coord, coord_s) log.debug("established new coordinator session to " .. remote_port .. " with ID " .. self.next_ids.coord) @@ -417,7 +424,7 @@ function svsessions.establish_pdg_session(local_port, remote_port, version) instance = nil ---@type pdg_session } - pdg_s.instance = pocket.new_session(self.next_ids.pdg, pdg_s.in_queue, pdg_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, self.fp_ok) table.insert(self.sessions.pdg, pdg_s) log.debug("established new pocket diagnostics session to " .. remote_port .. " with ID " .. self.next_ids.pdg) diff --git a/supervisor/startup.lua b/supervisor/startup.lua index cdae63e..d0f95a8 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -108,93 +108,104 @@ local function main() println_ts(util.c("UI error: ", message)) log.error(util.c("GUI crashed with error ", message)) else - -- start comms, open all channels - local superv_comms = supervisor.comms(SUPERVISOR_VERSION, config.NUM_REACTORS, config.REACTOR_COOLING, modem, - config.SCADA_DEV_LISTEN, config.SCADA_SV_CTL_LISTEN, config.TRUSTED_RANGE) - - -- base loop clock (6.67Hz, 3 ticks) - local MAIN_CLOCK = 0.15 - local loop_clock = util.new_clock(MAIN_CLOCK) - - -- start clock - loop_clock.start() - - -- event loop - while true do - local event, param1, param2, param3, param4, param5 = util.pull_event() - - -- handle event - if event == "peripheral_detach" then - local type, device = ppm.handle_unmount(param1) - - if type ~= nil and device ~= nil then - if type == "modem" then - -- we only care if this is our wireless modem - if device == modem then - log.warning("comms modem disconnected") - databus.tx_hw_modem(false) - else - log.warning("non-comms modem disconnected") - end - end - end - elseif event == "peripheral" then - local type, device = ppm.mount(param1) - - if type ~= nil and device ~= nil then - if type == "modem" then - if device.isWireless() then - -- reconnected modem - modem = device - superv_comms.reconnect_modem(modem) - - log.info("comms modem reconnected") - - databus.tx_hw_modem(true) - else - log.info("wired modem reconnected") - end - end - end - elseif event == "timer" and loop_clock.is_clock(param1) then - -- main loop tick - databus.heartbeat() - - -- iterate sessions - svsessions.iterate_all() - - -- free any closed sessions - svsessions.free_all_closed() - - loop_clock.start() - 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) - superv_comms.handle_packet(packet) - elseif event == "mouse_click" or event == "mouse_up" or event == "mouse_drag" or event == "mouse_scroll" then - -- handle a mouse event - renderer.handle_mouse(core.events.new_mouse_event(event, param1, param2, param3)) - end - - -- check for termination request - if event == "terminate" or ppm.should_terminate() then - log.info("terminate requested, closing sessions...") - svsessions.close_all() - log.info("sessions closed") - break - end - end - - renderer.close_ui() + -- redefine println_ts local to not print as we have the front panel running + println_ts = function (_) end end - println_ts("exited") + -- start comms, open all channels + local superv_comms = supervisor.comms(SUPERVISOR_VERSION, config.NUM_REACTORS, config.REACTOR_COOLING, modem, + config.SCADA_DEV_LISTEN, config.SCADA_SV_CTL_LISTEN, config.TRUSTED_RANGE, fp_ok) + + -- base loop clock (6.67Hz, 3 ticks) + local MAIN_CLOCK = 0.15 + local loop_clock = util.new_clock(MAIN_CLOCK) + + -- start clock + loop_clock.start() + + -- halve the rate heartbeat LED flash + local heartbeat_toggle = true + + -- event loop + while true do + local event, param1, param2, param3, param4, param5 = util.pull_event() + + -- handle event + if event == "peripheral_detach" then + local type, device = ppm.handle_unmount(param1) + + if type ~= nil and device ~= nil then + if type == "modem" then + -- we only care if this is our wireless modem + if device == modem then + println_ts("wireless modem disconnected!") + log.warning("comms modem disconnected") + databus.tx_hw_modem(false) + else + log.warning("non-comms modem disconnected") + end + end + end + elseif event == "peripheral" then + local type, device = ppm.mount(param1) + + if type ~= nil and device ~= nil then + if type == "modem" then + if device.isWireless() then + -- reconnected modem + modem = device + superv_comms.reconnect_modem(modem) + + println_ts("wireless modem reconnected.") + log.info("comms modem reconnected") + + databus.tx_hw_modem(true) + else + log.info("wired modem reconnected") + end + end + end + elseif event == "timer" and loop_clock.is_clock(param1) then + -- main loop tick + + if heartbeat_toggle then databus.heartbeat() end + heartbeat_toggle = not heartbeat_toggle + + -- iterate sessions + svsessions.iterate_all() + + -- free any closed sessions + svsessions.free_all_closed() + + loop_clock.start() + 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) + superv_comms.handle_packet(packet) + elseif event == "mouse_click" or event == "mouse_up" or event == "mouse_drag" or event == "mouse_scroll" then + -- handle a mouse event + renderer.handle_mouse(core.events.new_mouse_event(event, param1, param2, param3)) + end + + -- check for termination request + if event == "terminate" or ppm.should_terminate() then + println_ts("closing sesssions...") + log.info("terminate requested, closing sessions...") + svsessions.close_all() + log.info("sessions closed") + break + end + end + + renderer.close_ui() + + util.println_ts("exited") log.info("exited") end diff --git a/supervisor/supervisor.lua b/supervisor/supervisor.lua index 0424b53..6a27c0e 100644 --- a/supervisor/supervisor.lua +++ b/supervisor/supervisor.lua @@ -11,9 +11,6 @@ local DEVICE_TYPE = comms.DEVICE_TYPE local ESTABLISH_ACK = comms.ESTABLISH_ACK local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE --- local println = util.println -local println = function (str) end - -- supervisory controller communications ---@nodiscard ---@param _version string supervisor version @@ -23,8 +20,12 @@ local println = function (str) end ---@param dev_listen integer listening port for PLC/RTU devices ---@param svctl_listen integer listening port for supervisor access ---@param range integer trusted device connection range +---@param fp_ok boolean if the front panel UI is running ---@diagnostic disable-next-line: unused-local -function supervisor.comms(_version, num_reactors, cooling_conf, modem, dev_listen, svctl_listen, range) +function supervisor.comms(_version, num_reactors, cooling_conf, modem, dev_listen, svctl_listen, range, fp_ok) + -- print a log message to the terminal as long as the UI isn't running + local function println(message) if not fp_ok then util.println_ts(message) end end + local self = { last_est_acks = {} } @@ -42,8 +43,8 @@ function supervisor.comms(_version, num_reactors, cooling_conf, modem, dev_liste _conf_channels() - -- link modem to svsessions - svsessions.init(modem, num_reactors, cooling_conf) + -- pass modem, status, and config data to svsessions + svsessions.init(modem, fp_ok, num_reactors, cooling_conf) -- send an establish request response to a PLC/RTU ---@param dest integer From 24a72755439f94e5eecc3267642195a30fc5a064 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 3 Jun 2023 15:50:44 -0400 Subject: [PATCH 13/14] fixed trailing whitespace --- supervisor/panel/front_panel.lua | 2 +- supervisor/session/svsessions.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/supervisor/panel/front_panel.lua b/supervisor/panel/front_panel.lua index 8ebc448..8cdcf76 100644 --- a/supervisor/panel/front_panel.lua +++ b/supervisor/panel/front_panel.lua @@ -56,7 +56,7 @@ local function init(panel) modem.register(databus.ps, "has_modem", modem.update) - -- + -- -- about footer -- diff --git a/supervisor/session/svsessions.lua b/supervisor/session/svsessions.lua index a41658a..5d22e3d 100644 --- a/supervisor/session/svsessions.lua +++ b/supervisor/session/svsessions.lua @@ -318,7 +318,7 @@ function svsessions.establish_plc_session(local_port, remote_port, for_reactor, local units = self.facility.get_units() units[for_reactor].link_plc_session(plc_s) - log.debug(util.c("established new PLC session to ", remote_port, " with ID ", self.next_ids.plc, + log.debug(util.c("established new PLC session to ", remote_port, " with ID ", self.next_ids.plc, " for reactor ", for_reactor)) databus.tx_plc_connected(for_reactor, version, remote_port) From b4932b33b6854b2c45b142da751717b176935004 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 3 Jun 2023 17:31:06 -0400 Subject: [PATCH 14/14] code cleanup --- graphics/elements/indicators/data.lua | 7 +++---- graphics/elements/listbox.lua | 6 +++--- install_manifest.json | 2 +- supervisor/databus.lua | 14 +++++++------- supervisor/startup.lua | 2 +- supervisor/supervisor.lua | 2 +- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/graphics/elements/indicators/data.lua b/graphics/elements/indicators/data.lua index 6aa052a..9282a03 100644 --- a/graphics/elements/indicators/data.lua +++ b/graphics/elements/indicators/data.lua @@ -44,8 +44,9 @@ local function data(args) e.window.setCursorPos(1, 1) e.window.write(args.label) - local label_len = string.len(args.label) - local data_start = 1 + local value_color = e.fg_bg.fgd + local label_len = string.len(args.label) + local data_start = 1 local clear_width = args.width if label_len > 0 then @@ -53,8 +54,6 @@ local function data(args) clear_width = args.width - (label_len + 1) end - local value_color = e.fg_bg.fgd - -- on state change ---@param value any new value function e.on_update(value) diff --git a/graphics/elements/listbox.lua b/graphics/elements/listbox.lua index a5d5f20..87a274d 100644 --- a/graphics/elements/listbox.lua +++ b/graphics/elements/listbox.lua @@ -56,7 +56,7 @@ local function listbox(args) local mouse_last_y = 0 -- last reported y coordinate of drag -- draw scroll bar arrows, optionally showing one of them as pressed - ---@param pressed_arrow? integer arrow to show as pressed (1 = scroll up, 0 = neither, -1 = scroll down) + ---@param pressed_arrow? 1|0|-1 arrow to show as pressed (1 = scroll up, 0 = neither, -1 = scroll down) local function draw_arrows(pressed_arrow) local nav_fg_bg = args.nav_fg_bg or e.fg_bg local active_fg_bg = args.nav_active or nav_fg_bg @@ -200,7 +200,7 @@ local function listbox(args) end -- handle a child element having been added to the list - ---@param id string|integer element identifier + ---@param id element_id element identifier ---@param child graphics_element child element function e.on_added(id, child) table.insert(list, { id = id, e = child, y = 0, h = child.get_height() }) @@ -208,7 +208,7 @@ local function listbox(args) end -- handle a child element having been removed from the list - ---@param id string|integer element identifier + ---@param id element_id element identifier function e.on_removed(id) for idx, elem in ipairs(list) do if elem.id == id then diff --git a/install_manifest.json b/install_manifest.json index 819e6ee..a2f4b51 100644 --- a/install_manifest.json +++ b/install_manifest.json @@ -1 +1 @@ -{"versions": {"installer": "v1.2", "bootloader": "0.2", "comms": "1.4.1", "reactor-plc": "v1.3.6", "rtu": "v1.2.6", "supervisor": "v0.16.6", "coordinator": "v0.15.6", "pocket": "alpha-v0.3.6"}, "files": {"system": ["initenv.lua", "startup.lua"], "common": ["scada-common/crypto.lua", "scada-common/ppm.lua", "scada-common/comms.lua", "scada-common/psil.lua", "scada-common/tcallbackdsp.lua", "scada-common/rsio.lua", "scada-common/constants.lua", "scada-common/mqueue.lua", "scada-common/crash.lua", "scada-common/log.lua", "scada-common/types.lua", "scada-common/util.lua"], "graphics": ["graphics/element.lua", "graphics/events.lua", "graphics/flasher.lua", "graphics/core.lua", "graphics/elements/listbox.lua", "graphics/elements/textbox.lua", "graphics/elements/displaybox.lua", "graphics/elements/pipenet.lua", "graphics/elements/rectangle.lua", "graphics/elements/div.lua", "graphics/elements/multipane.lua", "graphics/elements/tiling.lua", "graphics/elements/colormap.lua", "graphics/elements/indicators/alight.lua", "graphics/elements/indicators/icon.lua", "graphics/elements/indicators/power.lua", "graphics/elements/indicators/rad.lua", "graphics/elements/indicators/state.lua", "graphics/elements/indicators/light.lua", "graphics/elements/indicators/vbar.lua", "graphics/elements/indicators/led.lua", "graphics/elements/indicators/coremap.lua", "graphics/elements/indicators/data.lua", "graphics/elements/indicators/ledpair.lua", "graphics/elements/indicators/hbar.lua", "graphics/elements/indicators/trilight.lua", "graphics/elements/indicators/ledrgb.lua", "graphics/elements/controls/switch_button.lua", "graphics/elements/controls/spinbox_numeric.lua", "graphics/elements/controls/hazard_button.lua", "graphics/elements/controls/push_button.lua", "graphics/elements/controls/radio_button.lua", "graphics/elements/controls/multi_button.lua", "graphics/elements/controls/tabbar.lua", "graphics/elements/controls/sidebar.lua", "graphics/elements/animations/waiting.lua"], "lockbox": ["lockbox/init.lua", "lockbox/LICENSE", "lockbox/kdf/pbkdf2.lua", "lockbox/util/bit.lua", "lockbox/util/array.lua", "lockbox/util/stream.lua", "lockbox/util/queue.lua", "lockbox/digest/sha2_224.lua", "lockbox/digest/sha1.lua", "lockbox/digest/sha2_256.lua", "lockbox/cipher/aes128.lua", "lockbox/cipher/aes256.lua", "lockbox/cipher/aes192.lua", "lockbox/cipher/mode/ofb.lua", "lockbox/cipher/mode/cbc.lua", "lockbox/cipher/mode/ctr.lua", "lockbox/cipher/mode/cfb.lua", "lockbox/mac/hmac.lua", "lockbox/padding/ansix923.lua", "lockbox/padding/pkcs7.lua", "lockbox/padding/zero.lua", "lockbox/padding/isoiec7816.lua"], "reactor-plc": ["reactor-plc/renderer.lua", "reactor-plc/threads.lua", "reactor-plc/databus.lua", "reactor-plc/plc.lua", "reactor-plc/config.lua", "reactor-plc/startup.lua", "reactor-plc/panel/front_panel.lua", "reactor-plc/panel/style.lua"], "rtu": ["rtu/renderer.lua", "rtu/threads.lua", "rtu/rtu.lua", "rtu/databus.lua", "rtu/modbus.lua", "rtu/config.lua", "rtu/startup.lua", "rtu/panel/front_panel.lua", "rtu/panel/style.lua", "rtu/dev/sps_rtu.lua", "rtu/dev/envd_rtu.lua", "rtu/dev/boilerv_rtu.lua", "rtu/dev/redstone_rtu.lua", "rtu/dev/sna_rtu.lua", "rtu/dev/imatrix_rtu.lua", "rtu/dev/turbinev_rtu.lua"], "supervisor": ["supervisor/renderer.lua", "supervisor/databus.lua", "supervisor/supervisor.lua", "supervisor/unit.lua", "supervisor/config.lua", "supervisor/startup.lua", "supervisor/unitlogic.lua", "supervisor/facility.lua", "supervisor/panel/pgi.lua", "supervisor/panel/front_panel.lua", "supervisor/panel/style.lua", "supervisor/panel/components/rtu_entry.lua", "supervisor/panel/components/pdg_entry.lua", "supervisor/session/coordinator.lua", "supervisor/session/svqtypes.lua", "supervisor/session/pocket.lua", "supervisor/session/svsessions.lua", "supervisor/session/rtu.lua", "supervisor/session/plc.lua", "supervisor/session/rsctl.lua", "supervisor/session/rtu/boilerv.lua", "supervisor/session/rtu/txnctrl.lua", "supervisor/session/rtu/unit_session.lua", "supervisor/session/rtu/turbinev.lua", "supervisor/session/rtu/envd.lua", "supervisor/session/rtu/imatrix.lua", "supervisor/session/rtu/sps.lua", "supervisor/session/rtu/qtypes.lua", "supervisor/session/rtu/sna.lua", "supervisor/session/rtu/redstone.lua"], "coordinator": ["coordinator/coordinator.lua", "coordinator/renderer.lua", "coordinator/iocontrol.lua", "coordinator/sounder.lua", "coordinator/config.lua", "coordinator/startup.lua", "coordinator/process.lua", "coordinator/ui/dialog.lua", "coordinator/ui/style.lua", "coordinator/ui/layout/main_view.lua", "coordinator/ui/layout/unit_view.lua", "coordinator/ui/components/reactor.lua", "coordinator/ui/components/processctl.lua", "coordinator/ui/components/unit_overview.lua", "coordinator/ui/components/boiler.lua", "coordinator/ui/components/unit_detail.lua", "coordinator/ui/components/imatrix.lua", "coordinator/ui/components/turbine.lua", "coordinator/session/api.lua", "coordinator/session/apisessions.lua"], "pocket": ["pocket/pocket.lua", "pocket/renderer.lua", "pocket/config.lua", "pocket/coreio.lua", "pocket/startup.lua", "pocket/ui/main.lua", "pocket/ui/style.lua", "pocket/ui/components/conn_waiting.lua", "pocket/ui/pages/turbine_page.lua", "pocket/ui/pages/reactor_page.lua", "pocket/ui/pages/home_page.lua", "pocket/ui/pages/unit_page.lua", "pocket/ui/pages/boiler_page.lua"]}, "depends": {"reactor-plc": ["system", "common", "graphics"], "rtu": ["system", "common", "graphics"], "supervisor": ["system", "common"], "coordinator": ["system", "common", "graphics"], "pocket": ["system", "common", "graphics"]}, "sizes": {"manifest": 5775, "system": 1991, "common": 91102, "graphics": 144089, "lockbox": 100797, "reactor-plc": 95896, "rtu": 100988, "supervisor": 310870, "coordinator": 197544, "pocket": 36338}} \ No newline at end of file +{"versions": {"installer": "v1.2", "bootloader": "0.2", "comms": "1.4.1", "reactor-plc": "v1.3.6", "rtu": "v1.2.6", "supervisor": "v0.16.6", "coordinator": "v0.15.6", "pocket": "alpha-v0.3.6"}, "files": {"system": ["initenv.lua", "startup.lua"], "common": ["scada-common/crypto.lua", "scada-common/ppm.lua", "scada-common/comms.lua", "scada-common/psil.lua", "scada-common/tcallbackdsp.lua", "scada-common/rsio.lua", "scada-common/constants.lua", "scada-common/mqueue.lua", "scada-common/crash.lua", "scada-common/log.lua", "scada-common/types.lua", "scada-common/util.lua"], "graphics": ["graphics/element.lua", "graphics/events.lua", "graphics/flasher.lua", "graphics/core.lua", "graphics/elements/listbox.lua", "graphics/elements/textbox.lua", "graphics/elements/displaybox.lua", "graphics/elements/pipenet.lua", "graphics/elements/rectangle.lua", "graphics/elements/div.lua", "graphics/elements/multipane.lua", "graphics/elements/tiling.lua", "graphics/elements/colormap.lua", "graphics/elements/indicators/alight.lua", "graphics/elements/indicators/icon.lua", "graphics/elements/indicators/power.lua", "graphics/elements/indicators/rad.lua", "graphics/elements/indicators/state.lua", "graphics/elements/indicators/light.lua", "graphics/elements/indicators/vbar.lua", "graphics/elements/indicators/led.lua", "graphics/elements/indicators/coremap.lua", "graphics/elements/indicators/data.lua", "graphics/elements/indicators/ledpair.lua", "graphics/elements/indicators/hbar.lua", "graphics/elements/indicators/trilight.lua", "graphics/elements/indicators/ledrgb.lua", "graphics/elements/controls/switch_button.lua", "graphics/elements/controls/spinbox_numeric.lua", "graphics/elements/controls/hazard_button.lua", "graphics/elements/controls/push_button.lua", "graphics/elements/controls/radio_button.lua", "graphics/elements/controls/multi_button.lua", "graphics/elements/controls/tabbar.lua", "graphics/elements/controls/sidebar.lua", "graphics/elements/animations/waiting.lua"], "lockbox": ["lockbox/init.lua", "lockbox/LICENSE", "lockbox/kdf/pbkdf2.lua", "lockbox/util/bit.lua", "lockbox/util/array.lua", "lockbox/util/stream.lua", "lockbox/util/queue.lua", "lockbox/digest/sha2_224.lua", "lockbox/digest/sha1.lua", "lockbox/digest/sha2_256.lua", "lockbox/cipher/aes128.lua", "lockbox/cipher/aes256.lua", "lockbox/cipher/aes192.lua", "lockbox/cipher/mode/ofb.lua", "lockbox/cipher/mode/cbc.lua", "lockbox/cipher/mode/ctr.lua", "lockbox/cipher/mode/cfb.lua", "lockbox/mac/hmac.lua", "lockbox/padding/ansix923.lua", "lockbox/padding/pkcs7.lua", "lockbox/padding/zero.lua", "lockbox/padding/isoiec7816.lua"], "reactor-plc": ["reactor-plc/renderer.lua", "reactor-plc/threads.lua", "reactor-plc/databus.lua", "reactor-plc/plc.lua", "reactor-plc/config.lua", "reactor-plc/startup.lua", "reactor-plc/panel/front_panel.lua", "reactor-plc/panel/style.lua"], "rtu": ["rtu/renderer.lua", "rtu/threads.lua", "rtu/rtu.lua", "rtu/databus.lua", "rtu/modbus.lua", "rtu/config.lua", "rtu/startup.lua", "rtu/panel/front_panel.lua", "rtu/panel/style.lua", "rtu/dev/sps_rtu.lua", "rtu/dev/envd_rtu.lua", "rtu/dev/boilerv_rtu.lua", "rtu/dev/redstone_rtu.lua", "rtu/dev/sna_rtu.lua", "rtu/dev/imatrix_rtu.lua", "rtu/dev/turbinev_rtu.lua"], "supervisor": ["supervisor/renderer.lua", "supervisor/databus.lua", "supervisor/supervisor.lua", "supervisor/unit.lua", "supervisor/config.lua", "supervisor/startup.lua", "supervisor/unitlogic.lua", "supervisor/facility.lua", "supervisor/panel/pgi.lua", "supervisor/panel/front_panel.lua", "supervisor/panel/style.lua", "supervisor/panel/components/rtu_entry.lua", "supervisor/panel/components/pdg_entry.lua", "supervisor/session/coordinator.lua", "supervisor/session/svqtypes.lua", "supervisor/session/pocket.lua", "supervisor/session/svsessions.lua", "supervisor/session/rtu.lua", "supervisor/session/plc.lua", "supervisor/session/rsctl.lua", "supervisor/session/rtu/boilerv.lua", "supervisor/session/rtu/txnctrl.lua", "supervisor/session/rtu/unit_session.lua", "supervisor/session/rtu/turbinev.lua", "supervisor/session/rtu/envd.lua", "supervisor/session/rtu/imatrix.lua", "supervisor/session/rtu/sps.lua", "supervisor/session/rtu/qtypes.lua", "supervisor/session/rtu/sna.lua", "supervisor/session/rtu/redstone.lua"], "coordinator": ["coordinator/coordinator.lua", "coordinator/renderer.lua", "coordinator/iocontrol.lua", "coordinator/sounder.lua", "coordinator/config.lua", "coordinator/startup.lua", "coordinator/process.lua", "coordinator/ui/dialog.lua", "coordinator/ui/style.lua", "coordinator/ui/layout/main_view.lua", "coordinator/ui/layout/unit_view.lua", "coordinator/ui/components/reactor.lua", "coordinator/ui/components/processctl.lua", "coordinator/ui/components/unit_overview.lua", "coordinator/ui/components/boiler.lua", "coordinator/ui/components/unit_detail.lua", "coordinator/ui/components/imatrix.lua", "coordinator/ui/components/turbine.lua", "coordinator/session/api.lua", "coordinator/session/apisessions.lua"], "pocket": ["pocket/pocket.lua", "pocket/renderer.lua", "pocket/config.lua", "pocket/coreio.lua", "pocket/startup.lua", "pocket/ui/main.lua", "pocket/ui/style.lua", "pocket/ui/components/conn_waiting.lua", "pocket/ui/pages/turbine_page.lua", "pocket/ui/pages/reactor_page.lua", "pocket/ui/pages/home_page.lua", "pocket/ui/pages/unit_page.lua", "pocket/ui/pages/boiler_page.lua"]}, "depends": {"reactor-plc": ["system", "common", "graphics"], "rtu": ["system", "common", "graphics"], "supervisor": ["system", "common"], "coordinator": ["system", "common", "graphics"], "pocket": ["system", "common", "graphics"]}, "sizes": {"manifest": 5775, "system": 1991, "common": 91102, "graphics": 144082, "lockbox": 100797, "reactor-plc": 95896, "rtu": 100988, "supervisor": 310851, "coordinator": 197544, "pocket": 36338}} \ No newline at end of file diff --git a/supervisor/databus.lua b/supervisor/databus.lua index 88e4ed3..a1e947e 100644 --- a/supervisor/databus.lua +++ b/supervisor/databus.lua @@ -15,10 +15,10 @@ databus.ps = psil.create() function databus.heartbeat() databus.ps.toggle("heartbeat") end -- transmit firmware versions across the bus ----@param plc_v string supervisor version +---@param sv_v string supervisor version ---@param comms_v string comms version -function databus.tx_versions(plc_v, comms_v) - databus.ps.publish("version", plc_v) +function databus.tx_versions(sv_v, comms_v) + databus.ps.publish("version", sv_v) databus.ps.publish("comms_version", comms_v) end @@ -38,7 +38,7 @@ function databus.tx_plc_connected(reactor_id, fw, channel) databus.ps.publish("plc_" .. reactor_id .. "_chan", tostring(channel)) end --- transmit PLC session connection state +-- transmit PLC disconnected ---@param reactor_id integer reactor unit ID function databus.tx_plc_disconnected(reactor_id) databus.ps.publish("plc_" .. reactor_id .. "_fw", " ------- ") @@ -110,7 +110,7 @@ function databus.tx_crd_connected(fw, channel) databus.ps.publish("crd_chan", tostring(channel)) end --- transmit coordinator session connection state +-- transmit coordinator disconnected function databus.tx_crd_disconnected() databus.ps.publish("crd_fw", " ------- ") databus.ps.publish("crd_conn", false) @@ -133,7 +133,7 @@ function databus.tx_crd_rtt(rtt) end end --- transmit PDG firmware version and session connection state +-- transmit PKT firmware version and PDG session connection state ---@param session_id integer PDG session ---@param fw string firmware version ---@param channel integer PDG remote port @@ -143,7 +143,7 @@ function databus.tx_pdg_connected(session_id, fw, channel) pgi.create_pdg_entry(session_id) end --- transmit PDG disconnected +-- transmit PDG session disconnected ---@param session_id integer PDG session function databus.tx_pdg_disconnected(session_id) pgi.delete_pdg_entry(session_id) diff --git a/supervisor/startup.lua b/supervisor/startup.lua index d0f95a8..06853ef 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -195,7 +195,7 @@ local function main() -- check for termination request if event == "terminate" or ppm.should_terminate() then - println_ts("closing sesssions...") + println_ts("closing sessions...") log.info("terminate requested, closing sessions...") svsessions.close_all() log.info("sessions closed") diff --git a/supervisor/supervisor.lua b/supervisor/supervisor.lua index 6a27c0e..874aaa9 100644 --- a/supervisor/supervisor.lua +++ b/supervisor/supervisor.lua @@ -308,7 +308,7 @@ function supervisor.comms(_version, num_reactors, cooling_conf, modem, dev_liste -- this is an attempt to establish a new pocket diagnostic session local s_id = svsessions.establish_pdg_session(l_port, r_port, firmware_v) - println(util.c("PDG (", firmware_v, ") [:", r_port, "] \xbb connected")) + println(util.c("PKT (", 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 })