From 35bbd14cbc8e655d37b459d012288964a7af7896 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Tue, 1 Oct 2024 16:35:04 +0000 Subject: [PATCH 01/11] #552 only modify sidebar if app is open --- pocket/pocket.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pocket/pocket.lua b/pocket/pocket.lua index e759160..b8038f5 100644 --- a/pocket/pocket.lua +++ b/pocket/pocket.lua @@ -167,8 +167,11 @@ function pocket.init_nav(smem) -- configure the sidebar ---@param items sidebar_entry[] function app.set_sidebar(items) - app.sidebar_items = items - if self.sidebar then self.sidebar.update(items) end + -- only modify the sidebar if this app is still open + if self.cur_app == app_id then + app.sidebar_items = items + if self.sidebar then self.sidebar.update(items) end + end end -- function to run on initial load into memory From 966ca94775d004bf8bb6fab744c61030139e5cbd Mon Sep 17 00:00:00 2001 From: Mikayla Date: Fri, 4 Oct 2024 02:33:26 +0000 Subject: [PATCH 02/11] added control app update message for better performance --- coordinator/session/pocket.lua | 20 ++++++++++++ coordinator/startup.lua | 2 +- pocket/iocontrol.lua | 58 +++++++++++++++++++++++++++++++++- pocket/pocket.lua | 9 ++++++ pocket/startup.lua | 2 +- pocket/ui/apps/control.lua | 18 +++++------ scada-common/comms.lua | 5 +-- 7 files changed, 100 insertions(+), 14 deletions(-) diff --git a/coordinator/session/pocket.lua b/coordinator/session/pocket.lua index aba0584..fa702c9 100644 --- a/coordinator/session/pocket.lua +++ b/coordinator/session/pocket.lua @@ -238,6 +238,26 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout) _send(CRDN_TYPE.API_GET_UNIT, data) end end + elseif pkt.type == CRDN_TYPE.API_GET_CTRL then + local data = {} + + for i = 1, #db.units do + local u = db.units[i] + + data[i] = { + u.connected, + u.reactor_data.rps_tripped, + u.reactor_data.mek_status.status, + u.reactor_data.mek_status.temp, + u.reactor_data.mek_status.burn_rate, + u.reactor_data.mek_status.act_burn_rate, + u.reactor_data.mek_struct.max_burn, + u.annunciator.AutoControl, + u.a_group + } + + _send(CRDN_TYPE.API_GET_CTRL, data) + end else log.debug(log_tag .. "handler received unsupported CRDN packet type " .. pkt.type) end diff --git a/coordinator/startup.lua b/coordinator/startup.lua index 950fdfc..d712fa9 100644 --- a/coordinator/startup.lua +++ b/coordinator/startup.lua @@ -19,7 +19,7 @@ local renderer = require("coordinator.renderer") local sounder = require("coordinator.sounder") local threads = require("coordinator.threads") -local COORDINATOR_VERSION = "v1.5.10" +local COORDINATOR_VERSION = "v1.5.11" local CHUNK_LOAD_DELAY_S = 30.0 diff --git a/pocket/iocontrol.lua b/pocket/iocontrol.lua index 89b96c5..3850795 100644 --- a/pocket/iocontrol.lua +++ b/pocket/iocontrol.lua @@ -6,6 +6,7 @@ local const = require("scada-common.constants") local psil = require("scada-common.psil") local types = require("scada-common.types") local util = require("scada-common.util") +local log = require("scada-common.log") local process = require("pocket.process") @@ -92,7 +93,8 @@ function iocontrol.init_core(pkt_comms, nav, cfg) -- API access ---@class pocket_ioctl_api io.api = { - get_unit = function (unit) comms.api__get_unit(unit) end + get_unit = function (unit) comms.api__get_unit(unit) end, + get_ctrl = function () comms.api__get_control() end } end @@ -526,6 +528,12 @@ function iocontrol.record_unit_data(data) end end + if type(unit.reactor_data.mek_struct) == "table" then + for key, val in pairs(unit.reactor_data.mek_struct) do + unit.unit_ps.publish(key, val) + end + end + if type(unit.reactor_data.mek_status) == "table" then for key, val in pairs(unit.reactor_data.mek_status) do unit.unit_ps.publish(key, val) @@ -823,6 +831,54 @@ function iocontrol.record_unit_data(data) --#endregion end +---@param data table +function iocontrol.record_control_data(data) + for u_id = 1, #data do + local unit = io.units[u_id] + local u_data = data[u_id] + + if type(u_data) ~= "table" then + log.debug(util.c("iocontrol.record_control_data: unit ", u_id, " data invalid")) + else + unit.connected = u_data[1] + + unit.reactor_data.rps_tripped = u_data[2] + unit.unit_ps.publish("rps_tripped", u_data[2]) + unit.reactor_data.mek_status.status = u_data[3] + unit.unit_ps.publish("status", u_data[3]) + unit.reactor_data.mek_status.temp = u_data[4] + unit.unit_ps.publish("temp", u_data[4]) + unit.reactor_data.mek_status.burn_rate = u_data[5] + unit.unit_ps.publish("burn_rate", u_data[5]) + unit.reactor_data.mek_status.act_burn_rate = u_data[6] + unit.unit_ps.publish("act_burn_rate", u_data[6]) + unit.reactor_data.mek_struct.max_burn = u_data[7] + unit.unit_ps.publish("max_burn", u_data[7]) + + unit.annunciator.AutoControl = u_data[8] + unit.unit_ps.publish("AutoControl", u_data[8]) + + unit.a_group = u_data[9] + unit.unit_ps.publish("auto_group_id", unit.a_group) + unit.unit_ps.publish("auto_group", types.AUTO_GROUP_NAMES[unit.a_group + 1]) + + local control_status = 1 + + if unit.connected then + if unit.reactor_data.rps_tripped then + control_status = 2 + end + + if unit.reactor_data.mek_status.status then + control_status = util.trinary(unit.annunciator.AutoControl, 4, 3) + end + end + + unit.unit_ps.publish("U_ControlStatus", control_status) + end + end +end + -- get the IO controller database function iocontrol.get_db() return io end diff --git a/pocket/pocket.lua b/pocket/pocket.lua index b8038f5..a625907 100644 --- a/pocket/pocket.lua +++ b/pocket/pocket.lua @@ -550,6 +550,11 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav) if self.api.linked then _send_api(CRDN_TYPE.API_GET_UNIT, { unit }) end end + -- coordinator get control app data + function public.api__get_control() + if self.api.linked then _send_api(CRDN_TYPE.API_GET_CTRL, {}) end + end + -- send a facility command ---@param cmd FAC_COMMAND command ---@param option any? optional option options for the optional options (like waste mode) @@ -702,6 +707,10 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav) if _check_length(packet, 12) and type(packet.data[1]) == "number" and iocontrol.get_db().units[packet.data[1]] then iocontrol.record_unit_data(packet.data) end + elseif packet.type == CRDN_TYPE.API_GET_CTRL then + if _check_length(packet, #iocontrol.get_db().units) then + iocontrol.record_control_data(packet.data) + end else _fail_type(packet) end else log.debug("discarding coordinator SCADA_CRDN packet before linked") diff --git a/pocket/startup.lua b/pocket/startup.lua index c31b599..2a508e3 100644 --- a/pocket/startup.lua +++ b/pocket/startup.lua @@ -20,7 +20,7 @@ local pocket = require("pocket.pocket") local renderer = require("pocket.renderer") local threads = require("pocket.threads") -local POCKET_VERSION = "v0.12.2-alpha" +local POCKET_VERSION = "v0.12.3-alpha" local println = util.println local println_ts = util.println_ts diff --git a/pocket/ui/apps/control.lua b/pocket/ui/apps/control.lua index a9129b4..59b1ffd 100644 --- a/pocket/ui/apps/control.lua +++ b/pocket/ui/apps/control.lua @@ -105,21 +105,21 @@ local function new_view(root) app.switcher(active_unit) end + local last_update = 0 + -- refresh data callback, every 500ms it will re-send the query + local function update() + if util.time_ms() - last_update >= 500 then + db.api.get_ctrl() + last_update = util.time_ms() + end + end + for i = 1, db.facility.num_units do local u_pane = panes[i] local u_div = Div{parent=u_pane,x=2,width=main.get_width()-2} local unit = db.units[i] local u_ps = unit.unit_ps - -- refresh data callback, every 500ms it will re-send the query - local last_update = 0 - local function update() - if util.time_ms() - last_update >= 500 then - db.api.get_unit(i) - last_update = util.time_ms() - end - end - local u_page = app.new_page(nil, i) u_page.tasks = { update } diff --git a/scada-common/comms.lua b/scada-common/comms.lua index 6f12fb2..a1281ce 100644 --- a/scada-common/comms.lua +++ b/scada-common/comms.lua @@ -18,7 +18,7 @@ local comms = {} -- protocol/data versions (protocol/data independent changes tracked by util.lua version) comms.version = "3.0.0" -comms.api_version = "0.0.4" +comms.api_version = "0.0.5" ---@enum PROTOCOL local PROTOCOL = { @@ -67,7 +67,8 @@ local CRDN_TYPE = { UNIT_STATUSES = 5, -- state of each of the reactor units UNIT_CMD = 6, -- command a reactor unit API_GET_FAC = 7, -- API: get all the facility data - API_GET_UNIT = 8 -- API: get reactor unit data + API_GET_UNIT = 8, -- API: get reactor unit data + API_GET_CTRL = 9 -- API: get data used for the control app } ---@enum ESTABLISH_ACK From 60c4cc2f80725106e27d95c684be328e91b4f450 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Fri, 4 Oct 2024 02:33:39 +0000 Subject: [PATCH 03/11] left align search result buttons --- pocket/ui/apps/guide.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pocket/ui/apps/guide.lua b/pocket/ui/apps/guide.lua index 660fcc4..5e4ae31 100644 --- a/pocket/ui/apps/guide.lua +++ b/pocket/ui/apps/guide.lua @@ -154,7 +154,7 @@ local function new_view(root) for idx = 1, #s_results[tier] do local entry = s_results[tier][idx] TextBox{parent=search_results,text=entry[3].." >",fg_bg=cpair(colors.gray,colors.black)} - PushButton{parent=search_results,text=entry[2],fg_bg=btn_fg_bg,active_fg_bg=btn_active,callback=entry[4]} + PushButton{parent=search_results,text=entry[2],alignment=ALIGN.LEFT,fg_bg=btn_fg_bg,active_fg_bg=btn_active,callback=entry[4]} empty = false end From 6a04354964b6d6b347e9f4a676c40127faaf4adc Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Thu, 3 Oct 2024 22:56:38 -0400 Subject: [PATCH 04/11] fixes for control app data updating --- coordinator/iocontrol.lua | 2 +- coordinator/session/pocket.lua | 3 +- pocket/iocontrol.lua | 2 +- scada-common/types.lua | 77 ++++++++++++++++++++++++++++++++++ scada-common/util.lua | 2 +- supervisor/session/plc.lua | 71 +------------------------------ supervisor/startup.lua | 2 +- 7 files changed, 84 insertions(+), 75 deletions(-) diff --git a/coordinator/iocontrol.lua b/coordinator/iocontrol.lua index 41bb058..5670219 100644 --- a/coordinator/iocontrol.lua +++ b/coordinator/iocontrol.lua @@ -219,7 +219,7 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale) annunciator = {}, ---@type annunciator unit_ps = psil.create(), - reactor_data = {}, ---@type reactor_db + reactor_data = types.new_reactor_db(), boiler_ps_tbl = {}, ---@type psil[] boiler_data_tbl = {}, ---@type boilerv_session_db[] diff --git a/coordinator/session/pocket.lua b/coordinator/session/pocket.lua index fa702c9..25dd2da 100644 --- a/coordinator/session/pocket.lua +++ b/coordinator/session/pocket.lua @@ -256,8 +256,9 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout) u.a_group } - _send(CRDN_TYPE.API_GET_CTRL, data) end + + _send(CRDN_TYPE.API_GET_CTRL, data) else log.debug(log_tag .. "handler received unsupported CRDN packet type " .. pkt.type) end diff --git a/pocket/iocontrol.lua b/pocket/iocontrol.lua index 3850795..8ad6b90 100644 --- a/pocket/iocontrol.lua +++ b/pocket/iocontrol.lua @@ -231,7 +231,7 @@ function iocontrol.init_fac(conf) annunciator = {}, ---@type annunciator unit_ps = psil.create(), - reactor_data = {}, ---@type reactor_db + reactor_data = types.new_reactor_db(), boiler_ps_tbl = {}, ---@type psil[] boiler_data_tbl = {}, ---@type boilerv_session_db[] diff --git a/scada-common/types.lua b/scada-common/types.lua index 29c52c5..ca1b885 100644 --- a/scada-common/types.lua +++ b/scada-common/types.lua @@ -127,6 +127,83 @@ function types.new_zero_coordinate() return { x = 0, y = 0, z = 0 } end ---@field reactor integer ---@field rsio IO_PORT[]|nil +-- create a new reactor database +---@nodiscard +function types.new_reactor_db() + ---@class reactor_db + local db = { + auto_ack_token = 0, + last_status_update = 0, + control_state = false, + no_reactor = false, + formed = false, + rps_tripped = false, + rps_trip_cause = "ok", ---@type rps_trip_cause + max_op_temp_H2O = 1200, + max_op_temp_Na = 1200, + ---@class rps_status + rps_status = { + high_dmg = false, + high_temp = false, + low_cool = false, + ex_waste = false, + ex_hcool = false, + no_fuel = false, + fault = false, + timeout = false, + manual = false, + automatic = false, + sys_fail = false, + force_dis = false + }, + ---@class mek_status + mek_status = { + heating_rate = 0.0, + + status = false, + burn_rate = 0.0, + act_burn_rate = 0.0, + temp = 0.0, + damage = 0.0, + boil_eff = 0.0, + env_loss = 0.0, + + fuel = 0, + fuel_need = 0, + fuel_fill = 0.0, + waste = 0, + waste_need = 0, + waste_fill = 0.0, + ccool_type = types.FLUID.EMPTY_GAS, ---@type fluid + ccool_amnt = 0, + ccool_need = 0, + ccool_fill = 0.0, + hcool_type = types.FLUID.EMPTY_GAS, ---@type fluid + hcool_amnt = 0, + hcool_need = 0, + hcool_fill = 0.0 + }, + ---@class mek_struct + mek_struct = { + length = 0, + width = 0, + height = 0, + min_pos = types.new_zero_coordinate(), + max_pos = types.new_zero_coordinate(), + heat_cap = 0, + fuel_asm = 0, + fuel_sa = 0, + fuel_cap = 0, + waste_cap = 0, + ccool_cap = 0, + hcool_cap = 0, + max_burn = 0.0 + } + } + + return db +end + --#endregion -- ALIASES -- diff --git a/scada-common/util.lua b/scada-common/util.lua index 2ae76a7..86645f8 100644 --- a/scada-common/util.lua +++ b/scada-common/util.lua @@ -24,7 +24,7 @@ local t_pack = table.pack local util = {} -- scada-common version -util.version = "1.4.5" +util.version = "1.4.6" util.TICK_TIME_S = 0.05 util.TICK_TIME_MS = 50 diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index 8850a16..bedbd8b 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.lua @@ -98,76 +98,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, rps_reset = true }, -- session database - ---@class reactor_db - sDB = { - auto_ack_token = 0, - last_status_update = 0, - control_state = false, - no_reactor = false, - formed = false, - rps_tripped = false, - rps_trip_cause = "ok", ---@type rps_trip_cause - max_op_temp_H2O = 1200, - max_op_temp_Na = 1200, - ---@class rps_status - rps_status = { - high_dmg = false, - high_temp = false, - low_cool = false, - ex_waste = false, - ex_hcool = false, - no_fuel = false, - fault = false, - timeout = false, - manual = false, - automatic = false, - sys_fail = false, - force_dis = false - }, - ---@class mek_status - mek_status = { - heating_rate = 0.0, - - status = false, - burn_rate = 0.0, - act_burn_rate = 0.0, - temp = 0.0, - damage = 0.0, - boil_eff = 0.0, - env_loss = 0.0, - - fuel = 0, - fuel_need = 0, - fuel_fill = 0.0, - waste = 0, - waste_need = 0, - waste_fill = 0.0, - ccool_type = types.FLUID.EMPTY_GAS, ---@type fluid - ccool_amnt = 0, - ccool_need = 0, - ccool_fill = 0.0, - hcool_type = types.FLUID.EMPTY_GAS, ---@type fluid - hcool_amnt = 0, - hcool_need = 0, - hcool_fill = 0.0 - }, - ---@class mek_struct - mek_struct = { - length = 0, - width = 0, - height = 0, - min_pos = types.new_zero_coordinate(), - max_pos = types.new_zero_coordinate(), - heat_cap = 0, - fuel_asm = 0, - fuel_sa = 0, - fuel_cap = 0, - waste_cap = 0, - ccool_cap = 0, - hcool_cap = 0, - max_burn = 0.0 - } - } + sDB = types.new_reactor_db() } ---@class plc_session diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 5e47cef..db6c2c6 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -22,7 +22,7 @@ local supervisor = require("supervisor.supervisor") local svsessions = require("supervisor.session.svsessions") -local SUPERVISOR_VERSION = "v1.5.5" +local SUPERVISOR_VERSION = "v1.5.6" local println = util.println local println_ts = util.println_ts From 2ccba197c7e1550787751dc1d47f895fdde04901 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Fri, 4 Oct 2024 16:31:49 +0000 Subject: [PATCH 05/11] updated cfg type annotations --- coordinator/configure.lua | 32 ++++++++++++++++---------------- pocket/configure.lua | 6 +++--- reactor-plc/configure.lua | 6 +++--- rtu/configure.lua | 20 ++++++++++---------- scada-common/log.lua | 4 ++-- supervisor/configure.lua | 6 +++--- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/coordinator/configure.lua b/coordinator/configure.lua index 1cd945b..b3197fd 100644 --- a/coordinator/configure.lua +++ b/coordinator/configure.lua @@ -118,25 +118,25 @@ local tmp_cfg = { UnitCount = 1, SpeakerVolume = 1.0, Time24Hour = true, - TempScale = 1, - EnergyScale = 1, + TempScale = 1, ---@type TEMP_SCALE + EnergyScale = 1, ---@type ENERGY_SCALE DisableFlowView = false, - MainDisplay = nil, ---@type string - FlowDisplay = nil, ---@type string - UnitDisplays = {}, - SVR_Channel = nil, ---@type integer - CRD_Channel = nil, ---@type integer - PKT_Channel = nil, ---@type integer - SVR_Timeout = nil, ---@type number - API_Timeout = nil, ---@type number - TrustedRange = nil, ---@type number - AuthKey = nil, ---@type string|nil - LogMode = 0, + MainDisplay = nil, ---@type string + FlowDisplay = nil, ---@type string + UnitDisplays = {}, ---@type string[] + SVR_Channel = nil, ---@type integer + CRD_Channel = nil, ---@type integer + PKT_Channel = nil, ---@type integer + SVR_Timeout = nil, ---@type number + API_Timeout = nil, ---@type number + TrustedRange = nil, ---@type number + AuthKey = nil, ---@type string|nil + LogMode = 0, ---@type LOG_MODE LogPath = "", LogDebug = false, - MainTheme = 1, - FrontPanelTheme = 1, - ColorMode = 1 + MainTheme = 1, ---@type UI_THEME + FrontPanelTheme = 1, ---@type FP_THEME + ColorMode = 1 ---@type COLOR_MODE } ---@class crd_config diff --git a/pocket/configure.lua b/pocket/configure.lua index e2585a6..40780da 100644 --- a/pocket/configure.lua +++ b/pocket/configure.lua @@ -75,15 +75,15 @@ local tool_ctl = { ---@class pkt_config local tmp_cfg = { - TempScale = 1, - EnergyScale = 1, + TempScale = 1, ---@type TEMP_SCALE + EnergyScale = 1, ---@type ENERGY_SCALE SVR_Channel = nil, ---@type integer CRD_Channel = nil, ---@type integer PKT_Channel = nil, ---@type integer ConnTimeout = nil, ---@type number TrustedRange = nil, ---@type number AuthKey = nil, ---@type string|nil - LogMode = 0, + LogMode = 0, ---@type LOG_MODE LogPath = "", LogDebug = false, } diff --git a/reactor-plc/configure.lua b/reactor-plc/configure.lua index e8b32d1..828c2e6 100644 --- a/reactor-plc/configure.lua +++ b/reactor-plc/configure.lua @@ -80,11 +80,11 @@ local tmp_cfg = { ConnTimeout = nil, ---@type number TrustedRange = nil, ---@type number AuthKey = nil, ---@type string|nil - LogMode = 0, + LogMode = 0, ---@type LOG_MODE LogPath = "", LogDebug = false, - FrontPanelTheme = 1, - ColorMode = 1 + FrontPanelTheme = 1, ---@type FP_THEME + ColorMode = 1 ---@type COLOR_MODE } ---@class plc_config diff --git a/rtu/configure.lua b/rtu/configure.lua index d4f842d..cc478c7 100644 --- a/rtu/configure.lua +++ b/rtu/configure.lua @@ -80,18 +80,18 @@ local tool_ctl = { ---@class rtu_config local tmp_cfg = { SpeakerVolume = 1.0, - Peripherals = {}, ---@type rtu_peri_definition[] - Redstone = {}, ---@type rtu_rs_definition[] - SVR_Channel = nil, ---@type integer - RTU_Channel = nil, ---@type integer - ConnTimeout = nil, ---@type number - TrustedRange = nil, ---@type number - AuthKey = nil, ---@type string|nil - LogMode = 0, + Peripherals = {}, ---@type rtu_peri_definition[] + Redstone = {}, ---@type rtu_rs_definition[] + SVR_Channel = nil, ---@type integer + RTU_Channel = nil, ---@type integer + ConnTimeout = nil, ---@type number + TrustedRange = nil, ---@type number + AuthKey = nil, ---@type string|nil + LogMode = 0, ---@type LOG_MODE LogPath = "", LogDebug = false, - FrontPanelTheme = 1, - ColorMode = 1 + FrontPanelTheme = 1, ---@type FP_THEME + ColorMode = 1 ---@type COLOR_MODE } ---@class rtu_config diff --git a/scada-common/log.lua b/scada-common/log.lua index 0df1efc..49f4c5e 100644 --- a/scada-common/log.lua +++ b/scada-common/log.lua @@ -11,7 +11,7 @@ local COLON, FUNC, ARROW = ":", "():", " > " ---@class logger local log = {} ----@enum MODE +---@enum LOG_MODE local MODE = { APPEND = 0, NEW = 1 } log.MODE = MODE @@ -82,7 +82,7 @@ end -- initialize logger ---@param path string file path ----@param write_mode MODE file write mode +---@param write_mode LOG_MODE file write mode ---@param include_debug boolean whether or not to include debug logs ---@param dmesg_redirect? Redirect terminal/window to direct dmesg to function log.init(path, write_mode, include_debug, dmesg_redirect) diff --git a/supervisor/configure.lua b/supervisor/configure.lua index 362c41d..6094a93 100644 --- a/supervisor/configure.lua +++ b/supervisor/configure.lua @@ -102,11 +102,11 @@ local tmp_cfg = { PKT_Timeout = nil, ---@type number TrustedRange = nil, ---@type number AuthKey = nil, ---@type string|nil - LogMode = 0, + LogMode = 0, ---@type LOG_MODE LogPath = "", LogDebug = false, - FrontPanelTheme = 1, - ColorMode = 1 + FrontPanelTheme = 1, ---@type FP_THEME + ColorMode = 1 ---@type COLOR_MODE } ---@class svr_config From 519fae3a27e9574b55e8f44567e21aa5c00c833c Mon Sep 17 00:00:00 2001 From: Mikayla Date: Fri, 4 Oct 2024 16:33:28 +0000 Subject: [PATCH 06/11] #528 pocket configurator cleanup --- pocket/configure.lua | 401 +++-------------------------------- pocket/startup.lua | 2 +- pocket/ui/config/system.lua | 410 ++++++++++++++++++++++++++++++++++++ 3 files changed, 438 insertions(+), 375 deletions(-) create mode 100644 pocket/ui/config/system.lua diff --git a/pocket/configure.lua b/pocket/configure.lua index 40780da..69a99c7 100644 --- a/pocket/configure.lua +++ b/pocket/configure.lua @@ -6,6 +6,8 @@ local log = require("scada-common.log") local types = require("scada-common.types") local util = require("scada-common.util") +local system = require("pocket.config.system") + local core = require("graphics.core") local themes = require("graphics.themes") @@ -15,12 +17,7 @@ local ListBox = require("graphics.elements.ListBox") local MultiPane = require("graphics.elements.MultiPane") local TextBox = require("graphics.elements.TextBox") -local Checkbox = require("graphics.elements.controls.Checkbox") local PushButton = require("graphics.elements.controls.PushButton") -local RadioButton = require("graphics.elements.controls.RadioButton") - -local NumberField = require("graphics.elements.form.NumberField") -local TextField = require("graphics.elements.form.TextField") local println = util.println local tri = util.trinary @@ -28,7 +25,6 @@ local tri = util.trinary local cpair = core.cpair local CENTER = core.ALIGN.CENTER -local RIGHT = core.ALIGN.RIGHT -- changes to the config data/format to let the user know local changes = { @@ -41,36 +37,28 @@ local configurator = {} local style = {} -style.root = cpair(colors.black, colors.lightGray) -style.header = cpair(colors.white, colors.gray) +style.root = cpair(colors.black, colors.lightGray) +style.header = cpair(colors.white, colors.gray) -style.colors = themes.smooth_stone.colors +style.colors = themes.smooth_stone.colors -local bw_fg_bg = cpair(colors.black, colors.white) -local g_lg_fg_bg = cpair(colors.gray, colors.lightGray) -local nav_fg_bg = bw_fg_bg -local btn_act_fg_bg = cpair(colors.white, colors.gray) -local dis_fg_bg = cpair(colors.lightGray,colors.white) +style.bw_fg_bg = cpair(colors.black, colors.white) +style.g_lg_fg_bg = cpair(colors.gray, colors.lightGray) +style.nav_fg_bg = style.bw_fg_bg +style.btn_act_fg_bg = cpair(colors.white, colors.gray) +style.btn_dis_fg_bg = cpair(colors.lightGray, colors.white) +---@class _pkt_cfg_tool_ctl local tool_ctl = { ask_config = false, has_config = false, viewing_config = false, - importing_legacy = false, view_cfg = nil, ---@type PushButton settings_apply = nil, ---@type PushButton - set_networked = nil, ---@type function - bundled_emcool = nil, ---@type function gen_summary = nil, ---@type function - show_current_cfg = nil, ---@type function - load_legacy = nil, ---@type function - - show_auth_key = nil, ---@type function - show_key_btn = nil, ---@type PushButton - auth_key_textbox = nil, ---@type TextBox - auth_key_value = "" + load_legacy = nil ---@type function } ---@class pkt_config @@ -124,6 +112,12 @@ end -- create the config view ---@param display DisplayBox local function config_view(display) + local bw_fg_bg = style.bw_fg_bg + local g_lg_fg_bg = style.g_lg_fg_bg + local nav_fg_bg = style.nav_fg_bg + local btn_act_fg_bg = style.btn_act_fg_bg + local btn_dis_fg_bg = style.btn_dis_fg_bg + ---@diagnostic disable-next-line: undefined-field local function exit() os.queueEvent("terminate") end @@ -140,7 +134,7 @@ local function config_view(display) local main_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes={main_page,ui_cfg,net_cfg,log_cfg,summary,changelog}} - -- Main Page + --#region Main Page local y_start = 7 @@ -164,286 +158,25 @@ local function config_view(display) end PushButton{parent=main_page,x=2,y=y_start,min_width=18,text="Configure Device",callback=function()main_pane.set_value(2)end,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=btn_act_fg_bg} - tool_ctl.view_cfg = PushButton{parent=main_page,x=2,y=y_start+2,min_width=20,text="View Configuration",callback=view_config,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=btn_act_fg_bg,dis_fg_bg=dis_fg_bg} + tool_ctl.view_cfg = PushButton{parent=main_page,x=2,y=y_start+2,min_width=20,text="View Configuration",callback=view_config,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg} if not tool_ctl.has_config then tool_ctl.view_cfg.disable() end PushButton{parent=main_page,x=2,y=18,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg} PushButton{parent=main_page,x=14,y=18,min_width=12,text="Change Log",callback=function()main_pane.set_value(6)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - --#region Pocket UI + --#endregion - local ui_c_1 = Div{parent=ui_cfg,x=2,y=4,width=24} + --#region System Configuration - TextBox{parent=ui_cfg,x=1,y=2,text=" Pocket UI",fg_bg=cpair(colors.black,colors.lime)} + local settings = { settings_cfg, ini_cfg, tmp_cfg, fields, load_settings } + local divs = { ui_cfg, net_cfg, log_cfg, summary } - TextBox{parent=ui_c_1,x=1,y=1,height=3,text="You may customize units below."} - - TextBox{parent=ui_c_1,x=1,y=4,text="Temperature Scale"} - local temp_scale = RadioButton{parent=ui_c_1,x=1,y=5,default=ini_cfg.TempScale,options=types.TEMP_SCALE_NAMES,callback=function()end,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.lime} - - TextBox{parent=ui_c_1,x=1,y=10,text="Energy Scale"} - local energy_scale = RadioButton{parent=ui_c_1,x=1,y=11,default=ini_cfg.EnergyScale,options=types.ENERGY_SCALE_NAMES,callback=function()end,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.lime} - - local function submit_ui_opts() - tmp_cfg.TempScale = temp_scale.get_value() - tmp_cfg.EnergyScale = energy_scale.get_value() - main_pane.set_value(3) - end - - PushButton{parent=ui_c_1,x=1,y=15,text="\x1b Back",callback=function()main_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - PushButton{parent=ui_c_1,x=19,y=15,text="Next \x1a",callback=submit_ui_opts,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + system.create(tool_ctl, main_pane, settings, divs, style, exit) --#endregion - --#region Network - - local net_c_1 = Div{parent=net_cfg,x=2,y=4,width=24} - local net_c_2 = Div{parent=net_cfg,x=2,y=4,width=24} - local net_c_3 = Div{parent=net_cfg,x=2,y=4,width=24} - local net_c_4 = Div{parent=net_cfg,x=2,y=4,width=24} - - local net_pane = MultiPane{parent=net_cfg,x=1,y=4,panes={net_c_1,net_c_2,net_c_3,net_c_4}} - - TextBox{parent=net_cfg,x=1,y=2,text=" Network Configuration",fg_bg=cpair(colors.black,colors.lightBlue)} - - TextBox{parent=net_c_1,x=1,y=1,text="Set network channels."} - TextBox{parent=net_c_1,x=1,y=3,height=4,text="Each of the named channels must be the same within a particular SCADA network.",fg_bg=g_lg_fg_bg} - - TextBox{parent=net_c_1,x=1,y=8,width=18,text="Supervisor Channel"} - local svr_chan = NumberField{parent=net_c_1,x=1,y=9,width=7,default=ini_cfg.SVR_Channel,min=1,max=65535,fg_bg=bw_fg_bg} - TextBox{parent=net_c_1,x=9,y=9,height=4,text="[SVR_CHANNEL]",fg_bg=g_lg_fg_bg} - - TextBox{parent=net_c_1,x=1,y=10,width=19,text="Coordinator Channel"} - local crd_chan = NumberField{parent=net_c_1,x=1,y=11,width=7,default=ini_cfg.CRD_Channel,min=1,max=65535,fg_bg=bw_fg_bg} - TextBox{parent=net_c_1,x=9,y=11,height=4,text="[CRD_CHANNEL]",fg_bg=g_lg_fg_bg} - - TextBox{parent=net_c_1,x=1,y=12,width=14,text="Pocket Channel"} - local pkt_chan = NumberField{parent=net_c_1,x=1,y=13,width=7,default=ini_cfg.PKT_Channel,min=1,max=65535,fg_bg=bw_fg_bg} - TextBox{parent=net_c_1,x=9,y=13,height=4,text="[PKT_CHANNEL]",fg_bg=g_lg_fg_bg} - - local chan_err = TextBox{parent=net_c_1,x=1,y=14,width=24,text="Please set all channels.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} - - local function submit_channels() - local svr_c, crd_c, pkt_c = tonumber(svr_chan.get_value()), tonumber(crd_chan.get_value()), tonumber(pkt_chan.get_value()) - if svr_c ~= nil and crd_c ~= nil and pkt_c ~= nil then - tmp_cfg.SVR_Channel, tmp_cfg.CRD_Channel, tmp_cfg.PKT_Channel = svr_c, crd_c, pkt_c - net_pane.set_value(2) - chan_err.hide(true) - else chan_err.show() end - end - - PushButton{parent=net_c_1,x=1,y=15,text="\x1b Back",callback=function()main_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - PushButton{parent=net_c_1,x=19,y=15,text="Next \x1a",callback=submit_channels,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - - TextBox{parent=net_c_2,x=1,y=1,text="Set connection timeout."} - TextBox{parent=net_c_2,x=1,y=3,height=7,text="You generally should not need to modify this. On slow servers, you can try to increase this to make the system wait longer before assuming a disconnection.",fg_bg=g_lg_fg_bg} - - TextBox{parent=net_c_2,x=1,y=11,width=19,text="Connection Timeout"} - local timeout = NumberField{parent=net_c_2,x=1,y=12,width=7,default=ini_cfg.ConnTimeout,min=2,max=25,max_chars=6,max_frac_digits=2,allow_decimal=true,fg_bg=bw_fg_bg} - - TextBox{parent=net_c_2,x=9,y=12,height=2,text="seconds\n(default 5)",fg_bg=g_lg_fg_bg} - - local ct_err = TextBox{parent=net_c_2,x=1,y=14,width=24,text="Please set timeout.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} - - local function submit_timeouts() - local timeout_val = tonumber(timeout.get_value()) - if timeout_val ~= nil then - tmp_cfg.ConnTimeout = timeout_val - net_pane.set_value(3) - ct_err.hide(true) - else ct_err.show() end - end - - PushButton{parent=net_c_2,x=1,y=15,text="\x1b Back",callback=function()net_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - PushButton{parent=net_c_2,x=19,y=15,text="Next \x1a",callback=submit_timeouts,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - - TextBox{parent=net_c_3,x=1,y=1,text="Set the trusted range."} - TextBox{parent=net_c_3,x=1,y=3,height=4,text="Setting this to a value larger than 0 prevents connections with devices that many blocks away.",fg_bg=g_lg_fg_bg} - TextBox{parent=net_c_3,x=1,y=8,height=4,text="This is optional. You can disable this functionality by setting the value to 0.",fg_bg=g_lg_fg_bg} - - local range = NumberField{parent=net_c_3,x=1,y=13,width=10,default=ini_cfg.TrustedRange,min=0,max_chars=20,allow_decimal=true,fg_bg=bw_fg_bg} - - local tr_err = TextBox{parent=net_c_3,x=1,y=14,width=24,text="Set the trusted range.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} - - local function submit_tr() - local range_val = tonumber(range.get_value()) - if range_val ~= nil then - tmp_cfg.TrustedRange = range_val - net_pane.set_value(4) - tr_err.hide(true) - else tr_err.show() end - end - - PushButton{parent=net_c_3,x=1,y=15,text="\x1b Back",callback=function()net_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - PushButton{parent=net_c_3,x=19,y=15,text="Next \x1a",callback=submit_tr,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - - TextBox{parent=net_c_4,x=1,y=1,height=4,text="Optionally, set the facility authentication key. Do NOT use one of your passwords."} - TextBox{parent=net_c_4,x=1,y=6,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers.",fg_bg=g_lg_fg_bg} - - TextBox{parent=net_c_4,x=1,y=12,text="Facility Auth Key"} - local key, _ = TextField{parent=net_c_4,x=1,y=13,max_len=64,value=ini_cfg.AuthKey,width=24,height=1,fg_bg=bw_fg_bg} - - local function censor_key(enable) key.censor(util.trinary(enable, "*", nil)) end - - -- declare back first so tabbing makes sense visually - PushButton{parent=net_c_4,x=1,y=15,text="\x1b Back",callback=function()net_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - - local hide_key = Checkbox{parent=net_c_4,x=8,y=15,label="Hide Key",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key} - - hide_key.set_value(true) - censor_key(true) - - local key_err = TextBox{parent=net_c_4,x=1,y=14,width=24,text="Length must be > 7.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} - - local function submit_auth() - local v = key.get_value() - if string.len(v) == 0 or string.len(v) >= 8 then - tmp_cfg.AuthKey = key.get_value() - main_pane.set_value(4) - key_err.hide(true) - else key_err.show() end - end - - PushButton{parent=net_c_4,x=19,y=15,text="Next \x1a",callback=submit_auth,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - - --#endregion - - --#region Logging - - local log_c_1 = Div{parent=log_cfg,x=2,y=4,width=24} - - TextBox{parent=log_cfg,x=1,y=2,text=" Logging Configuration",fg_bg=cpair(colors.black,colors.pink)} - - TextBox{parent=log_c_1,x=1,y=1,text="Configure logging below."} - - TextBox{parent=log_c_1,x=1,y=3,text="Log File Mode"} - local mode = RadioButton{parent=log_c_1,x=1,y=4,default=ini_cfg.LogMode+1,options={"Append on Startup","Replace on Startup"},callback=function()end,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.pink} - - TextBox{parent=log_c_1,x=1,y=7,text="Log File Path"} - local path = TextField{parent=log_c_1,x=1,y=8,width=24,height=1,value=ini_cfg.LogPath,max_len=128,fg_bg=bw_fg_bg} - - local en_dbg = Checkbox{parent=log_c_1,x=1,y=10,default=ini_cfg.LogDebug,label="Enable Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)} - TextBox{parent=log_c_1,x=3,y=11,height=4,text="This results in much larger log files. Use only as needed.",fg_bg=g_lg_fg_bg} - - local path_err = TextBox{parent=log_c_1,x=1,y=14,width=24,text="Provide a log file path.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} - - local function submit_log() - if path.get_value() ~= "" then - path_err.hide(true) - tmp_cfg.LogMode = mode.get_value() - 1 - tmp_cfg.LogPath = path.get_value() - tmp_cfg.LogDebug = en_dbg.get_value() - tool_ctl.gen_summary(tmp_cfg) - tool_ctl.viewing_config = false - tool_ctl.importing_legacy = false - tool_ctl.settings_apply.show() - main_pane.set_value(5) - else path_err.show() end - end - - PushButton{parent=log_c_1,x=1,y=15,text="\x1b Back",callback=function()main_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - PushButton{parent=log_c_1,x=19,y=15,text="Next \x1a",callback=submit_log,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - - --#endregion - - --#region Summary and Saving - - local sum_c_1 = Div{parent=summary,x=2,y=4,width=24} - local sum_c_2 = Div{parent=summary,x=2,y=4,width=24} - local sum_c_3 = Div{parent=summary,x=2,y=4,width=24} - local sum_c_4 = Div{parent=summary,x=2,y=4,width=24} - - local sum_pane = MultiPane{parent=summary,x=1,y=4,panes={sum_c_1,sum_c_2,sum_c_3,sum_c_4}} - - TextBox{parent=summary,x=1,y=2,text=" Summary",fg_bg=cpair(colors.black,colors.green)} - - local setting_list = ListBox{parent=sum_c_1,x=1,y=1,height=11,width=24,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} - - local function back_from_summary() - if tool_ctl.viewing_config or tool_ctl.importing_legacy then - main_pane.set_value(1) - tool_ctl.viewing_config = false - tool_ctl.importing_legacy = false - tool_ctl.settings_apply.show() - else - main_pane.set_value(4) - end - end - - ---@param element graphics_element - ---@param data any - local function try_set(element, data) - if data ~= nil then element.set_value(data) end - end - - local function save_and_continue() - for _, field in ipairs(fields) do - local k, v = field[1], tmp_cfg[field[1]] - if v == nil then settings.unset(k) else settings.set(k, v) end - end - - if settings.save("/pocket.settings") then - load_settings(settings_cfg, true) - load_settings(ini_cfg) - - try_set(temp_scale, ini_cfg.TempScale) - try_set(energy_scale, ini_cfg.EnergyScale) - try_set(svr_chan, ini_cfg.SVR_Channel) - try_set(crd_chan, ini_cfg.CRD_Channel) - try_set(pkt_chan, ini_cfg.PKT_Channel) - try_set(timeout, ini_cfg.ConnTimeout) - try_set(range, ini_cfg.TrustedRange) - try_set(key, ini_cfg.AuthKey) - try_set(mode, ini_cfg.LogMode) - try_set(path, ini_cfg.LogPath) - try_set(en_dbg, ini_cfg.LogDebug) - - tool_ctl.view_cfg.enable() - - if tool_ctl.importing_legacy then - tool_ctl.importing_legacy = false - sum_pane.set_value(3) - else - sum_pane.set_value(2) - end - else - sum_pane.set_value(4) - end - end - - PushButton{parent=sum_c_1,x=1,y=15,text="\x1b Back",callback=back_from_summary,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - tool_ctl.show_key_btn = PushButton{parent=sum_c_1,x=1,y=13,min_width=17,text="Unhide Auth Key",callback=function()tool_ctl.show_auth_key()end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=dis_fg_bg} - tool_ctl.settings_apply = PushButton{parent=sum_c_1,x=18,y=15,min_width=7,text="Apply",callback=save_and_continue,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg} - - TextBox{parent=sum_c_2,x=1,y=1,text="Settings saved!"} - - local function go_home() - main_pane.set_value(1) - net_pane.set_value(1) - sum_pane.set_value(1) - end - - PushButton{parent=sum_c_2,x=1,y=15,min_width=6,text="Home",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - PushButton{parent=sum_c_2,x=19,y=15,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)} - - TextBox{parent=sum_c_3,x=1,y=1,height=4,text="The old config.lua file will now be deleted, then the configurator will exit."} - - local function delete_legacy() - fs.delete("/pocket/config.lua") - exit() - end - - PushButton{parent=sum_c_3,x=1,y=15,min_width=8,text="Cancel",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - PushButton{parent=sum_c_3,x=19,y=15,min_width=6,text="OK",callback=delete_legacy,fg_bg=cpair(colors.black,colors.green),active_fg_bg=cpair(colors.white,colors.gray)} - - TextBox{parent=sum_c_4,x=1,y=1,height=8,text="Failed to save the settings file.\n\nThere may not be enough space for the modification or server file permissions may be denying writes."} - PushButton{parent=sum_c_4,x=1,y=15,min_width=6,text="Home",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - PushButton{parent=sum_c_4,x=19,y=15,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)} - - --#endregion - - -- Config Change Log + --#region Config Change Log local cl = Div{parent=changelog,x=2,y=4,width=24} @@ -462,87 +195,7 @@ local function config_view(display) PushButton{parent=cl,x=1,y=15,text="\x1b Back",callback=function()main_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - -- set tool functions now that we have the elements - - -- load a legacy config file - function tool_ctl.load_legacy() - local config = require("pocket.config") - - tmp_cfg.SVR_Channel = config.SVR_CHANNEL - tmp_cfg.CRD_Channel = config.CRD_CHANNEL - tmp_cfg.PKT_Channel = config.PKT_CHANNEL - tmp_cfg.ConnTimeout = config.COMMS_TIMEOUT - tmp_cfg.TrustedRange = config.TRUSTED_RANGE - tmp_cfg.AuthKey = config.AUTH_KEY or "" - - tmp_cfg.LogMode = config.LOG_MODE - tmp_cfg.LogPath = config.LOG_PATH - tmp_cfg.LogDebug = config.LOG_DEBUG or false - - tool_ctl.gen_summary(tmp_cfg) - sum_pane.set_value(1) - main_pane.set_value(5) - tool_ctl.importing_legacy = true - end - - -- expose the auth key on the summary page - function tool_ctl.show_auth_key() - tool_ctl.show_key_btn.disable() - tool_ctl.auth_key_textbox.set_value(tool_ctl.auth_key_value) - end - - -- generate the summary list - ---@param cfg pkt_config - function tool_ctl.gen_summary(cfg) - setting_list.remove_all() - - local alternate = false - local inner_width = setting_list.get_width() - 1 - - tool_ctl.show_key_btn.enable() - tool_ctl.auth_key_value = cfg.AuthKey or "" -- to show auth key - - for i = 1, #fields do - local f = fields[i] - local height = 1 - local label_w = string.len(f[2]) - local val_max_w = (inner_width - label_w) - 1 - local raw = cfg[f[1]] - local val = util.strval(raw) - - if f[1] == "AuthKey" then - val = string.rep("*", string.len(val)) - elseif f[1] == "LogMode" then - val = util.trinary(raw == log.MODE.APPEND, "append", "replace") - elseif f[1] == "TempScale" then - val = util.strval(types.TEMP_SCALE_NAMES[raw]) - elseif f[1] == "EnergyScale" then - val = util.strval(types.ENERGY_SCALE_NAMES[raw]) - end - - if val == "nil" then val = "" end - - local c = util.trinary(alternate, g_lg_fg_bg, cpair(colors.gray,colors.white)) - alternate = not alternate - - if string.len(val) > val_max_w then - local lines = util.strwrap(val, inner_width) - height = #lines + 1 - end - - local line = Div{parent=setting_list,height=height,fg_bg=c} - TextBox{parent=line,text=f[2],width=string.len(f[2]),fg_bg=cpair(colors.black,line.get_fg_bg().bkg)} - - local textbox - if height > 1 then - textbox = TextBox{parent=line,x=1,y=2,text=val,height=height-1} - else - textbox = TextBox{parent=line,x=label_w+1,y=1,text=val,alignment=RIGHT} - end - - if f[1] == "AuthKey" then tool_ctl.auth_key_textbox = textbox end - end - end + --#endregion end -- reset terminal screen diff --git a/pocket/startup.lua b/pocket/startup.lua index 2a508e3..0bdfed5 100644 --- a/pocket/startup.lua +++ b/pocket/startup.lua @@ -20,7 +20,7 @@ local pocket = require("pocket.pocket") local renderer = require("pocket.renderer") local threads = require("pocket.threads") -local POCKET_VERSION = "v0.12.3-alpha" +local POCKET_VERSION = "v0.12.4-alpha" local println = util.println local println_ts = util.println_ts diff --git a/pocket/ui/config/system.lua b/pocket/ui/config/system.lua new file mode 100644 index 0000000..4c195ff --- /dev/null +++ b/pocket/ui/config/system.lua @@ -0,0 +1,410 @@ +local log = require("scada-common.log") +local types = require("scada-common.types") +local util = require("scada-common.util") + +local core = require("graphics.core") + +local Div = require("graphics.elements.Div") +local ListBox = require("graphics.elements.ListBox") +local MultiPane = require("graphics.elements.MultiPane") +local TextBox = require("graphics.elements.TextBox") + +local Checkbox = require("graphics.elements.controls.Checkbox") +local PushButton = require("graphics.elements.controls.PushButton") +local RadioButton = require("graphics.elements.controls.RadioButton") + +local NumberField = require("graphics.elements.form.NumberField") +local TextField = require("graphics.elements.form.TextField") + +local tri = util.trinary + +local cpair = core.cpair + +local RIGHT = core.ALIGN.RIGHT + +local self = { + importing_legacy = false, + + show_auth_key = nil, ---@type function + show_key_btn = nil, ---@type PushButton + auth_key_textbox = nil, ---@type TextBox + auth_key_value = "" +} + +local system = {} + +-- create the system configuration view +---@param tool_ctl _pkt_cfg_tool_ctl +---@param main_pane MultiPane +---@param cfg_sys [ pkt_config, pkt_config, pkt_config, { [1]: string, [2]: string, [3]: any }[], function ] +---@param divs Div[] +---@param style { [string]: cpair } +---@param exit function +function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit) + local settings_cfg, ini_cfg, tmp_cfg, fields, load_settings = cfg_sys[1], cfg_sys[2], cfg_sys[3], cfg_sys[4], cfg_sys[5] + local ui_cfg, net_cfg, log_cfg, summary = divs[1], divs[2], divs[3], divs[4] + + local bw_fg_bg = style.bw_fg_bg + local g_lg_fg_bg = style.g_lg_fg_bg + local nav_fg_bg = style.nav_fg_bg + local btn_act_fg_bg = style.btn_act_fg_bg + local btn_dis_fg_bg = style.btn_dis_fg_bg + + --#region Pocket UI + + local ui_c_1 = Div{parent=ui_cfg,x=2,y=4,width=24} + + TextBox{parent=ui_cfg,x=1,y=2,text=" Pocket UI",fg_bg=cpair(colors.black,colors.lime)} + + TextBox{parent=ui_c_1,x=1,y=1,height=3,text="You may customize units below."} + + TextBox{parent=ui_c_1,x=1,y=4,text="Temperature Scale"} + local temp_scale = RadioButton{parent=ui_c_1,x=1,y=5,default=ini_cfg.TempScale,options=types.TEMP_SCALE_NAMES,callback=function()end,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.lime} + + TextBox{parent=ui_c_1,x=1,y=10,text="Energy Scale"} + local energy_scale = RadioButton{parent=ui_c_1,x=1,y=11,default=ini_cfg.EnergyScale,options=types.ENERGY_SCALE_NAMES,callback=function()end,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.lime} + + local function submit_ui_opts() + tmp_cfg.TempScale = temp_scale.get_value() + tmp_cfg.EnergyScale = energy_scale.get_value() + main_pane.set_value(3) + end + + PushButton{parent=ui_c_1,x=1,y=15,text="\x1b Back",callback=function()main_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=ui_c_1,x=19,y=15,text="Next \x1a",callback=submit_ui_opts,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + --#endregion + + --#region Network + + local net_c_1 = Div{parent=net_cfg,x=2,y=4,width=24} + local net_c_2 = Div{parent=net_cfg,x=2,y=4,width=24} + local net_c_3 = Div{parent=net_cfg,x=2,y=4,width=24} + local net_c_4 = Div{parent=net_cfg,x=2,y=4,width=24} + + local net_pane = MultiPane{parent=net_cfg,x=1,y=4,panes={net_c_1,net_c_2,net_c_3,net_c_4}} + + TextBox{parent=net_cfg,x=1,y=2,text=" Network Configuration",fg_bg=cpair(colors.black,colors.lightBlue)} + + TextBox{parent=net_c_1,x=1,y=1,text="Set network channels."} + TextBox{parent=net_c_1,x=1,y=3,height=4,text="Each of the named channels must be the same within a particular SCADA network.",fg_bg=g_lg_fg_bg} + + TextBox{parent=net_c_1,x=1,y=8,width=18,text="Supervisor Channel"} + local svr_chan = NumberField{parent=net_c_1,x=1,y=9,width=7,default=ini_cfg.SVR_Channel,min=1,max=65535,fg_bg=bw_fg_bg} + TextBox{parent=net_c_1,x=9,y=9,height=4,text="[SVR_CHANNEL]",fg_bg=g_lg_fg_bg} + + TextBox{parent=net_c_1,x=1,y=10,width=19,text="Coordinator Channel"} + local crd_chan = NumberField{parent=net_c_1,x=1,y=11,width=7,default=ini_cfg.CRD_Channel,min=1,max=65535,fg_bg=bw_fg_bg} + TextBox{parent=net_c_1,x=9,y=11,height=4,text="[CRD_CHANNEL]",fg_bg=g_lg_fg_bg} + + TextBox{parent=net_c_1,x=1,y=12,width=14,text="Pocket Channel"} + local pkt_chan = NumberField{parent=net_c_1,x=1,y=13,width=7,default=ini_cfg.PKT_Channel,min=1,max=65535,fg_bg=bw_fg_bg} + TextBox{parent=net_c_1,x=9,y=13,height=4,text="[PKT_CHANNEL]",fg_bg=g_lg_fg_bg} + + local chan_err = TextBox{parent=net_c_1,x=1,y=14,width=24,text="Please set all channels.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} + + local function submit_channels() + local svr_c, crd_c, pkt_c = tonumber(svr_chan.get_value()), tonumber(crd_chan.get_value()), tonumber(pkt_chan.get_value()) + if svr_c ~= nil and crd_c ~= nil and pkt_c ~= nil then + tmp_cfg.SVR_Channel, tmp_cfg.CRD_Channel, tmp_cfg.PKT_Channel = svr_c, crd_c, pkt_c + net_pane.set_value(2) + chan_err.hide(true) + else chan_err.show() end + end + + PushButton{parent=net_c_1,x=1,y=15,text="\x1b Back",callback=function()main_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=net_c_1,x=19,y=15,text="Next \x1a",callback=submit_channels,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + TextBox{parent=net_c_2,x=1,y=1,text="Set connection timeout."} + TextBox{parent=net_c_2,x=1,y=3,height=7,text="You generally should not need to modify this. On slow servers, you can try to increase this to make the system wait longer before assuming a disconnection.",fg_bg=g_lg_fg_bg} + + TextBox{parent=net_c_2,x=1,y=11,width=19,text="Connection Timeout"} + local timeout = NumberField{parent=net_c_2,x=1,y=12,width=7,default=ini_cfg.ConnTimeout,min=2,max=25,max_chars=6,max_frac_digits=2,allow_decimal=true,fg_bg=bw_fg_bg} + + TextBox{parent=net_c_2,x=9,y=12,height=2,text="seconds\n(default 5)",fg_bg=g_lg_fg_bg} + + local ct_err = TextBox{parent=net_c_2,x=1,y=14,width=24,text="Please set timeout.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} + + local function submit_timeouts() + local timeout_val = tonumber(timeout.get_value()) + if timeout_val ~= nil then + tmp_cfg.ConnTimeout = timeout_val + net_pane.set_value(3) + ct_err.hide(true) + else ct_err.show() end + end + + PushButton{parent=net_c_2,x=1,y=15,text="\x1b Back",callback=function()net_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=net_c_2,x=19,y=15,text="Next \x1a",callback=submit_timeouts,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + TextBox{parent=net_c_3,x=1,y=1,text="Set the trusted range."} + TextBox{parent=net_c_3,x=1,y=3,height=4,text="Setting this to a value larger than 0 prevents connections with devices that many blocks away.",fg_bg=g_lg_fg_bg} + TextBox{parent=net_c_3,x=1,y=8,height=4,text="This is optional. You can disable this functionality by setting the value to 0.",fg_bg=g_lg_fg_bg} + + local range = NumberField{parent=net_c_3,x=1,y=13,width=10,default=ini_cfg.TrustedRange,min=0,max_chars=20,allow_decimal=true,fg_bg=bw_fg_bg} + + local tr_err = TextBox{parent=net_c_3,x=1,y=14,width=24,text="Set the trusted range.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} + + local function submit_tr() + local range_val = tonumber(range.get_value()) + if range_val ~= nil then + tmp_cfg.TrustedRange = range_val + net_pane.set_value(4) + tr_err.hide(true) + else tr_err.show() end + end + + PushButton{parent=net_c_3,x=1,y=15,text="\x1b Back",callback=function()net_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=net_c_3,x=19,y=15,text="Next \x1a",callback=submit_tr,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + TextBox{parent=net_c_4,x=1,y=1,height=4,text="Optionally, set the facility authentication key. Do NOT use one of your passwords."} + TextBox{parent=net_c_4,x=1,y=6,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers.",fg_bg=g_lg_fg_bg} + + TextBox{parent=net_c_4,x=1,y=12,text="Facility Auth Key"} + local key, _ = TextField{parent=net_c_4,x=1,y=13,max_len=64,value=ini_cfg.AuthKey,width=24,height=1,fg_bg=bw_fg_bg} + + local function censor_key(enable) key.censor(tri(enable, "*", nil)) end + + -- declare back first so tabbing makes sense visually + PushButton{parent=net_c_4,x=1,y=15,text="\x1b Back",callback=function()net_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + local hide_key = Checkbox{parent=net_c_4,x=8,y=15,label="Hide Key",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key} + + hide_key.set_value(true) + censor_key(true) + + local key_err = TextBox{parent=net_c_4,x=1,y=14,width=24,text="Length must be > 7.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} + + local function submit_auth() + local v = key.get_value() + if string.len(v) == 0 or string.len(v) >= 8 then + tmp_cfg.AuthKey = key.get_value() + main_pane.set_value(4) + key_err.hide(true) + else key_err.show() end + end + + PushButton{parent=net_c_4,x=19,y=15,text="Next \x1a",callback=submit_auth,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + --#endregion + + --#region Logging + + local log_c_1 = Div{parent=log_cfg,x=2,y=4,width=24} + + TextBox{parent=log_cfg,x=1,y=2,text=" Logging Configuration",fg_bg=cpair(colors.black,colors.pink)} + + TextBox{parent=log_c_1,x=1,y=1,text="Configure logging below."} + + TextBox{parent=log_c_1,x=1,y=3,text="Log File Mode"} + local mode = RadioButton{parent=log_c_1,x=1,y=4,default=ini_cfg.LogMode+1,options={"Append on Startup","Replace on Startup"},callback=function()end,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.pink} + + TextBox{parent=log_c_1,x=1,y=7,text="Log File Path"} + local path = TextField{parent=log_c_1,x=1,y=8,width=24,height=1,value=ini_cfg.LogPath,max_len=128,fg_bg=bw_fg_bg} + + local en_dbg = Checkbox{parent=log_c_1,x=1,y=10,default=ini_cfg.LogDebug,label="Enable Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)} + TextBox{parent=log_c_1,x=3,y=11,height=4,text="This results in much larger log files. Use only as needed.",fg_bg=g_lg_fg_bg} + + local path_err = TextBox{parent=log_c_1,x=1,y=14,width=24,text="Provide a log file path.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} + + local function submit_log() + if path.get_value() ~= "" then + path_err.hide(true) + tmp_cfg.LogMode = mode.get_value() - 1 + tmp_cfg.LogPath = path.get_value() + tmp_cfg.LogDebug = en_dbg.get_value() + tool_ctl.gen_summary(tmp_cfg) + tool_ctl.viewing_config = false + self.importing_legacy = false + tool_ctl.settings_apply.show() + main_pane.set_value(5) + else path_err.show() end + end + + PushButton{parent=log_c_1,x=1,y=15,text="\x1b Back",callback=function()main_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=log_c_1,x=19,y=15,text="Next \x1a",callback=submit_log,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + --#endregion + + --#region Summary and Saving + + local sum_c_1 = Div{parent=summary,x=2,y=4,width=24} + local sum_c_2 = Div{parent=summary,x=2,y=4,width=24} + local sum_c_3 = Div{parent=summary,x=2,y=4,width=24} + local sum_c_4 = Div{parent=summary,x=2,y=4,width=24} + + local sum_pane = MultiPane{parent=summary,x=1,y=4,panes={sum_c_1,sum_c_2,sum_c_3,sum_c_4}} + + TextBox{parent=summary,x=1,y=2,text=" Summary",fg_bg=cpair(colors.black,colors.green)} + + local setting_list = ListBox{parent=sum_c_1,x=1,y=1,height=11,width=24,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} + + local function back_from_summary() + if tool_ctl.viewing_config or self.importing_legacy then + main_pane.set_value(1) + tool_ctl.viewing_config = false + self.importing_legacy = false + tool_ctl.settings_apply.show() + else + main_pane.set_value(4) + end + end + + ---@param element graphics_element + ---@param data any + local function try_set(element, data) + if data ~= nil then element.set_value(data) end + end + + local function save_and_continue() + for _, field in ipairs(fields) do + local k, v = field[1], tmp_cfg[field[1]] + if v == nil then settings.unset(k) else settings.set(k, v) end + end + + if settings.save("/pocket.settings") then + load_settings(settings_cfg, true) + load_settings(ini_cfg) + + try_set(temp_scale, ini_cfg.TempScale) + try_set(energy_scale, ini_cfg.EnergyScale) + try_set(svr_chan, ini_cfg.SVR_Channel) + try_set(crd_chan, ini_cfg.CRD_Channel) + try_set(pkt_chan, ini_cfg.PKT_Channel) + try_set(timeout, ini_cfg.ConnTimeout) + try_set(range, ini_cfg.TrustedRange) + try_set(key, ini_cfg.AuthKey) + try_set(mode, ini_cfg.LogMode) + try_set(path, ini_cfg.LogPath) + try_set(en_dbg, ini_cfg.LogDebug) + + tool_ctl.view_cfg.enable() + + if self.importing_legacy then + self.importing_legacy = false + sum_pane.set_value(3) + else + sum_pane.set_value(2) + end + else + sum_pane.set_value(4) + end + end + + PushButton{parent=sum_c_1,x=1,y=15,text="\x1b Back",callback=back_from_summary,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + self.show_key_btn = PushButton{parent=sum_c_1,x=1,y=13,min_width=17,text="Unhide Auth Key",callback=function()self.show_auth_key()end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg} + tool_ctl.settings_apply = PushButton{parent=sum_c_1,x=18,y=15,min_width=7,text="Apply",callback=save_and_continue,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg} + + TextBox{parent=sum_c_2,x=1,y=1,text="Settings saved!"} + + local function go_home() + main_pane.set_value(1) + net_pane.set_value(1) + sum_pane.set_value(1) + end + + PushButton{parent=sum_c_2,x=1,y=15,min_width=6,text="Home",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=sum_c_2,x=19,y=15,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)} + + TextBox{parent=sum_c_3,x=1,y=1,height=4,text="The old config.lua file will now be deleted, then the configurator will exit."} + + local function delete_legacy() + fs.delete("/pocket/config.lua") + exit() + end + + PushButton{parent=sum_c_3,x=1,y=15,min_width=8,text="Cancel",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=sum_c_3,x=19,y=15,min_width=6,text="OK",callback=delete_legacy,fg_bg=cpair(colors.black,colors.green),active_fg_bg=cpair(colors.white,colors.gray)} + + TextBox{parent=sum_c_4,x=1,y=1,height=8,text="Failed to save the settings file.\n\nThere may not be enough space for the modification or server file permissions may be denying writes."} + PushButton{parent=sum_c_4,x=1,y=15,min_width=6,text="Home",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=sum_c_4,x=19,y=15,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)} + + --#endregion + + --#region Tool Functions + + -- load a legacy config file + function tool_ctl.load_legacy() + local config = require("pocket.config") + + tmp_cfg.SVR_Channel = config.SVR_CHANNEL + tmp_cfg.CRD_Channel = config.CRD_CHANNEL + tmp_cfg.PKT_Channel = config.PKT_CHANNEL + tmp_cfg.ConnTimeout = config.COMMS_TIMEOUT + tmp_cfg.TrustedRange = config.TRUSTED_RANGE + tmp_cfg.AuthKey = config.AUTH_KEY or "" + + tmp_cfg.LogMode = config.LOG_MODE + tmp_cfg.LogPath = config.LOG_PATH + tmp_cfg.LogDebug = config.LOG_DEBUG or false + + tool_ctl.gen_summary(tmp_cfg) + sum_pane.set_value(1) + main_pane.set_value(5) + self.importing_legacy = true + end + + -- expose the auth key on the summary page + function self.show_auth_key() + self.show_key_btn.disable() + self.auth_key_textbox.set_value(self.auth_key_value) + end + + -- generate the summary list + ---@param cfg pkt_config + function tool_ctl.gen_summary(cfg) + setting_list.remove_all() + + local alternate = false + local inner_width = setting_list.get_width() - 1 + + self.show_key_btn.enable() + self.auth_key_value = cfg.AuthKey or "" -- to show auth key + + for i = 1, #fields do + local f = fields[i] + local height = 1 + local label_w = string.len(f[2]) + local val_max_w = (inner_width - label_w) - 1 + local raw = cfg[f[1]] + local val = util.strval(raw) + + if f[1] == "AuthKey" then + val = string.rep("*", string.len(val)) + elseif f[1] == "LogMode" then + val = tri(raw == log.MODE.APPEND, "append", "replace") + elseif f[1] == "TempScale" then + val = util.strval(types.TEMP_SCALE_NAMES[raw]) + elseif f[1] == "EnergyScale" then + val = util.strval(types.ENERGY_SCALE_NAMES[raw]) + end + + if val == "nil" then val = "" end + + local c = tri(alternate, g_lg_fg_bg, cpair(colors.gray,colors.white)) + alternate = not alternate + + if string.len(val) > val_max_w then + local lines = util.strwrap(val, inner_width) + height = #lines + 1 + end + + local line = Div{parent=setting_list,height=height,fg_bg=c} + TextBox{parent=line,text=f[2],width=string.len(f[2]),fg_bg=cpair(colors.black,line.get_fg_bg().bkg)} + + local textbox + if height > 1 then + textbox = TextBox{parent=line,x=1,y=2,text=val,height=height-1} + else + textbox = TextBox{parent=line,x=label_w+1,y=1,text=val,alignment=RIGHT} + end + + if f[1] == "AuthKey" then self.auth_key_textbox = textbox end + end + end + + --#endregion +end + +return system From 749c84490bd599bb16f865f7ff41c04d16884bbc Mon Sep 17 00:00:00 2001 From: Mikayla Date: Fri, 4 Oct 2024 16:38:34 +0000 Subject: [PATCH 07/11] #528 moved pocket config folder --- pocket/{ui => }/config/system.lua | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pocket/{ui => }/config/system.lua (100%) diff --git a/pocket/ui/config/system.lua b/pocket/config/system.lua similarity index 100% rename from pocket/ui/config/system.lua rename to pocket/config/system.lua From 8238b26eecc7b97591adf9e3d2a3aed4b4c623e5 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Fri, 4 Oct 2024 21:12:37 -0400 Subject: [PATCH 08/11] comments and version increments --- pocket/iocontrol.lua | 1 + reactor-plc/startup.lua | 2 +- rtu/startup.lua | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pocket/iocontrol.lua b/pocket/iocontrol.lua index 8ad6b90..ea8e6f8 100644 --- a/pocket/iocontrol.lua +++ b/pocket/iocontrol.lua @@ -831,6 +831,7 @@ function iocontrol.record_unit_data(data) --#endregion end +-- update control app with unit data from API_GET_CTRL ---@param data table function iocontrol.record_control_data(data) for u_id = 1, #data do diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index 8df764e..c918d4d 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.8.10" +local R_PLC_VERSION = "v1.8.11" local println = util.println local println_ts = util.println_ts diff --git a/rtu/startup.lua b/rtu/startup.lua index 4e0a083..0a6e357 100644 --- a/rtu/startup.lua +++ b/rtu/startup.lua @@ -31,7 +31,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.10.11" +local RTU_VERSION = "v1.10.12" local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_HW_STATE = databus.RTU_HW_STATE From 65609ddaa2af4aeac5168ba88ae9e7f0be530350 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Fri, 4 Oct 2024 21:13:46 -0400 Subject: [PATCH 09/11] cleanup --- pocket/iocontrol.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pocket/iocontrol.lua b/pocket/iocontrol.lua index ea8e6f8..d1bf95e 100644 --- a/pocket/iocontrol.lua +++ b/pocket/iocontrol.lua @@ -835,7 +835,7 @@ end ---@param data table function iocontrol.record_control_data(data) for u_id = 1, #data do - local unit = io.units[u_id] + local unit = io.units[u_id] local u_data = data[u_id] if type(u_data) ~= "table" then From f1a13f11250ef8d9a2a0709ddb68e89bdfa81234 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Fri, 4 Oct 2024 21:16:30 -0400 Subject: [PATCH 10/11] updated color accessibility note in coordinator config --- coordinator/configure.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coordinator/configure.lua b/coordinator/configure.lua index b3197fd..4e772ca 100644 --- a/coordinator/configure.lua +++ b/coordinator/configure.lua @@ -832,7 +832,7 @@ local function config_view(display) TextBox{parent=clr_c_1,x=18,y=7,text="Front Panel Theme"} local fp_theme = RadioButton{parent=clr_c_1,x=18,y=8,default=ini_cfg.FrontPanelTheme,options=themes.FP_THEME_NAMES,callback=function()end,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.magenta} - TextBox{parent=clr_c_2,x=1,y=1,height=6,text="This system uses color heavily to distinguish ok and not, with some indicators using many colors. By selecting a mode below, indicators will change as shown. For non-standard modes, indicators with more than two colors will be split up."} + TextBox{parent=clr_c_2,x=1,y=1,height=6,text="This system uses color heavily to distinguish ok and not, with some indicators using many colors. By selecting a mode below, indicators will change as shown. For non-standard modes, indicators with more than two colors will usually be split up."} TextBox{parent=clr_c_2,x=21,y=7,text="Preview"} local _ = IndLight{parent=clr_c_2,x=21,y=8,label="Good",colors=cpair(colors.black,colors.green)} From 4e5858bd2dd76719ed6d018e403e1246ea032e92 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sun, 6 Oct 2024 18:21:04 -0400 Subject: [PATCH 11/11] optimizations on data handling in pocket and computer for internally loading reactor data structures --- coordinator/iocontrol.lua | 44 ++++++++++------------- coordinator/ui/components/unit_detail.lua | 10 +++--- pocket/iocontrol.lua | 33 ++++------------- pocket/ui/apps/control.lua | 10 +++--- 4 files changed, 33 insertions(+), 64 deletions(-) diff --git a/coordinator/iocontrol.lua b/coordinator/iocontrol.lua index 5670219..aa436a6 100644 --- a/coordinator/iocontrol.lua +++ b/coordinator/iocontrol.lua @@ -840,15 +840,27 @@ function iocontrol.update_unit_statuses(statuses) log.debug(log_header .. "reactor general status length mismatch") end - unit.reactor_data.rps_status = rps_status - unit.reactor_data.mek_status = mek_status - - -- if status hasn't been received, mek_status = {} - if type(unit.reactor_data.mek_status.act_burn_rate) == "number" then - burn_rate = unit.reactor_data.mek_status.act_burn_rate - burn_rate_sum = burn_rate_sum + burn_rate + for key, val in pairs(unit.reactor_data) do + if key ~= "rps_status" and key ~= "mek_struct" and key ~= "mek_status" then + unit.unit_ps.publish(key, val) + end end + unit.reactor_data.rps_status = rps_status + for key, val in pairs(rps_status) do + unit.unit_ps.publish(key, val) + end + + if next(mek_status) then + unit.reactor_data.mek_status = mek_status + for key, val in pairs(mek_status) do + unit.unit_ps.publish(key, val) + end + end + + burn_rate = unit.reactor_data.mek_status.act_burn_rate + burn_rate_sum = burn_rate_sum + burn_rate + if unit.reactor_data.mek_status.status then unit.unit_ps.publish("computed_status", 5) -- running else @@ -865,24 +877,6 @@ function iocontrol.update_unit_statuses(statuses) end end - for key, val in pairs(unit.reactor_data) do - if key ~= "rps_status" and key ~= "mek_struct" and key ~= "mek_status" then - unit.unit_ps.publish(key, val) - end - end - - if type(unit.reactor_data.rps_status) == "table" then - for key, val in pairs(unit.reactor_data.rps_status) do - unit.unit_ps.publish(key, val) - end - end - - if type(unit.reactor_data.mek_status) == "table" then - for key, val in pairs(unit.reactor_data.mek_status) do - unit.unit_ps.publish(key, val) - end - end - unit.connected = true else log.debug(log_header .. "reactor status length mismatch") diff --git a/coordinator/ui/components/unit_detail.lua b/coordinator/ui/components/unit_detail.lua index 709b684..8c9ce7a 100644 --- a/coordinator/ui/components/unit_detail.lua +++ b/coordinator/ui/components/unit_detail.lua @@ -381,12 +381,10 @@ local function init(parent, id) db.process.unit_ack[id].on_ack_alarms = ack_a.on_response local function start_button_en_check() - if (unit.reactor_data ~= nil) and (unit.reactor_data.mek_status ~= nil) then - local can_start = (not unit.reactor_data.mek_status.status) and - (not unit.reactor_data.rps_tripped) and - (unit.a_group == AUTO_GROUP.MANUAL) - if can_start then start.enable() else start.disable() end - end + local can_start = (not unit.reactor_data.mek_status.status) and + (not unit.reactor_data.rps_tripped) and + (unit.a_group == AUTO_GROUP.MANUAL) + if can_start then start.enable() else start.disable() end end start.register(u_ps, "status", start_button_en_check) diff --git a/pocket/iocontrol.lua b/pocket/iocontrol.lua index d1bf95e..36b5fd6 100644 --- a/pocket/iocontrol.lua +++ b/pocket/iocontrol.lua @@ -522,22 +522,16 @@ function iocontrol.record_unit_data(data) end end - if type(unit.reactor_data.rps_status) == "table" then - for key, val in pairs(unit.reactor_data.rps_status) do - unit.unit_ps.publish(key, val) - end + for key, val in pairs(unit.reactor_data.rps_status) do + unit.unit_ps.publish(key, val) end - if type(unit.reactor_data.mek_struct) == "table" then - for key, val in pairs(unit.reactor_data.mek_struct) do - unit.unit_ps.publish(key, val) - end + for key, val in pairs(unit.reactor_data.mek_struct) do + unit.unit_ps.publish(key, val) end - if type(unit.reactor_data.mek_status) == "table" then - for key, val in pairs(unit.reactor_data.mek_status) do - unit.unit_ps.publish(key, val) - end + for key, val in pairs(unit.reactor_data.mek_status) do + unit.unit_ps.publish(key, val) end end @@ -633,21 +627,6 @@ function iocontrol.record_unit_data(data) local function white(text) return { text = text, color = colors.white } end local function blue(text) return { text = text, color = colors.blue } end - -- unit.reactor_data.rps_status = { - -- high_dmg = false, - -- high_temp = false, - -- low_cool = false, - -- ex_waste = false, - -- ex_hcool = false, - -- no_fuel = false, - -- fault = false, - -- timeout = false, - -- manual = false, - -- automatic = false, - -- sys_fail = false, - -- force_dis = false - -- } - -- if unit.reactor_data.rps_status then -- for k, v in pairs(unit.alarms) do -- unit.alarms[k] = ALARM_STATE.TRIPPED diff --git a/pocket/ui/apps/control.lua b/pocket/ui/apps/control.lua index 59b1ffd..a74866b 100644 --- a/pocket/ui/apps/control.lua +++ b/pocket/ui/apps/control.lua @@ -167,12 +167,10 @@ local function new_view(root) unit.reset_rps_ack = reset.on_response local function start_button_en_check() - if (unit.reactor_data ~= nil) and (unit.reactor_data.mek_status ~= nil) then - local can_start = (not unit.reactor_data.mek_status.status) and - (not unit.reactor_data.rps_tripped) and - (unit.a_group == AUTO_GROUP.MANUAL) - if can_start then start.enable() else start.disable() end - end + local can_start = (not unit.reactor_data.mek_status.status) and + (not unit.reactor_data.rps_tripped) and + (unit.a_group == AUTO_GROUP.MANUAL) + if can_start then start.enable() else start.disable() end end start.register(u_ps, "status", start_button_en_check)