diff --git a/coordinator/configure.lua b/coordinator/configure.lua
index 31d359c..1cd945b 100644
--- a/coordinator/configure.lua
+++ b/coordinator/configure.lua
@@ -13,20 +13,20 @@ local util = require("scada-common.util")
local core = require("graphics.core")
local themes = require("graphics.themes")
-local DisplayBox = require("graphics.elements.displaybox")
-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 DisplayBox = require("graphics.elements.DisplayBox")
+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.push_button")
-local RadioButton = require("graphics.elements.controls.radio_button")
+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.number_field")
-local TextField = require("graphics.elements.form.text_field")
+local NumberField = require("graphics.elements.form.NumberField")
+local TextField = require("graphics.elements.form.TextField")
-local IndLight = require("graphics.elements.indicators.light")
+local IndLight = require("graphics.elements.indicators.IndicatorLight")
local println = util.println
local tri = util.trinary
@@ -71,7 +71,7 @@ local tool_ctl = {
net_listen = false,
sv_addr = comms.BROADCAST,
sv_seq_num = util.time_ms() * 10,
- sv_cool_conf = nil, ---@type table list of boiler & turbine counts
+ sv_cool_conf = nil, ---@type [ integer, integer ][] list of boiler & turbine counts
show_sv_cfg = nil, ---@type function
start_fail = 0,
@@ -81,36 +81,36 @@ local tool_ctl = {
importing_legacy = false,
jumped_to_color = false,
- view_cfg = nil, ---@type graphics_element
- color_cfg = nil, ---@type graphics_element
- color_next = nil, ---@type graphics_element
- color_apply = nil, ---@type graphics_element
- settings_apply = nil, ---@type graphics_element
+ view_cfg = nil, ---@type PushButton
+ color_cfg = nil, ---@type PushButton
+ color_next = nil, ---@type PushButton
+ color_apply = nil, ---@type PushButton
+ settings_apply = nil, ---@type PushButton
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 graphics_element
- auth_key_textbox = nil, ---@type graphics_element
+ show_key_btn = nil, ---@type PushButton
+ auth_key_textbox = nil, ---@type TextBox
auth_key_value = "",
sv_connect = nil, ---@type function
- sv_conn_button = nil, ---@type graphics_element
- sv_conn_status = nil, ---@type graphics_element
- sv_conn_detail = nil, ---@type graphics_element
- sv_skip = nil, ---@type graphics_element
- sv_next = nil, ---@type graphics_element
+ sv_conn_button = nil, ---@type PushButton
+ sv_conn_status = nil, ---@type TextBox
+ sv_conn_detail = nil, ---@type TextBox
+ sv_skip = nil, ---@type PushButton
+ sv_next = nil, ---@type PushButton
- apply_mon = nil, ---@type graphics_element
+ apply_mon = nil, ---@type PushButton
update_mon_reqs = nil, ---@type function
gen_mon_list = function () end,
edit_monitor = nil, ---@type function
mon_iface = "",
- mon_expect = {}
+ mon_expect = {} ---@type integer[]
}
---@class crd_config
@@ -302,7 +302,7 @@ local function load_settings(target, raw)
end
-- create the config view
----@param display graphics_element
+---@param display DisplayBox
local function config_view(display)
---@diagnostic disable-next-line: undefined-field
local function exit() os.queueEvent("terminate") end
@@ -460,11 +460,11 @@ local function config_view(display)
TextBox{parent=net_c_4,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra compution (can slow things down).",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_4,x=1,y=11,text="Facility Auth Key"}
- local key, _, censor = TextField{parent=net_c_4,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg}
+ local key, _ = TextField{parent=net_c_4,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg}
- local function censor_key(enable) censor(util.trinary(enable, "*", nil)) end
+ local function censor_key(enable) key.censor(util.trinary(enable, "*", nil)) end
- local hide_key = CheckBox{parent=net_c_4,x=34,y=12,label="Hide",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key}
+ local hide_key = Checkbox{parent=net_c_4,x=34,y=12,label="Hide",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key}
hide_key.set_value(true)
censor_key(true)
@@ -622,7 +622,7 @@ local function config_view(display)
local mon_desc = TextBox{parent=mon_c_3,x=1,y=1,height=4,text=""}
- local mon_unit_l, mon_unit = nil, nil ---@type graphics_element, graphics_element
+ local mon_unit_l, mon_unit = nil, nil ---@type TextBox, NumberField
local mon_warn = TextBox{parent=mon_c_3,x=1,y=11,height=2,text="",fg_bg=cpair(colors.red,colors.lightGray)}
@@ -706,7 +706,7 @@ local function config_view(display)
TextBox{parent=mon_c_4,x=1,y=1,height=3,text="For legacy compatibility with facilities built without space for a flow monitor, you can disable the flow monitor requirement here."}
TextBox{parent=mon_c_4,x=1,y=5,height=3,text="Please be aware that THIS OPTION WILL BE REMOVED ON RELEASE. Disabling it will only be available for the remainder of the beta."}
- local dis_flow_view = CheckBox{parent=mon_c_4,x=1,y=9,default=ini_cfg.DisableFlowView,label="Disable Flow View Monitor",box_fg_bg=cpair(colors.blue,colors.black)}
+ local dis_flow_view = Checkbox{parent=mon_c_4,x=1,y=9,default=ini_cfg.DisableFlowView,label="Disable Flow View Monitor",box_fg_bg=cpair(colors.blue,colors.black)}
local function back_from_legacy()
tmp_cfg.DisableFlowView = dis_flow_view.get_value()
@@ -790,7 +790,7 @@ local function config_view(display)
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=49,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 Logging Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)}
+ local en_dbg = Checkbox{parent=log_c_1,x=1,y=10,default=ini_cfg.LogDebug,label="Enable Logging Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)}
TextBox{parent=log_c_1,x=3,y=11,height=2,text="This results in much larger log files. It is best to only use this when there is a problem.",fg_bg=g_lg_fg_bg}
local path_err = TextBox{parent=log_c_1,x=8,y=14,width=35,text="Please provide a log file path.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
@@ -1263,7 +1263,7 @@ local function config_view(display)
-- list connected monitors
local monitors = ppm.get_monitor_list()
for iface, device in pairs(monitors) do
- local dev = device.dev
+ local dev = device.dev ---@type Monitor
dev.setTextScale(0.5)
dev.setTextColor(colors.white)
diff --git a/coordinator/coordinator.lua b/coordinator/coordinator.lua
index bb8bcee..78748c8 100644
--- a/coordinator/coordinator.lua
+++ b/coordinator/coordinator.lua
@@ -111,12 +111,12 @@ function coordinator.load_config()
---@class monitors_struct
local monitors = {
- main = nil, ---@type table|nil
+ main = nil, ---@type Monitor|nil
main_name = "",
- flow = nil, ---@type table|nil
+ flow = nil, ---@type Monitor|nil
flow_name = "",
- unit_displays = {},
- unit_name_map = {}
+ unit_displays = {}, ---@type Monitor[]
+ unit_name_map = {} ---@type string[]
}
local mon_cfv = util.new_validator()
@@ -623,7 +623,7 @@ function coordinator.comms(version, nic, sv_watchdog)
local unit_id = packet.data[2]
local ack = packet.data[3] == true
- local unit = iocontrol.get_db().units[unit_id] ---@type ioctl_unit
+ local unit = iocontrol.get_db().units[unit_id]
if unit ~= nil then
if cmd == UNIT_COMMAND.SCRAM then
diff --git a/coordinator/iocontrol.lua b/coordinator/iocontrol.lua
index 37230b3..41bb058 100644
--- a/coordinator/iocontrol.lua
+++ b/coordinator/iocontrol.lua
@@ -29,15 +29,6 @@ local iocontrol = {}
---@class ioctl
local io = {}
--- luacheck: no unused args
-
--- placeholder acknowledge function for type hinting
----@param success boolean
----@diagnostic disable-next-line: unused-local
-local function __generic_ack(success) end
-
--- luacheck: unused args
-
-- initialize front panel PSIL
---@param firmware_v string coordinator version
---@param comms_v string comms version
@@ -115,25 +106,23 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale)
radiation = types.new_zero_radiation_reading(),
- save_cfg_ack = __generic_ack,
- start_ack = __generic_ack,
- stop_ack = __generic_ack,
+ save_cfg_ack = nil, ---@type fun(success: boolean)
+ start_ack = nil, ---@type fun(success: boolean)
+ stop_ack = nil, ---@type fun(success: boolean)
+ ---@type { [TONE]: boolean }
alarm_tones = { false, false, false, false, false, false, false, false },
ps = psil.create(),
- induction_ps_tbl = {},
- induction_data_tbl = {},
+ induction_ps_tbl = {}, ---@type psil[]
+ induction_data_tbl = {}, ---@type imatrix_session_db[]
- sps_ps_tbl = {},
- sps_data_tbl = {},
+ sps_ps_tbl = {}, ---@type psil[]
+ sps_data_tbl = {}, ---@type sps_session_db[]
- tank_ps_tbl = {},
- tank_data_tbl = {},
-
- env_d_ps = psil.create(),
- env_d_data = {}
+ tank_ps_tbl = {}, ---@type psil[]
+ tank_data_tbl = {} ---@type dynamicv_session_db[]
}
-- create induction and SPS tables (currently only 1 of each is supported)
@@ -151,7 +140,7 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale)
end
-- create unit data structures
- io.units = {}
+ io.units = {} ---@type ioctl_unit[]
for i = 1, conf.num_units do
local function ack(alarm) process.ack_alarm(i, alarm) end
local function reset(alarm) process.reset_alarm(i, alarm) end
@@ -160,7 +149,10 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale)
local entry = {
unit_id = i,
connected = false,
- rtu_hw = { boilers = {}, turbines = {} },
+ rtu_hw = {
+ boilers = {}, ---@type { connected: boolean, faulted: boolean }[]
+ turbines = {} ---@type { connected: boolean, faulted: boolean }[]
+ },
num_boilers = 0,
num_turbines = 0,
@@ -208,7 +200,7 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale)
t_trip = { ack = function () ack(12) end, reset = function () reset(12) end }
},
- ---@type alarms
+ ---@type { [ALARM]: ALARM_STATE }
alarms = {
ALARM_STATE.INACTIVE, -- containment breach
ALARM_STATE.INACTIVE, -- containment radiation
@@ -224,19 +216,19 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale)
ALARM_STATE.INACTIVE -- turbine trip
},
- annunciator = {}, ---@type annunciator
+ annunciator = {}, ---@type annunciator
unit_ps = psil.create(),
- reactor_data = {}, ---@type reactor_db
+ reactor_data = {}, ---@type reactor_db
- boiler_ps_tbl = {},
- boiler_data_tbl = {},
+ boiler_ps_tbl = {}, ---@type psil[]
+ boiler_data_tbl = {}, ---@type boilerv_session_db[]
- turbine_ps_tbl = {},
- turbine_data_tbl = {},
+ turbine_ps_tbl = {}, ---@type psil[]
+ turbine_data_tbl = {}, ---@type turbinev_session_db[]
- tank_ps_tbl = {},
- tank_data_tbl = {}
+ tank_ps_tbl = {}, ---@type psil[]
+ tank_data_tbl = {} ---@type dynamicv_session_db[]
}
-- on other facility modes, overwrite unit TANK option with facility tank defs
@@ -357,8 +349,8 @@ end
-- record and publish multiblock RTU build data
---@param id integer
---@param entry table
----@param data_tbl table
----@param ps_tbl table
+---@param data_tbl (imatrix_session_db|sps_session_db|dynamicv_session_db|turbinev_session_db|boilerv_session_db)[]
+---@param ps_tbl psil[]
---@param create boolean? true to create an entry if non exists, false to fail on missing
---@return boolean ok true if data saved, false if invalid ID
local function _record_multiblock_build(id, entry, data_tbl, ps_tbl, create)
@@ -369,8 +361,8 @@ local function _record_multiblock_build(id, entry, data_tbl, ps_tbl, create)
data_tbl[id] = {}
end
- data_tbl[id].formed = entry[1] ---@type boolean
- data_tbl[id].build = entry[2] ---@type table
+ data_tbl[id].formed = entry[1]
+ data_tbl[id].build = entry[2]
ps_tbl[id].publish("formed", entry[1])
@@ -444,7 +436,7 @@ function iocontrol.record_unit_builds(builds)
else
-- reactor build
if type(build.reactor) == "table" then
- unit.reactor_data.mek_struct = build.reactor ---@type mek_struct
+ unit.reactor_data.mek_struct = build.reactor
for key, val in pairs(unit.reactor_data.mek_struct) do
unit.unit_ps.publish(key, val)
end
@@ -497,10 +489,10 @@ end
---@param ps psil
---@return boolean is_faulted
local function _record_multiblock_status(entry, data, ps)
- local is_faulted = entry[1] ---@type boolean
- data.formed = entry[2] ---@type boolean
- data.state = entry[3] ---@type table
- data.tanks = entry[4] ---@type table
+ local is_faulted = entry[1]
+ data.formed = entry[2]
+ data.state = entry[3]
+ data.tanks = entry[4]
ps.publish("formed", data.formed)
ps.publish("faulted", is_faulted)
@@ -600,8 +592,8 @@ function iocontrol.update_facility_status(status)
-- power statistics
if type(rtu_statuses.power) == "table" and #rtu_statuses.power == 4 then
- local data = fac.induction_data_tbl[1] ---@type imatrix_session_db
- local ps = fac.induction_ps_tbl[1] ---@type psil
+ local data = fac.induction_data_tbl[1]
+ local ps = fac.induction_ps_tbl[1]
local chg = tonumber(rtu_statuses.power[1])
local in_f = tonumber(rtu_statuses.power[2])
@@ -636,23 +628,23 @@ function iocontrol.update_facility_status(status)
for id, matrix in pairs(rtu_statuses.induction) do
if type(fac.induction_data_tbl[id]) == "table" then
- local data = fac.induction_data_tbl[id] ---@type imatrix_session_db
- local ps = fac.induction_ps_tbl[id] ---@type psil
+ local data = fac.induction_data_tbl[id]
+ local ps = fac.induction_ps_tbl[id]
local rtu_faulted = _record_multiblock_status(matrix, data, ps)
if rtu_faulted then
- ps.publish("computed_status", 3) -- faulted
+ ps.publish("computed_status", 3) -- faulted
elseif data.formed then
if data.tanks.energy_fill >= 0.99 then
- ps.publish("computed_status", 6) -- full
+ ps.publish("computed_status", 6) -- full
elseif data.tanks.energy_fill <= 0.01 then
- ps.publish("computed_status", 5) -- empty
+ ps.publish("computed_status", 5) -- empty
else
- ps.publish("computed_status", 4) -- on-line
+ ps.publish("computed_status", 4) -- on-line
end
else
- ps.publish("computed_status", 2) -- not formed
+ ps.publish("computed_status", 2) -- not formed
end
else
log.debug(util.c(log_header, "invalid induction matrix id ", id))
@@ -674,21 +666,21 @@ function iocontrol.update_facility_status(status)
for id, sps in pairs(rtu_statuses.sps) do
if type(fac.sps_data_tbl[id]) == "table" then
- local data = fac.sps_data_tbl[id] ---@type sps_session_db
- local ps = fac.sps_ps_tbl[id] ---@type psil
+ local data = fac.sps_data_tbl[id]
+ local ps = fac.sps_ps_tbl[id]
local rtu_faulted = _record_multiblock_status(sps, data, ps)
if rtu_faulted then
- ps.publish("computed_status", 3) -- faulted
+ ps.publish("computed_status", 3) -- faulted
elseif data.formed then
if data.state.process_rate > 0 then
- ps.publish("computed_status", 5) -- active
+ ps.publish("computed_status", 5) -- active
else
- ps.publish("computed_status", 4) -- idle
+ ps.publish("computed_status", 4) -- idle
end
else
- ps.publish("computed_status", 2) -- not formed
+ ps.publish("computed_status", 2) -- not formed
end
io.facility.ps.publish("am_rate", data.state.process_rate * 1000)
@@ -712,23 +704,23 @@ function iocontrol.update_facility_status(status)
for id, tank in pairs(rtu_statuses.tanks) do
if type(fac.tank_data_tbl[id]) == "table" then
- local data = fac.tank_data_tbl[id] ---@type dynamicv_session_db
- local ps = fac.tank_ps_tbl[id] ---@type psil
+ local data = fac.tank_data_tbl[id]
+ local ps = fac.tank_ps_tbl[id]
local rtu_faulted = _record_multiblock_status(tank, data, ps)
if rtu_faulted then
- ps.publish("computed_status", 3) -- faulted
+ ps.publish("computed_status", 3) -- faulted
elseif data.formed then
if data.tanks.fill >= 0.99 then
- ps.publish("computed_status", 6) -- full
+ ps.publish("computed_status", 6) -- full
elseif data.tanks.fill < 0.20 then
- ps.publish("computed_status", 5) -- low
+ ps.publish("computed_status", 5) -- low
else
- ps.publish("computed_status", 4) -- on-line
+ ps.publish("computed_status", 4) -- on-line
end
else
- ps.publish("computed_status", 2) -- not formed
+ ps.publish("computed_status", 2) -- not formed
end
else
log.debug(util.c(log_header, "invalid dynamic tank id ", id))
@@ -812,7 +804,7 @@ function iocontrol.update_unit_statuses(statuses)
for i = 1, #statuses do
local log_header = util.c("iocontrol.update_unit_statuses[unit ", i, "]: ")
- local unit = io.units[i] ---@type ioctl_unit
+ local unit = io.units[i]
local status = statuses[i]
local burn_rate = 0.0
@@ -848,8 +840,8 @@ function iocontrol.update_unit_statuses(statuses)
log.debug(log_header .. "reactor general status length mismatch")
end
- unit.reactor_data.rps_status = rps_status ---@type rps_status
- unit.reactor_data.mek_status = mek_status ---@type mek_status
+ 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
@@ -858,18 +850,18 @@ function iocontrol.update_unit_statuses(statuses)
end
if unit.reactor_data.mek_status.status then
- unit.unit_ps.publish("computed_status", 5) -- running
+ unit.unit_ps.publish("computed_status", 5) -- running
else
if unit.reactor_data.no_reactor then
- unit.unit_ps.publish("computed_status", 3) -- faulted
+ unit.unit_ps.publish("computed_status", 3) -- faulted
elseif not unit.reactor_data.formed then
- unit.unit_ps.publish("computed_status", 2) -- multiblock not formed
+ unit.unit_ps.publish("computed_status", 2) -- multiblock not formed
elseif unit.reactor_data.rps_status.force_dis then
- unit.unit_ps.publish("computed_status", 7) -- reactor force disabled
+ unit.unit_ps.publish("computed_status", 7) -- reactor force disabled
elseif unit.reactor_data.rps_tripped and unit.reactor_data.rps_trip_cause ~= "manual" then
- unit.unit_ps.publish("computed_status", 6) -- SCRAM
+ unit.unit_ps.publish("computed_status", 6) -- SCRAM
else
- unit.unit_ps.publish("computed_status", 4) -- disabled
+ unit.unit_ps.publish("computed_status", 4) -- disabled
end
end
@@ -917,24 +909,24 @@ function iocontrol.update_unit_statuses(statuses)
for id, boiler in pairs(rtu_statuses.boilers) do
if type(unit.boiler_data_tbl[id]) == "table" then
- local data = unit.boiler_data_tbl[id] ---@type boilerv_session_db
- local ps = unit.boiler_ps_tbl[id] ---@type psil
+ local data = unit.boiler_data_tbl[id]
+ local ps = unit.boiler_ps_tbl[id]
local rtu_faulted = _record_multiblock_status(boiler, data, ps)
unit.rtu_hw.boilers[id].faulted = rtu_faulted
if rtu_faulted then
- ps.publish("computed_status", 3) -- faulted
+ ps.publish("computed_status", 3) -- faulted
elseif data.formed then
boil_sum = boil_sum + data.state.boil_rate
if data.state.boil_rate > 0 then
- ps.publish("computed_status", 5) -- active
+ ps.publish("computed_status", 5) -- active
else
- ps.publish("computed_status", 4) -- idle
+ ps.publish("computed_status", 4) -- idle
end
else
- ps.publish("computed_status", 2) -- not formed
+ ps.publish("computed_status", 2) -- not formed
end
else
log.debug(util.c(log_header, "invalid boiler id ", id))
@@ -964,26 +956,26 @@ function iocontrol.update_unit_statuses(statuses)
for id, turbine in pairs(rtu_statuses.turbines) do
if type(unit.turbine_data_tbl[id]) == "table" then
- local data = unit.turbine_data_tbl[id] ---@type turbinev_session_db
- local ps = unit.turbine_ps_tbl[id] ---@type psil
+ local data = unit.turbine_data_tbl[id]
+ local ps = unit.turbine_ps_tbl[id]
local rtu_faulted = _record_multiblock_status(turbine, data, ps)
unit.rtu_hw.turbines[id].faulted = rtu_faulted
if rtu_faulted then
- ps.publish("computed_status", 3) -- faulted
+ ps.publish("computed_status", 3) -- faulted
elseif data.formed then
flow_sum = flow_sum + data.state.flow_rate
if data.tanks.energy_fill >= 0.99 then
- ps.publish("computed_status", 6) -- trip
+ ps.publish("computed_status", 6) -- trip
elseif data.state.flow_rate < 100 then
- ps.publish("computed_status", 4) -- idle
+ ps.publish("computed_status", 4) -- idle
else
- ps.publish("computed_status", 5) -- active
+ ps.publish("computed_status", 5) -- active
end
else
- ps.publish("computed_status", 2) -- not formed
+ ps.publish("computed_status", 2) -- not formed
end
else
log.debug(util.c(log_header, "invalid turbine id ", id))
@@ -1008,23 +1000,23 @@ function iocontrol.update_unit_statuses(statuses)
for id, tank in pairs(rtu_statuses.tanks) do
if type(unit.tank_data_tbl[id]) == "table" then
- local data = unit.tank_data_tbl[id] ---@type dynamicv_session_db
- local ps = unit.tank_ps_tbl[id] ---@type psil
+ local data = unit.tank_data_tbl[id]
+ local ps = unit.tank_ps_tbl[id]
local rtu_faulted = _record_multiblock_status(tank, data, ps)
if rtu_faulted then
- ps.publish("computed_status", 3) -- faulted
+ ps.publish("computed_status", 3) -- faulted
elseif data.formed then
if data.tanks.fill >= 0.99 then
- ps.publish("computed_status", 6) -- full
+ ps.publish("computed_status", 6) -- full
elseif data.tanks.fill < 0.20 then
- ps.publish("computed_status", 5) -- low
+ ps.publish("computed_status", 5) -- low
else
- ps.publish("computed_status", 4) -- on-line
+ ps.publish("computed_status", 4) -- on-line
end
else
- ps.publish("computed_status", 2) -- not formed
+ ps.publish("computed_status", 2) -- not formed
end
else
log.debug(util.c(log_header, "invalid dynamic tank id ", id))
diff --git a/coordinator/process.lua b/coordinator/process.lua
index 5f7f010..f96b3e7 100644
--- a/coordinator/process.lua
+++ b/coordinator/process.lua
@@ -29,13 +29,13 @@ local pctl = {
burn_target = 0.0,
charge_target = 0.0,
gen_target = 0.0,
- limits = {},
+ limits = {}, ---@type number[]
waste_product = PRODUCT.PLUTONIUM,
pu_fallback = false,
sps_low_power = false
},
- waste_modes = {},
- priority_groups = {}
+ waste_modes = {}, ---@type WASTE_MODE[]
+ priority_groups = {} ---@type AUTO_GROUP[]
},
commands = {
unit = {}, ---@type process_command_state[][]
@@ -46,7 +46,7 @@ local pctl = {
---@class process_command_state
---@field active boolean if this command is live
---@field timeout integer expiration time of this command request
----@field requestors table list of callbacks from the requestors
+---@field requestors function[] list of callbacks from the requestors
-- write auto process control to config file
local function _write_auto_config()
@@ -80,8 +80,8 @@ function process.init(iocontrol, coord_comms)
ctl_proc.limits[i] = 0.1
end
- local ctrl_states = settings.get("ControlStates", {})
- local config = ctrl_states.process ---@type sys_auto_config
+ local ctrl_states = settings.get("ControlStates", {}) ---@type sys_control_states
+ local config = ctrl_states.process
-- facility auto control configuration
if type(config) == "table" then
@@ -103,7 +103,7 @@ function process.init(iocontrol, coord_comms)
pctl.io.facility.ps.publish("process_sps_low_power", ctl_proc.sps_low_power)
for id = 1, math.min(#ctl_proc.limits, pctl.io.facility.num_units) do
- local unit = pctl.io.units[id] ---@type ioctl_unit
+ local unit = pctl.io.units[id]
unit.unit_ps.publish("burn_limit", ctl_proc.limits[id])
end
@@ -116,7 +116,7 @@ function process.init(iocontrol, coord_comms)
end
-- unit waste states
- local waste_modes = ctrl_states.waste_modes ---@type table|nil
+ local waste_modes = ctrl_states.waste_modes
if type(waste_modes) == "table" then
for id, mode in pairs(waste_modes) do
pctl.control_states.waste_modes[id] = mode
@@ -127,7 +127,7 @@ function process.init(iocontrol, coord_comms)
end
-- unit priority groups
- local prio_groups = ctrl_states.priority_groups ---@type table|nil
+ local prio_groups = ctrl_states.priority_groups
if type(prio_groups) == "table" then
for id, group in pairs(prio_groups) do
pctl.control_states.priority_groups[id] = group
@@ -443,7 +443,7 @@ end
---@param burn_target number burn rate target
---@param charge_target number charge target
---@param gen_target number generation rate target
----@param limits table unit burn rate limits
+---@param limits number[] unit burn rate limits
function process.save(mode, burn_target, charge_target, gen_target, limits)
log.debug("PROCESS: SAVE")
@@ -473,7 +473,7 @@ function process.start_ack_handle(response)
for i = 1, math.min(#response[6], pctl.io.facility.num_units) do
ctl_proc.limits[i] = response[6][i]
- local unit = pctl.io.units[i] ---@type ioctl_unit
+ local unit = pctl.io.units[i]
unit.unit_ps.publish("burn_limit", ctl_proc.limits[i])
end
diff --git a/coordinator/renderer.lua b/coordinator/renderer.lua
index f2d2418..cfa5013 100644
--- a/coordinator/renderer.lua
+++ b/coordinator/renderer.lua
@@ -19,7 +19,7 @@ local unit_view = require("coordinator.ui.layout.unit_view")
local core = require("graphics.core")
local flasher = require("graphics.flasher")
-local DisplayBox = require("graphics.elements.displaybox")
+local DisplayBox = require("graphics.elements.DisplayBox")
local log_render = coordinator.log_render
@@ -30,20 +30,20 @@ local renderer = {}
local engine = {
color_mode = 1, ---@type COLOR_MODE
monitors = nil, ---@type monitors_struct|nil
- dmesg_window = nil, ---@type table|nil
+ dmesg_window = nil, ---@type Window|nil
ui_ready = false,
fp_ready = false,
ui = {
- front_panel = nil, ---@type graphics_element|nil
- main_display = nil, ---@type graphics_element|nil
- flow_display = nil, ---@type graphics_element|nil
- unit_displays = {}
+ front_panel = nil, ---@type DisplayBox|nil
+ main_display = nil, ---@type DisplayBox|nil
+ flow_display = nil, ---@type DisplayBox|nil
+ unit_displays = {} ---@type (DisplayBox|nil)[]
},
disable_flow_view = false
}
-- init a display to the "default", but set text scale to 0.5
----@param monitor table monitor
+---@param monitor Monitor monitor
local function _init_display(monitor)
monitor.setTextScale(0.5)
monitor.setTextColor(colors.white)
@@ -64,7 +64,7 @@ local function _init_display(monitor)
end
-- print out that the monitor is too small
----@param monitor table monitor
+---@param monitor Monitor monitor
local function _print_too_small(monitor)
monitor.setCursorPos(1, 1)
monitor.setBackgroundColor(colors.black)
@@ -275,7 +275,7 @@ function renderer.fp_ready() return engine.fp_ready end
function renderer.ui_ready() return engine.ui_ready end
-- handle a monitor peripheral being disconnected
----@param device table monitor
+---@param device Monitor monitor
---@return boolean is_used if the monitor is one of the configured monitors
function renderer.handle_disconnect(device)
local is_used = false
@@ -326,7 +326,7 @@ end
-- handle a monitor peripheral being reconnected
---@param name string monitor name
----@param device table monitor
+---@param device Monitor monitor
---@return boolean is_used if the monitor is one of the configured monitors
function renderer.handle_reconnect(name, device)
local is_used = false
@@ -373,7 +373,7 @@ function renderer.handle_resize(name)
if not engine.monitors then return false, false end
if engine.monitors.main_name == name and engine.monitors.main then
- local device = engine.monitors.main ---@type table
+ local device = engine.monitors.main ---@type Monitor
-- this is necessary if the bottom left block was broken and on reconnect
_init_display(device)
@@ -416,7 +416,7 @@ function renderer.handle_resize(name)
end
else engine.dmesg_window.redraw() end
elseif engine.monitors.flow_name == name and engine.monitors.flow then
- local device = engine.monitors.flow ---@type table
+ local device = engine.monitors.flow ---@type Monitor
-- this is necessary if the bottom left block was broken and on reconnect
_init_display(device)
diff --git a/coordinator/session/apisessions.lua b/coordinator/session/apisessions.lua
index 5c4a38a..30fee09 100644
--- a/coordinator/session/apisessions.lua
+++ b/coordinator/session/apisessions.lua
@@ -13,7 +13,7 @@ local self = {
nic = nil, ---@type nic
config = nil, ---@type crd_config
next_id = 0,
- sessions = {}
+ sessions = {} ---@type pkt_session_struct[]
}
-- PRIVATE FUNCTIONS --
@@ -129,7 +129,7 @@ end
---@param timer_event number
function apisessions.check_all_watchdogs(timer_event)
for i = 1, #self.sessions do
- local session = self.sessions[i] ---@type pkt_session_struct
+ local session = self.sessions[i]
if session.open then
local triggered = session.instance.check_wd(timer_event)
if triggered then
@@ -143,7 +143,7 @@ end
-- iterate all the API sessions
function apisessions.iterate_all()
for i = 1, #self.sessions do
- local session = self.sessions[i] ---@type pkt_session_struct
+ local session = self.sessions[i]
if session.open and session.instance.iterate() then
_api_handle_outq(session)
@@ -168,7 +168,7 @@ end
-- close all open connections
function apisessions.close_all()
for i = 1, #self.sessions do
- local session = self.sessions[i] ---@type pkt_session_struct
+ local session = self.sessions[i]
if session.open then _shutdown(session) end
end
diff --git a/coordinator/session/pocket.lua b/coordinator/session/pocket.lua
index 0205397..aba0584 100644
--- a/coordinator/session/pocket.lua
+++ b/coordinator/session/pocket.lua
@@ -217,7 +217,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
_send(CRDN_TYPE.API_GET_FAC, data)
elseif pkt.type == CRDN_TYPE.API_GET_UNIT then
if pkt.length == 1 and type(pkt.data[1]) == "number" then
- local u = db.units[pkt.data[1]] ---@type ioctl_unit
+ local u = db.units[pkt.data[1]]
if u then
local data = {
diff --git a/coordinator/sounder.lua b/coordinator/sounder.lua
index e7a02ac..7ec48c5 100644
--- a/coordinator/sounder.lua
+++ b/coordinator/sounder.lua
@@ -9,7 +9,7 @@ local log = require("scada-common.log")
local sounder = {}
local alarm_ctl = {
- speaker = nil,
+ speaker = nil, ---@type Speaker
volume = 0.5,
stream = audio.new_stream()
}
@@ -24,7 +24,7 @@ local function play()
end
-- initialize the annunciator alarm system
----@param speaker table speaker peripheral
+---@param speaker Speaker speaker peripheral
---@param volume number speaker volume
function sounder.init(speaker, volume)
alarm_ctl.speaker = speaker
@@ -36,7 +36,7 @@ function sounder.init(speaker, volume)
end
-- reconnect the speaker peripheral
----@param speaker table speaker peripheral
+---@param speaker Speaker speaker peripheral
function sounder.reconnect(speaker)
alarm_ctl.speaker = speaker
alarm_ctl.playing = false
@@ -44,7 +44,7 @@ function sounder.reconnect(speaker)
end
-- set alarm tones
----@param states table alarm tone commands from supervisor
+---@param states { [TONE]: boolean } alarm tone commands from supervisor
function sounder.set(states)
-- set tone states
for id = 1, #states do alarm_ctl.stream.set_active(id, states[id]) end
diff --git a/coordinator/startup.lua b/coordinator/startup.lua
index 52ed4a6..637f500 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.8"
+local COORDINATOR_VERSION = "v1.5.9"
local CHUNK_LOAD_DELAY_S = 30.0
@@ -152,7 +152,7 @@ local function main()
-- core coordinator devices
crd_dev = {
modem = ppm.get_wireless_modem(),
- speaker = ppm.get_device("speaker")
+ speaker = ppm.get_device("speaker") ---@type Speaker|nil
},
-- system objects
diff --git a/coordinator/threads.lua b/coordinator/threads.lua
index cefe705..0392178 100644
--- a/coordinator/threads.lua
+++ b/coordinator/threads.lua
@@ -68,6 +68,7 @@ function threads.thread__main(smem)
if type ~= nil and device ~= nil then
if type == "modem" then
+ ---@cast device Modem
-- we only really care if this is our wireless modem
-- if it is another modem, handle other peripheral losses separately
if nic.is_modem(device) then
@@ -91,8 +92,10 @@ function threads.thread__main(smem)
log_sys("non-comms modem disconnected")
end
elseif type == "monitor" then
+ ---@cast device Monitor
smem.q.mq_render.push_data(MQ__RENDER_DATA.MON_DISCONNECT, device)
elseif type == "speaker" then
+ ---@cast device Speaker
log_sys("lost alarm sounder speaker")
iocontrol.fp_has_speaker(false)
end
@@ -102,6 +105,7 @@ function threads.thread__main(smem)
if type ~= nil and device ~= nil then
if type == "modem" then
+ ---@cast device Modem
if device.isWireless() and not nic.is_connected() then
-- reconnected modem
log_sys("comms modem reconnected")
@@ -113,8 +117,10 @@ function threads.thread__main(smem)
log_sys("wired modem reconnected")
end
elseif type == "monitor" then
+ ---@cast device Monitor
smem.q.mq_render.push_data(MQ__RENDER_DATA.MON_CONNECT, { name = param1, device = device })
elseif type == "speaker" then
+ ---@cast device Speaker
log_sys("alarm sounder speaker reconnected")
sounder.reconnect(device)
iocontrol.fp_has_speaker(true)
diff --git a/coordinator/ui/components/boiler.lua b/coordinator/ui/components/boiler.lua
index 86866f5..38bd05c 100644
--- a/coordinator/ui/components/boiler.lua
+++ b/coordinator/ui/components/boiler.lua
@@ -4,18 +4,18 @@ local style = require("coordinator.ui.style")
local core = require("graphics.core")
-local Rectangle = require("graphics.elements.rectangle")
-local TextBox = require("graphics.elements.textbox")
+local Rectangle = require("graphics.elements.Rectangle")
+local TextBox = require("graphics.elements.TextBox")
-local DataIndicator = require("graphics.elements.indicators.data")
-local StateIndicator = require("graphics.elements.indicators.state")
-local VerticalBar = require("graphics.elements.indicators.vbar")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
+local StateIndicator = require("graphics.elements.indicators.StateIndicator")
+local VerticalBar = require("graphics.elements.indicators.VerticalBar")
local cpair = core.cpair
local border = core.border
-- new boiler view
----@param root graphics_element parent
+---@param root Container parent
---@param x integer top left x
---@param y integer top left y
---@param ps psil ps interface
diff --git a/coordinator/ui/components/imatrix.lua b/coordinator/ui/components/imatrix.lua
index cfec34d..186f7bd 100644
--- a/coordinator/ui/components/imatrix.lua
+++ b/coordinator/ui/components/imatrix.lua
@@ -6,15 +6,15 @@ local style = require("coordinator.ui.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local Rectangle = require("graphics.elements.rectangle")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local Rectangle = require("graphics.elements.Rectangle")
+local TextBox = require("graphics.elements.TextBox")
-local DataIndicator = require("graphics.elements.indicators.data")
-local IndicatorLight = require("graphics.elements.indicators.light")
-local PowerIndicator = require("graphics.elements.indicators.power")
-local StateIndicator = require("graphics.elements.indicators.state")
-local VerticalBar = require("graphics.elements.indicators.vbar")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
+local IndicatorLight = require("graphics.elements.indicators.IndicatorLight")
+local PowerIndicator = require("graphics.elements.indicators.PowerIndicator")
+local StateIndicator = require("graphics.elements.indicators.StateIndicator")
+local VerticalBar = require("graphics.elements.indicators.VerticalBar")
local cpair = core.cpair
local border = core.border
@@ -22,7 +22,7 @@ local border = core.border
local ALIGN = core.ALIGN
-- new induction matrix view
----@param root graphics_element parent
+---@param root Container parent
---@param x integer top left x
---@param y integer top left y
---@param data imatrix_session_db matrix data
diff --git a/coordinator/ui/components/pkt_entry.lua b/coordinator/ui/components/pkt_entry.lua
index e377e2e..b7a8d1e 100644
--- a/coordinator/ui/components/pkt_entry.lua
+++ b/coordinator/ui/components/pkt_entry.lua
@@ -8,17 +8,17 @@ local style = require("coordinator.ui.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local TextBox = require("graphics.elements.TextBox")
-local DataIndicator = require("graphics.elements.indicators.data")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
local ALIGN = core.ALIGN
local cpair = core.cpair
-- create a pocket list entry
----@param parent graphics_element parent
+---@param parent ListBox parent
---@param id integer PKT session ID
local function init(parent, id)
local s_hi_box = style.fp_theme.highlight_box
diff --git a/coordinator/ui/components/process_ctl.lua b/coordinator/ui/components/process_ctl.lua
index 85e0436..44c9ceb 100644
--- a/coordinator/ui/components/process_ctl.lua
+++ b/coordinator/ui/components/process_ctl.lua
@@ -8,20 +8,20 @@ local style = require("coordinator.ui.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local Rectangle = require("graphics.elements.rectangle")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local Rectangle = require("graphics.elements.Rectangle")
+local TextBox = require("graphics.elements.TextBox")
-local DataIndicator = require("graphics.elements.indicators.data")
-local IndicatorLight = require("graphics.elements.indicators.light")
-local RadIndicator = require("graphics.elements.indicators.rad")
-local StateIndicator = require("graphics.elements.indicators.state")
-local TriIndicatorLight = require("graphics.elements.indicators.trilight")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
+local IndicatorLight = require("graphics.elements.indicators.IndicatorLight")
+local RadIndicator = require("graphics.elements.indicators.RadIndicator")
+local StateIndicator = require("graphics.elements.indicators.StateIndicator")
+local TriIndicatorLight = require("graphics.elements.indicators.TriIndicatorLight")
-local Checkbox = require("graphics.elements.controls.checkbox")
-local HazardButton = require("graphics.elements.controls.hazard_button")
-local RadioButton = require("graphics.elements.controls.radio_button")
-local SpinboxNumeric = require("graphics.elements.controls.spinbox_numeric")
+local Checkbox = require("graphics.elements.controls.Checkbox")
+local HazardButton = require("graphics.elements.controls.HazardButton")
+local NumericSpinbox = require("graphics.elements.controls.NumericSpinbox")
+local RadioButton = require("graphics.elements.controls.RadioButton")
local ALIGN = core.ALIGN
@@ -33,7 +33,7 @@ local bw_fg_bg = style.bw_fg_bg
local period = core.flasher.PERIOD
-- new process control view
----@param root graphics_element parent
+---@param root Container parent
---@param x integer top left x
---@param y integer top left y
local function new_view(root, x, y)
@@ -131,7 +131,7 @@ local function new_view(root, x, y)
TextBox{parent=burn_tag,x=2,y=2,text="Burn Target",width=7,height=2}
local burn_target = Div{parent=targets,x=9,y=1,width=23,height=3,fg_bg=s_hi_box}
- local b_target = SpinboxNumeric{parent=burn_target,x=11,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=arrow_fg_bg,arrow_disable=style.theme.disabled}
+ local b_target = NumericSpinbox{parent=burn_target,x=11,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=arrow_fg_bg,arrow_disable=style.theme.disabled}
TextBox{parent=burn_target,x=18,y=2,text="mB/t",fg_bg=style.theme.label_fg}
local burn_sum = DataIndicator{parent=targets,x=9,y=4,label="",format="%18.1f",value=0,unit="mB/t",commas=true,lu_colors=black,width=23,fg_bg=blk_brn}
@@ -142,7 +142,7 @@ local function new_view(root, x, y)
TextBox{parent=chg_tag,x=2,y=2,text="Charge Target",width=7,height=2}
local chg_target = Div{parent=targets,x=9,y=6,width=23,height=3,fg_bg=s_hi_box}
- local c_target = SpinboxNumeric{parent=chg_target,x=2,y=1,whole_num_precision=15,fractional_precision=0,min=0,arrow_fg_bg=arrow_fg_bg,arrow_disable=style.theme.disabled}
+ local c_target = NumericSpinbox{parent=chg_target,x=2,y=1,whole_num_precision=15,fractional_precision=0,min=0,arrow_fg_bg=arrow_fg_bg,arrow_disable=style.theme.disabled}
TextBox{parent=chg_target,x=18,y=2,text="M"..db.energy_label,fg_bg=style.theme.label_fg}
local cur_charge = DataIndicator{parent=targets,x=9,y=9,label="",format="%19d",value=0,unit="M"..db.energy_label,commas=true,lu_colors=black,width=23,fg_bg=blk_brn}
@@ -153,7 +153,7 @@ local function new_view(root, x, y)
TextBox{parent=gen_tag,x=2,y=2,text="Gen. Target",width=7,height=2}
local gen_target = Div{parent=targets,x=9,y=11,width=23,height=3,fg_bg=s_hi_box}
- local g_target = SpinboxNumeric{parent=gen_target,x=8,y=1,whole_num_precision=9,fractional_precision=0,min=0,arrow_fg_bg=arrow_fg_bg,arrow_disable=style.theme.disabled}
+ local g_target = NumericSpinbox{parent=gen_target,x=8,y=1,whole_num_precision=9,fractional_precision=0,min=0,arrow_fg_bg=arrow_fg_bg,arrow_disable=style.theme.disabled}
TextBox{parent=gen_target,x=18,y=2,text="k"..db.energy_label.."/t",fg_bg=style.theme.label_fg}
local cur_gen = DataIndicator{parent=targets,x=9,y=14,label="",format="%17d",value=0,unit="k"..db.energy_label.."/t",commas=true,lu_colors=black,width=23,fg_bg=blk_brn}
@@ -177,7 +177,7 @@ local function new_view(root, x, y)
local cur_lu = style.theme.disabled
if i <= facility.num_units then
- unit = units[i] ---@type ioctl_unit
+ unit = units[i]
tag_fg_bg = cpair(colors.black, colors.lightBlue)
lim_fg_bg = s_hi_box
label_fg = style.theme.label_fg
@@ -191,7 +191,7 @@ local function new_view(root, x, y)
TextBox{parent=unit_tag,x=2,y=2,text="Unit "..i.." Limit",width=7,height=2}
local lim_ctl = Div{parent=limit_div,x=9,y=_y,width=14,height=3,fg_bg=s_hi_box}
- local lim = SpinboxNumeric{parent=lim_ctl,x=2,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=arrow_fg_bg,arrow_disable=style.theme.disabled,fg_bg=lim_fg_bg}
+ local lim = NumericSpinbox{parent=lim_ctl,x=2,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=arrow_fg_bg,arrow_disable=style.theme.disabled,fg_bg=lim_fg_bg}
TextBox{parent=lim_ctl,x=9,y=2,text="mB/t",width=4,fg_bg=label_fg}
local cur_burn = DataIndicator{parent=limit_div,x=9,y=_y+3,label="",format="%7.1f",value=0,unit="mB/t",commas=false,lu_colors=cpair(cur_lu,cur_lu),width=14,fg_bg=cur_fg_bg}
@@ -234,7 +234,7 @@ local function new_view(root, x, y)
local degraded = IndicatorLight{parent=lights,x=2,y=3,label="Degraded",colors=cpair(ind_red.fgd,ind_off),flash=true,period=period.BLINK_250_MS}
if i <= facility.num_units then
- local unit = units[i] ---@type ioctl_unit
+ local unit = units[i]
ready.register(unit.unit_ps, "U_AutoReady", ready.update)
degraded.register(unit.unit_ps, "U_AutoDegraded", degraded.update)
@@ -323,7 +323,7 @@ local function new_view(root, x, y)
local waste_status = Div{parent=proc,width=24,height=4,x=57,y=1,}
for i = 1, facility.num_units do
- local unit = units[i] ---@type ioctl_unit
+ local unit = units[i]
TextBox{parent=waste_status,y=i,text="U"..i.." Waste",width=8}
local a_waste = IndicatorLight{parent=waste_status,x=10,y=i,label="Auto",colors=ind_wht}
diff --git a/coordinator/ui/components/reactor.lua b/coordinator/ui/components/reactor.lua
index 2319f76..f1cec6d 100644
--- a/coordinator/ui/components/reactor.lua
+++ b/coordinator/ui/components/reactor.lua
@@ -6,18 +6,18 @@ local style = require("coordinator.ui.style")
local core = require("graphics.core")
-local Rectangle = require("graphics.elements.rectangle")
-local TextBox = require("graphics.elements.textbox")
+local Rectangle = require("graphics.elements.Rectangle")
+local TextBox = require("graphics.elements.TextBox")
-local DataIndicator = require("graphics.elements.indicators.data")
-local HorizontalBar = require("graphics.elements.indicators.hbar")
-local StateIndicator = require("graphics.elements.indicators.state")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
+local HorizontalBar = require("graphics.elements.indicators.HorizontalBar")
+local StateIndicator = require("graphics.elements.indicators.StateIndicator")
local cpair = core.cpair
local border = core.border
-- create new reactor view
----@param root graphics_element parent
+---@param root Container parent
---@param x integer top left x
---@param y integer top left y
---@param ps psil ps interface
diff --git a/coordinator/ui/components/turbine.lua b/coordinator/ui/components/turbine.lua
index fd6049a..6ce3d11 100644
--- a/coordinator/ui/components/turbine.lua
+++ b/coordinator/ui/components/turbine.lua
@@ -4,19 +4,19 @@ local style = require("coordinator.ui.style")
local core = require("graphics.core")
-local Rectangle = require("graphics.elements.rectangle")
-local TextBox = require("graphics.elements.textbox")
+local Rectangle = require("graphics.elements.Rectangle")
+local TextBox = require("graphics.elements.TextBox")
-local DataIndicator = require("graphics.elements.indicators.data")
-local PowerIndicator = require("graphics.elements.indicators.power")
-local StateIndicator = require("graphics.elements.indicators.state")
-local VerticalBar = require("graphics.elements.indicators.vbar")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
+local PowerIndicator = require("graphics.elements.indicators.PowerIndicator")
+local StateIndicator = require("graphics.elements.indicators.StateIndicator")
+local VerticalBar = require("graphics.elements.indicators.VerticalBar")
local cpair = core.cpair
local border = core.border
-- new turbine view
----@param root graphics_element parent
+---@param root Container parent
---@param x integer top left x
---@param y integer top left y
---@param ps psil ps interface
diff --git a/coordinator/ui/components/unit_detail.lua b/coordinator/ui/components/unit_detail.lua
index fcfd062..709b684 100644
--- a/coordinator/ui/components/unit_detail.lua
+++ b/coordinator/ui/components/unit_detail.lua
@@ -11,23 +11,23 @@ local style = require("coordinator.ui.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local Rectangle = require("graphics.elements.rectangle")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local Rectangle = require("graphics.elements.Rectangle")
+local TextBox = require("graphics.elements.TextBox")
-local AlarmLight = require("graphics.elements.indicators.alight")
-local CoreMap = require("graphics.elements.indicators.coremap")
-local DataIndicator = require("graphics.elements.indicators.data")
-local IndicatorLight = require("graphics.elements.indicators.light")
-local RadIndicator = require("graphics.elements.indicators.rad")
-local TriIndicatorLight = require("graphics.elements.indicators.trilight")
-local VerticalBar = require("graphics.elements.indicators.vbar")
+local AlarmLight = require("graphics.elements.indicators.AlarmLight")
+local CoreMap = require("graphics.elements.indicators.CoreMap")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
+local IndicatorLight = require("graphics.elements.indicators.IndicatorLight")
+local RadIndicator = require("graphics.elements.indicators.RadIndicator")
+local TriIndicatorLight = require("graphics.elements.indicators.TriIndicatorLight")
+local VerticalBar = require("graphics.elements.indicators.VerticalBar")
-local HazardButton = require("graphics.elements.controls.hazard_button")
-local MultiButton = require("graphics.elements.controls.multi_button")
-local PushButton = require("graphics.elements.controls.push_button")
-local RadioButton = require("graphics.elements.controls.radio_button")
-local SpinboxNumeric = require("graphics.elements.controls.spinbox_numeric")
+local HazardButton = require("graphics.elements.controls.HazardButton")
+local MultiButton = require("graphics.elements.controls.MultiButton")
+local NumericSpinbox = require("graphics.elements.controls.NumericSpinbox")
+local PushButton = require("graphics.elements.controls.PushButton")
+local RadioButton = require("graphics.elements.controls.RadioButton")
local AUTO_GROUP = types.AUTO_GROUP
@@ -42,7 +42,7 @@ local gry_wht = style.gray_white
local period = core.flasher.PERIOD
-- create a unit view
----@param parent graphics_element parent
+---@param parent Container parent
---@param id integer
local function init(parent, id)
local s_hi_box = style.theme.highlight_box
@@ -62,7 +62,7 @@ local function init(parent, id)
local ind_wht = style.ind_wht
local db = iocontrol.get_db()
- local unit = db.units[id] ---@type ioctl_unit
+ local unit = db.units[id]
local f_ps = db.facility.ps
local main = Div{parent=parent,x=1,y=1}
@@ -361,7 +361,7 @@ local function init(parent, id)
----------------------
local burn_control = Div{parent=main,x=12,y=28,width=19,height=3,fg_bg=s_hi_box}
- local burn_rate = SpinboxNumeric{parent=burn_control,x=2,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=arrow_fg_bg,arrow_disable=style.theme.disabled}
+ local burn_rate = NumericSpinbox{parent=burn_control,x=2,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=arrow_fg_bg,arrow_disable=style.theme.disabled}
TextBox{parent=burn_control,x=9,y=2,text="mB/t",fg_bg=style.theme.label_fg}
local set_burn = function () unit.set_burn(burn_rate.get_value()) end
diff --git a/coordinator/ui/components/unit_flow.lua b/coordinator/ui/components/unit_flow.lua
index 9ba29be..27e4d0d 100644
--- a/coordinator/ui/components/unit_flow.lua
+++ b/coordinator/ui/components/unit_flow.lua
@@ -8,16 +8,16 @@ local style = require("coordinator.ui.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local PipeNetwork = require("graphics.elements.pipenet")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local PipeNetwork = require("graphics.elements.PipeNetwork")
+local TextBox = require("graphics.elements.TextBox")
-local Rectangle = require("graphics.elements.rectangle")
+local Rectangle = require("graphics.elements.Rectangle")
-local DataIndicator = require("graphics.elements.indicators.data")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
-local IndicatorLight = require("graphics.elements.indicators.light")
-local TriIndicatorLight = require("graphics.elements.indicators.trilight")
+local IndicatorLight = require("graphics.elements.indicators.IndicatorLight")
+local TriIndicatorLight = require("graphics.elements.indicators.TriIndicatorLight")
local ALIGN = core.ALIGN
@@ -31,7 +31,7 @@ local wh_gray = style.wh_gray
local lg_gray = style.lg_gray
-- make a new unit flow window
----@param parent graphics_element parent
+---@param parent Container parent
---@param x integer top left x
---@param y integer top left y
---@param wide boolean whether to render wide version
diff --git a/coordinator/ui/components/unit_overview.lua b/coordinator/ui/components/unit_overview.lua
index fc4ac4e..a3f41c1 100644
--- a/coordinator/ui/components/unit_overview.lua
+++ b/coordinator/ui/components/unit_overview.lua
@@ -10,16 +10,16 @@ local reactor_view = require("coordinator.ui.components.reactor")
local boiler_view = require("coordinator.ui.components.boiler")
local turbine_view = require("coordinator.ui.components.turbine")
-local Div = require("graphics.elements.div")
-local PipeNetwork = require("graphics.elements.pipenet")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local PipeNetwork = require("graphics.elements.PipeNetwork")
+local TextBox = require("graphics.elements.TextBox")
local ALIGN = core.ALIGN
local pipe = core.pipe
-- make a new unit overview window
----@param parent graphics_element parent
+---@param parent Container parent
---@param x integer top left x
---@param y integer top left y
---@param unit ioctl_unit unit database entry
diff --git a/coordinator/ui/layout/flow_view.lua b/coordinator/ui/layout/flow_view.lua
index 7a7f57d..b002f24 100644
--- a/coordinator/ui/layout/flow_view.lua
+++ b/coordinator/ui/layout/flow_view.lua
@@ -13,15 +13,15 @@ local unit_flow = require("coordinator.ui.components.unit_flow")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local PipeNetwork = require("graphics.elements.pipenet")
-local Rectangle = require("graphics.elements.rectangle")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local PipeNetwork = require("graphics.elements.PipeNetwork")
+local Rectangle = require("graphics.elements.Rectangle")
+local TextBox = require("graphics.elements.TextBox")
-local DataIndicator = require("graphics.elements.indicators.data")
-local HorizontalBar = require("graphics.elements.indicators.hbar")
-local IndicatorLight = require("graphics.elements.indicators.light")
-local StateIndicator = require("graphics.elements.indicators.state")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
+local HorizontalBar = require("graphics.elements.indicators.HorizontalBar")
+local IndicatorLight = require("graphics.elements.indicators.IndicatorLight")
+local StateIndicator = require("graphics.elements.indicators.StateIndicator")
local CONTAINER_MODE = types.CONTAINER_MODE
@@ -34,7 +34,7 @@ local pipe = core.pipe
local wh_gray = style.wh_gray
-- create new flow view
----@param main graphics_element main displaybox
+---@param main DisplayBox main displaybox
local function init(main)
local s_hi_bright = style.theme.highlight_box_bright
local s_field = style.theme.field_box
@@ -84,8 +84,7 @@ local function init(main)
table.insert(water_pipes, pipe(2, y, 2, y + 3, colors.blue, true))
table.insert(water_pipes, pipe(2, y, 21, y, colors.blue, true))
- local u = units[i] ---@type ioctl_unit
- local x = util.trinary(u.num_boilers == 0, 45, 84)
+ local x = util.trinary(units[i].num_boilers == 0, 45, 84)
table.insert(water_pipes, pipe(21, y, x, y + 2, colors.blue, true, true))
end
end
@@ -102,8 +101,7 @@ local function init(main)
table.insert(water_pipes, pipe(2, y, 21, y, colors.blue, true))
end
- local u = units[i] ---@type ioctl_unit
- local x = util.trinary(u.num_boilers == 0, 45, 84)
+ local x = util.trinary(units[i].num_boilers == 0, 45, 84)
table.insert(water_pipes, pipe(21, y, x, y + 2, colors.blue, true, true))
end
end
diff --git a/coordinator/ui/layout/front_panel.lua b/coordinator/ui/layout/front_panel.lua
index 3573fb2..11ae58f 100644
--- a/coordinator/ui/layout/front_panel.lua
+++ b/coordinator/ui/layout/front_panel.lua
@@ -14,16 +14,16 @@ local pkt_entry = require("coordinator.ui.components.pkt_entry")
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 Div = require("graphics.elements.Div")
+local ListBox = require("graphics.elements.ListBox")
+local MultiPane = require("graphics.elements.MultiPane")
+local TextBox = require("graphics.elements.TextBox")
-local TabBar = require("graphics.elements.controls.tabbar")
+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.RGBLED")
local LINK_STATE = types.PANEL_LINK_STATE
@@ -34,7 +34,7 @@ local cpair = core.cpair
local led_grn = style.led_grn
-- create new front panel view
----@param panel graphics_element main displaybox
+---@param panel DisplayBox main displaybox
---@param num_units integer number of units (number of unit monitors)
local function init(panel, num_units)
local ps = iocontrol.get_db().fp.ps
diff --git a/coordinator/ui/layout/main_view.lua b/coordinator/ui/layout/main_view.lua
index 33ed43c..ebc9cc3 100644
--- a/coordinator/ui/layout/main_view.lua
+++ b/coordinator/ui/layout/main_view.lua
@@ -14,14 +14,14 @@ local unit_overview = require("coordinator.ui.components.unit_overview")
local core = require("graphics.core")
-local TextBox = require("graphics.elements.textbox")
+local TextBox = require("graphics.elements.TextBox")
-local DataIndicator = require("graphics.elements.indicators.data")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
local ALIGN = core.ALIGN
-- create new main view
----@param main graphics_element main displaybox
+---@param main DisplayBox main displaybox
local function init(main)
local s_header = style.theme.header
@@ -37,7 +37,8 @@ local function init(main)
ping.register(facility.ps, "sv_ping", ping.update)
datetime.register(facility.ps, "date_time", datetime.set_value)
- local uo_1, uo_2, uo_3, uo_4 ---@type graphics_element
+ ---@type Div, Div, Div, Div
+ local uo_1, uo_2, uo_3, uo_4
local cnc_y_start = 3
local row_1_height = 0
diff --git a/coordinator/ui/layout/unit_view.lua b/coordinator/ui/layout/unit_view.lua
index 7ac1b7c..7a8ec26 100644
--- a/coordinator/ui/layout/unit_view.lua
+++ b/coordinator/ui/layout/unit_view.lua
@@ -5,7 +5,7 @@
local unit_detail = require("coordinator.ui.components.unit_detail")
-- create a unit view
----@param main graphics_element main displaybox
+---@param main DisplayBox main displaybox
---@param id integer
local function init(main, id)
unit_detail(main, id)
diff --git a/coordinator/ui/pgi.lua b/coordinator/ui/pgi.lua
index b603465..70ca0b8 100644
--- a/coordinator/ui/pgi.lua
+++ b/coordinator/ui/pgi.lua
@@ -8,15 +8,17 @@ local util = require("scada-common.util")
local pgi = {}
local data = {
- pkt_list = nil, ---@type nil|graphics_element
- pkt_entry = nil, ---@type function
+ pkt_list = nil, ---@type ListBox|nil
+ pkt_entry = nil, ---@type function
-- session entries
- s_entries = { pkt = {} }
+ s_entries = {
+ pkt = {} ---@type Div[]
+ }
}
-- link list boxes
----@param pkt_list graphics_element pocket list element
----@param pkt_entry function pocket entry constructor
+---@param pkt_list ListBox pocket list element
+---@param pkt_entry fun(parent: ListBox, id: integer) : Div pocket entry constructor
function pgi.link_elements(pkt_list, pkt_entry)
data.pkt_list = pkt_list
data.pkt_entry = pkt_entry
diff --git a/graphics/core.lua b/graphics/core.lua
index fe3b291..4b8e13c 100644
--- a/graphics/core.lua
+++ b/graphics/core.lua
@@ -7,7 +7,7 @@ local flasher = require("graphics.flasher")
local core = {}
-core.version = "2.3.4"
+core.version = "2.4.0"
core.flasher = flasher
core.events = events
@@ -17,6 +17,8 @@ core.events = events
---@enum ALIGN
core.ALIGN = { LEFT = 1, CENTER = 2, RIGHT = 3 }
+---@alias Container DisplayBox|Div|ListBox|MultiPane|AppMultiPane|Rectangle
+
---@class graphics_border
---@field width integer
---@field color color
@@ -124,10 +126,10 @@ end
-- Interactive Field Manager
---@param e graphics_base element
----@param max_len any max value length
----@param fg_bg any enabled fg/bg
----@param dis_fg_bg any disabled fg/bg
----@param align_right any true to align content right while unfocused
+---@param max_len integer max value length
+---@param fg_bg cpair enabled fg/bg
+---@param dis_fg_bg? cpair disabled fg/bg
+---@param align_right? boolean true to align content right while unfocused
function core.new_ifield(e, max_len, fg_bg, dis_fg_bg, align_right)
local self = {
frame_start = 1,
diff --git a/graphics/element.lua b/graphics/element.lua
index 1e94edd..0d6800a 100644
--- a/graphics/element.lua
+++ b/graphics/element.lua
@@ -11,8 +11,8 @@ local events = core.events
local element = {}
----@class graphics_args_generic
----@field window? table
+---@class graphics_args
+---@field window? Window
---@field parent? graphics_element
---@field id? string element id
---@field x? integer 1 if omitted
@@ -24,47 +24,6 @@ local element = {}
---@field hidden? boolean true to hide on initial draw
---@field can_focus? boolean true if this element can be focused, false by default
----@alias graphics_args graphics_args_generic
----|waiting_args
----|app_button_args
----|checkbox_args
----|hazard_button_args
----|multi_button_args
----|push_button_args
----|radio_2d_args
----|radio_button_args
----|sidebar_args
----|spinbox_args
----|switch_button_args
----|tabbar_args
----|number_field_args
----|text_field_args
----|alarm_indicator_light
----|core_map_args
----|data_indicator_args
----|hbar_args
----|icon_indicator_args
----|indicator_led_args
----|indicator_led_pair_args
----|indicator_led_rgb_args
----|indicator_light_args
----|power_indicator_args
----|rad_indicator_args
----|signal_bar_args
----|state_indicator_args
----|tristate_indicator_light_args
----|vbar_args
----|app_multipane_args
----|colormap_args
----|displaybox_args
----|div_args
----|listbox_args
----|multipane_args
----|pipenet_args
----|rectangle_args
----|textbox_args
----|tiling_args
-
---@class element_subscription
---@field ps psil ps used
---@field key string data key
@@ -92,14 +51,14 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
is_root = args.parent == nil,
elem_type = debug.getinfo(2).name,
define_completed = false,
- p_window = nil, ---@type table
+ p_window = nil, ---@type Window
position = events.new_coord_2d(1, 1),
bounds = { x1 = 1, y1 = 1, x2 = 1, y2 = 1 }, ---@class element_bounds
offset_x = 0,
offset_y = 0,
next_y = 1, -- next child y coordinate
next_id = 0, -- next child ID
- subscriptions = {},
+ subscriptions = {}, ---@type { ps: psil, key: string, func: function }[]
button_down = { events.new_coord_2d(-1, -1), events.new_coord_2d(-1, -1), events.new_coord_2d(-1, -1) },
focused = false,
mt = {}
@@ -109,13 +68,13 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
local protected = {
enabled = true,
value = nil, ---@type any
- window = nil, ---@type table
- content_window = nil, ---@type table|nil
+ window = nil, ---@type Window
+ content_window = nil, ---@type Window|nil
mouse_window_shift = { x = 0, y = 0 },
fg_bg = core.cpair(colors.white, colors.black),
frame = core.gframe(1, 1, 1, 1),
- children = {},
- child_id_map = {}
+ children = {}, ---@type graphics_base[]
+ child_id_map = {} ---@type { [element_id]: integer }
}
-- element as string
@@ -128,9 +87,9 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
setmetatable(public, self.mt)
- -----------------------
- -- PRIVATE FUNCTIONS --
- -----------------------
+ ------------------------------
+ --#region PRIVATE FUNCTIONS --
+ ------------------------------
-- use tab to jump to the next focusable field
---@param reverse boolean
@@ -168,10 +127,10 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
end
- ---@param children table
+ ---@param children graphics_base[]
local function traverse(children)
for i = 1, #children do
- local child = children[i] ---@type graphics_base
+ local child = children[i]
handle_element(child.get())
if child.get().is_visible() then traverse(child.children) end
end
@@ -191,9 +150,11 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
end
- -------------------------
- -- PROTECTED FUNCTIONS --
- -------------------------
+ --#endregion
+
+ --------------------------------
+ --#region PROTECTED FUNCTIONS --
+ --------------------------------
-- prepare the template
---@param offset_x integer x offset for mouse events
@@ -286,24 +247,29 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- alias functions
- -- window set cursor position
+ -- window set cursor position
+ ---@see Window.setCursorPos
---@param x integer
---@param y integer
function protected.w_set_cur(x, y) protected.window.setCursorPos(x, y) end
- -- set background color
+ -- set background color
+ ---@see Window.setBackgroundColor
---@param c color
function protected.w_set_bkg(c) protected.window.setBackgroundColor(c) end
- -- set foreground (text) color
+ -- set foreground (text) color
+ ---@see Window.setTextColor
---@param c color
function protected.w_set_fgd(c) protected.window.setTextColor(c) end
- -- write text
+ -- write text
+ ---@see Window.write
---@param str string
function protected.w_write(str) protected.window.write(str) end
- -- blit text
+ -- blit text
+ ---@see Window.blit
---@param str string
---@param fg string
---@param bg string
@@ -335,8 +301,10 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- report completion of element instantiation and get the public interface
---@nodiscard
+ ---@param redraw? boolean true to call redraw as part of completing this element
---@return graphics_element element, element_id id
- function protected.complete()
+ function protected.complete(redraw)
+ if redraw then protected.redraw() end
if args.parent ~= nil then args.parent.__child_ready(self.id, public) end
return public, self.id
end
@@ -352,7 +320,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- focus this element and take away focus from all other elements
function protected.take_focus() args.parent.__focus_child(public) end
- -- action handlers --
+ --#region Action Handlers
-- luacheck: push ignore
---@diagnostic disable: unused-local, unused-vararg
@@ -401,14 +369,12 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
function protected.handle_paste(text) end
-- handle data value changes
- ---@vararg any value(s)
+ ---@param ... any value(s)
function protected.on_update(...) end
- -- callback on control press responses
- ---@param result any
- function protected.response_callback(result) end
+ --#endregion
- -- accessors and control --
+ --#region Accessors and Control
-- get value
---@nodiscard
@@ -427,11 +393,11 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
function protected.set_max(max) end
-- custom recolor command, varies by element if implemented
- ---@vararg cpair|color color(s)
+ ---@param ... cpair|color color(s)
function protected.recolor(...) end
-- custom resize command, varies by element if implemented
- ---@vararg integer sizing
+ ---@param ... integer sizing
function protected.resize(...) end
-- luacheck: pop
@@ -446,9 +412,13 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- stop animations
function protected.stop_anim() end
- -----------
- -- SETUP --
- -----------
+ --#endregion
+
+ --#endregion
+
+ ------------------
+ --#region SETUP --
+ ------------------
-- get the parent window
self.p_window = args.window
@@ -467,9 +437,11 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
self.id = args.parent.__add_child(args.id, protected)
end
- ----------------------
- -- PUBLIC FUNCTIONS --
- ----------------------
+ --#endregion
+
+ -----------------------------
+ --#region PUBLIC FUNCTIONS --
+ -----------------------------
-- get the window object
---@nodiscard
@@ -511,9 +483,10 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
end
- -- ELEMENT TREE --
+ --#region ELEMENT TREE
-- add a child element
+ ---@package
---@nodiscard
---@param key string|nil id
---@param child graphics_base
@@ -523,7 +496,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
self.next_y = child.frame.y + child.frame.h
- local id = key ---@type string|integer|nil
+ local id = key ---@type element_id|nil
if id == nil then
id = self.next_id
self.next_id = self.next_id + 1
@@ -537,6 +510,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
-- remove a child element
+ ---@package
---@param id element_id id
function public.__remove_child(id)
local index = protected.child_id_map[id]
@@ -548,11 +522,13 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
-- actions to take upon a child element becoming ready (initial draw/construction completed)
+ ---@package
---@param key element_id id
---@param child graphics_element
function public.__child_ready(key, child) protected.on_added(key, child) end
-- focus solely on this child
+ ---@package
---@param child graphics_element
function public.__focus_child(child)
if self.is_root then
@@ -562,6 +538,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
-- a child was focused, used to make sure it is actually visible to the user in the content frame
+ ---@package
---@param child graphics_element
function public.__child_focused(child)
protected.on_child_focused(child)
@@ -571,8 +548,8 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- get a child element
---@nodiscard
---@param id element_id
- ---@return graphics_element
- function public.get_child(id) return protected.children[protected.child_id_map[id]].get() end
+ ---@return graphics_element element
+ function public.get_child(id) return ({ protected.children[protected.child_id_map[id]].get() })[1] end
-- get all children
---@nodiscard
@@ -598,7 +575,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- remove all child elements and reset next y
function public.remove_all()
for i = 1, #protected.children do
- local child = protected.children[i].get() ---@type graphics_element
+ local child = protected.children[i].get() ---@type graphics_element
child.delete()
protected.on_removed(child.get_id())
end
@@ -619,29 +596,33 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
local elem = child.get().get_element_by_id(id)
if elem ~= nil then return elem end
end
- else return protected.children[index].get() end
+ else return ({ protected.children[index].get() })[1] end
end
- -- AUTO-PLACEMENT --
+ --#endregion
+
+ --#region AUTO-PLACEMENT
-- skip a line for automatically placed elements
function public.line_break()
self.next_y = self.next_y + 1
end
- -- PROPERTIES --
+ --#endregion
- -- get element id
+ --#region PROPERTIES
+
+ -- get element ID
---@nodiscard
---@return element_id
function public.get_id() return self.id end
- -- get element x
+ -- get element relative x position
---@nodiscard
---@return integer x
function public.get_x() return protected.frame.x end
- -- get element y
+ -- get element relative y position
---@nodiscard
---@return integer y
function public.get_y() return protected.frame.y end
@@ -661,12 +642,12 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
---@return cpair fg_bg
function public.get_fg_bg() return protected.fg_bg end
- -- get the element value
+ -- get the element's value
---@nodiscard
---@return any value
function public.get_value() return protected.get_value() end
- -- set the element value
+ -- set the element's value
---@param value any new value
function public.set_value(value) protected.set_value(value) end
@@ -728,11 +709,11 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
-- custom recolor command, varies by element if implemented
- ---@vararg cpair|color color(s)
+ ---@param ... cpair|color color(s)
function public.recolor(...) protected.recolor(...) end
-- resize attributes of the element value if supported
- ---@vararg number dimensions (element specific)
+ ---@param ... number dimensions (element specific)
function public.resize(...) protected.resize(...) end
-- reposition the element window
@@ -756,7 +737,9 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
self.bounds.y2 = self.position.y + protected.frame.h - 1
end
- -- FUNCTION CALLBACKS --
+ --#endregion
+
+ --#region FUNCTION CALLBACKS
-- handle a monitor touch or mouse click if this element is visible
---@param event mouse_interaction mouse interaction event
@@ -818,13 +801,9 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
-- draw the element given new data
- ---@vararg any new data
+ ---@param ... any new data
function public.update(...) protected.on_update(...) end
- -- on a control request response
- ---@param result any
- function public.on_response(result) protected.response_callback(result) end
-
-- register a callback with a PSIL, allowing for automatic unregister on delete
-- do not use graphics elements directly with PSIL subscribe()
---@param ps psil PSIL to subscribe to
@@ -835,7 +814,9 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
ps.subscribe(key, func)
end
- -- VISIBILITY & ANIMATIONS --
+ --#endregion
+
+ --#region VISIBILITY & ANIMATIONS
-- check if this element is visible
function public.is_visible() return protected.window.isVisible() end
@@ -849,6 +830,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- 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 Window.redraw
---@see graphics_element.redraw
---@see graphics_element.content_redraw
---@param clear? boolean true to visibly hide this element (redraws the parent)
@@ -900,6 +882,10 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
end
+ --#endregion
+
+ --#endregion
+
return protected
end
diff --git a/graphics/elements/appmultipane.lua b/graphics/elements/AppMultiPane.lua
similarity index 92%
rename from graphics/elements/appmultipane.lua
rename to graphics/elements/AppMultiPane.lua
index 5973182..948cb32 100644
--- a/graphics/elements/appmultipane.lua
+++ b/graphics/elements/AppMultiPane.lua
@@ -24,15 +24,15 @@ local MOUSE_CLICK = core.events.MOUSE_CLICK
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new app multipane element
+-- Create a new app multipane container element.
---@nodiscard
---@param args app_multipane_args
----@return graphics_element element, element_id id
-local function multipane(args)
+---@return AppMultiPane element, element_id id
+return function (args)
element.assert(type(args.panes) == "table", "panes is a required field")
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = 1
@@ -100,10 +100,8 @@ local function multipane(args)
end
end
- -- initial draw
- e.redraw()
+ ---@class AppMultiPane:graphics_element
+ local AppMultiPane, id = e.complete(true)
- return e.complete()
+ return AppMultiPane, id
end
-
-return multipane
diff --git a/graphics/elements/colormap.lua b/graphics/elements/ColorMap.lua
similarity index 66%
rename from graphics/elements/colormap.lua
rename to graphics/elements/ColorMap.lua
index 7e3554f..1a4b0a7 100644
--- a/graphics/elements/colormap.lua
+++ b/graphics/elements/ColorMap.lua
@@ -9,10 +9,10 @@ local element = require("graphics.element")
---@field y? integer auto incremented if omitted
---@field hidden? boolean true to hide on initial draw
--- new color map
+-- Create a horizontal reference color map. Primarily used for tuning custom colors.
---@param args colormap_args
----@return graphics_element element, element_id id
-local function colormap(args)
+---@return ColorMap element, element_id id
+return function (args)
local bkg = "008877FFCCEE114455DD9933BBAA2266"
local spaces = string.rep(" ", 32)
@@ -20,7 +20,7 @@ local function colormap(args)
args.height = 1
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- draw color map
function e.redraw()
@@ -28,10 +28,8 @@ local function colormap(args)
e.w_blit(spaces, bkg, bkg)
end
- -- initial draw
- e.redraw()
+ ---@class ColorMap:graphics_element
+ local ColorMap, id = e.complete(true)
- return e.complete()
+ return ColorMap, id
end
-
-return colormap
diff --git a/graphics/elements/displaybox.lua b/graphics/elements/DisplayBox.lua
similarity index 69%
rename from graphics/elements/displaybox.lua
rename to graphics/elements/DisplayBox.lua
index 3578a63..ecfe03a 100644
--- a/graphics/elements/displaybox.lua
+++ b/graphics/elements/DisplayBox.lua
@@ -13,13 +13,16 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new root display box
+-- Create a root display box.
---@nodiscard
---@param args displaybox_args
----@return graphics_element element, element_id id
-local function displaybox(args)
+---@return DisplayBox element, element_id id
+return function (args)
-- create new graphics element base object
- return element.new(args).complete()
-end
+ local e = element.new(args --[[@as graphics_args]])
-return displaybox
+ ---@class DisplayBox:graphics_element
+ local DisplayBox, id = e.complete()
+
+ return DisplayBox, id
+end
diff --git a/graphics/elements/div.lua b/graphics/elements/Div.lua
similarity index 72%
rename from graphics/elements/div.lua
rename to graphics/elements/Div.lua
index 0af3259..2be440b 100644
--- a/graphics/elements/div.lua
+++ b/graphics/elements/Div.lua
@@ -13,13 +13,16 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new div element
+-- Create a new div container element.
---@nodiscard
---@param args div_args
----@return graphics_element element, element_id id
-local function div(args)
+---@return Div element, element_id id
+return function (args)
-- create new graphics element base object
- return element.new(args).complete()
-end
+ local e = element.new(args --[[@as graphics_args]])
-return div
+ ---@class Div:graphics_element
+ local Div, id = e.complete()
+
+ return Div, id
+end
diff --git a/graphics/elements/listbox.lua b/graphics/elements/ListBox.lua
similarity index 97%
rename from graphics/elements/listbox.lua
rename to graphics/elements/ListBox.lua
index 86cacd4..e1c8dec 100644
--- a/graphics/elements/listbox.lua
+++ b/graphics/elements/ListBox.lua
@@ -30,15 +30,15 @@ local MOUSE_CLICK = core.events.MOUSE_CLICK
---@field y integer y position
---@field h integer element height
--- new listbox element
+-- Create a new scrollable listbox container element.
---@nodiscard
---@param args listbox_args
----@return graphics_element element, element_id id
-local function listbox(args)
+---@return ListBox element, element_id id
+return function (args)
args.can_focus = true
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- create content window for child elements
local scroll_frame = window.create(e.window, 1, 1, e.frame.w - 1, args.scroll_height, false)
@@ -339,10 +339,8 @@ local function listbox(args)
draw_bar()
end
- -- initial draw
- e.redraw()
+ ---@class ListBox:graphics_element
+ local ListBox, id = e.complete(true)
- return e.complete()
+ return ListBox, id
end
-
-return listbox
diff --git a/graphics/elements/multipane.lua b/graphics/elements/MultiPane.lua
similarity index 81%
rename from graphics/elements/multipane.lua
rename to graphics/elements/MultiPane.lua
index a283ed8..aae22ac 100644
--- a/graphics/elements/multipane.lua
+++ b/graphics/elements/MultiPane.lua
@@ -14,15 +14,15 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new multipane element
+-- Create a new multipane container element.
---@nodiscard
---@param args multipane_args
----@return graphics_element element, element_id id
-local function multipane(args)
+---@return MultiPane element, element_id id
+return function (args)
element.assert(type(args.panes) == "table", "panes is a required field")
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = 1
@@ -41,10 +41,8 @@ local function multipane(args)
end
end
- -- initial draw
- e.redraw()
+ ---@class MultiPane:graphics_element
+ local MultiPane, id = e.complete(true)
- return e.complete()
+ return MultiPane, id
end
-
-return multipane
diff --git a/graphics/elements/pipenet.lua b/graphics/elements/PipeNetwork.lua
similarity index 97%
rename from graphics/elements/pipenet.lua
rename to graphics/elements/PipeNetwork.lua
index 625a70d..7045bd0 100644
--- a/graphics/elements/pipenet.lua
+++ b/graphics/elements/PipeNetwork.lua
@@ -20,10 +20,10 @@ local element = require("graphics.element")
---@field fg string foreground blit
---@field bg string background blit
--- new pipe network
+-- Create a pipe network diagram.
---@param args pipenet_args
----@return graphics_element element, element_id id
-local function pipenet(args)
+---@return PipeNetwork element, element_id id
+return function (args)
element.assert(type(args.pipes) == "table", "pipes is a required field")
args.width = 0
@@ -47,7 +47,7 @@ local function pipenet(args)
end
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- determine if there are any thin pipes involved
local any_thin = false
@@ -322,10 +322,8 @@ local function pipenet(args)
if any_thin then map_draw() else vector_draw() end
end
- -- initial draw
- e.redraw()
+ ---@class PipeNetwork:graphics_element
+ local PipeNetwork, id = e.complete(true)
- return e.complete()
+ return PipeNetwork, id
end
-
-return pipenet
diff --git a/graphics/elements/rectangle.lua b/graphics/elements/Rectangle.lua
similarity index 96%
rename from graphics/elements/rectangle.lua
rename to graphics/elements/Rectangle.lua
index eceb9bd..ce5fbba 100644
--- a/graphics/elements/rectangle.lua
+++ b/graphics/elements/Rectangle.lua
@@ -18,10 +18,10 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new rectangle
+-- Create a new rectangle container element.
---@param args rectangle_args
----@return graphics_element element, element_id id
-local function rectangle(args)
+---@return Rectangle element, element_id id
+return function (args)
element.assert(args.border ~= nil or args.thin ~= true, "thin requires border to be provided")
-- if thin, then width will always need to be 1
@@ -45,7 +45,7 @@ local function rectangle(args)
end
-- create new graphics element base object
- local e = element.new(args, nil, offset_x, offset_y)
+ local e = element.new(args --[[@as graphics_args]], nil, offset_x, offset_y)
-- 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))
@@ -191,7 +191,8 @@ local function rectangle(args)
e.redraw()
end
- return e.complete()
-end
+ ---@class Rectangle:graphics_element
+ local Rectangle, id = e.complete()
-return rectangle
+ return Rectangle, id
+end
diff --git a/graphics/elements/textbox.lua b/graphics/elements/TextBox.lua
similarity index 89%
rename from graphics/elements/textbox.lua
rename to graphics/elements/TextBox.lua
index a52d528..cc3c4aa 100644
--- a/graphics/elements/textbox.lua
+++ b/graphics/elements/TextBox.lua
@@ -21,10 +21,10 @@ local ALIGN = core.ALIGN
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new text box
+-- Create a new text box element.
---@param args textbox_args
----@return graphics_element element, element_id id
-local function textbox(args)
+---@return TextBox element, element_id id
+return function (args)
element.assert(type(args.text) == "string", "text is a required field")
if args.anchor == true then args.can_focus = true end
@@ -42,7 +42,7 @@ local function textbox(args)
end
-- create new graphics element base object
- local e = element.new(args, constrain)
+ local e = element.new(args --[[@as graphics_args]], constrain)
e.value = args.text
@@ -82,10 +82,8 @@ local function textbox(args)
e.redraw()
end
- -- initial draw
- e.redraw()
+ ---@class TextBox:graphics_element
+ local TextBox, id = e.complete(true)
- return e.complete()
+ return TextBox, id
end
-
-return textbox
diff --git a/graphics/elements/tiling.lua b/graphics/elements/Tiling.lua
similarity index 90%
rename from graphics/elements/tiling.lua
rename to graphics/elements/Tiling.lua
index 02e2605..d4b48d2 100644
--- a/graphics/elements/tiling.lua
+++ b/graphics/elements/Tiling.lua
@@ -18,14 +18,14 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new tiling box
+-- Create a new tiling box element.
---@param args tiling_args
----@return graphics_element element, element_id id
-local function tiling(args)
+---@return Tiling element, element_id id
+return function (args)
element.assert(type(args.fill_c) == "table", "fill_c is a required field")
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
local fill_a = args.fill_c.blit_a
local fill_b = args.fill_c.blit_b
@@ -52,7 +52,7 @@ local function tiling(args)
element.assert(start_x <= inner_width, "start_x > inner_width")
element.assert(start_y <= inner_height, "start_y > inner_height")
- -- draw tiling box
+ -- draw the tiling box
function e.redraw()
local alternator = true
@@ -86,10 +86,8 @@ local function tiling(args)
end
end
- -- initial draw
- e.redraw()
+ ---@class Tiling:graphics_element
+ local Tiling, id = e.complete(true)
- return e.complete()
+ return Tiling, id
end
-
-return tiling
diff --git a/graphics/elements/animations/waiting.lua b/graphics/elements/animations/Waiting.lua
similarity index 91%
rename from graphics/elements/animations/waiting.lua
rename to graphics/elements/animations/Waiting.lua
index 36aa432..0456ef3 100644
--- a/graphics/elements/animations/waiting.lua
+++ b/graphics/elements/animations/Waiting.lua
@@ -12,10 +12,10 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new waiting animation element
+-- Create a new waiting animation element.
---@param args waiting_args
----@return graphics_element element, element_id id
-local function waiting(args)
+---@return Waiting element, element_id id
+return function (args)
local state = 0
local run_animation = false
@@ -23,7 +23,7 @@ local function waiting(args)
args.height = 3
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
local blit_fg = e.fg_bg.blit_fgd
local blit_bg = e.fg_bg.blit_bkg
@@ -103,7 +103,8 @@ local function waiting(args)
e.start_anim()
- return e.complete()
-end
+ ---@class Waiting:graphics_element
+ local Waiting, id = e.complete()
-return waiting
+ return Waiting, id
+end
diff --git a/graphics/elements/controls/app.lua b/graphics/elements/controls/App.lua
similarity index 92%
rename from graphics/elements/controls/app.lua
rename to graphics/elements/controls/App.lua
index 4ac936d..2d6ca01 100644
--- a/graphics/elements/controls/app.lua
+++ b/graphics/elements/controls/App.lua
@@ -20,10 +20,10 @@ local MOUSE_CLICK = core.events.MOUSE_CLICK
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new app button
+-- Create a new app icon style button control element, like on a mobile device.
---@param args app_button_args
----@return graphics_element element, element_id id
-local function app_button(args)
+---@return App element, element_id id
+return function (args)
element.assert(type(args.text) == "string", "text is a required field")
element.assert(type(args.title) == "string", "title is a required field")
element.assert(type(args.callback) == "function", "callback is a required field")
@@ -33,7 +33,7 @@ local function app_button(args)
args.width = 7
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- draw the app button
local function draw()
@@ -123,10 +123,8 @@ local function app_button(args)
draw()
end
- -- initial draw
- e.redraw()
+ ---@class App:graphics_element
+ local App, id = e.complete(true)
- return e.complete()
+ return App, id
end
-
-return app_button
diff --git a/graphics/elements/controls/checkbox.lua b/graphics/elements/controls/Checkbox.lua
similarity index 92%
rename from graphics/elements/controls/checkbox.lua
rename to graphics/elements/controls/Checkbox.lua
index d63ca69..26d4faf 100644
--- a/graphics/elements/controls/checkbox.lua
+++ b/graphics/elements/controls/Checkbox.lua
@@ -15,10 +15,10 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new checkbox control
+-- Create a new checkbox control element.
---@param args checkbox_args
----@return graphics_element element, element_id id
-local function checkbox(args)
+---@return Checkbox element, element_id id
+return function (args)
element.assert(type(args.label) == "string", "label is a required field")
element.assert(type(args.box_fg_bg) == "table", "box_fg_bg is a required field")
@@ -27,7 +27,7 @@ local function checkbox(args)
args.width = 2 + string.len(args.label)
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = args.default == true
@@ -112,10 +112,8 @@ local function checkbox(args)
draw_label()
end
- -- initial draw
- e.redraw()
+ ---@class Checkbox:graphics_element
+ local Checkbox, id = e.complete(true)
- return e.complete()
+ return Checkbox, id
end
-
-return checkbox
diff --git a/graphics/elements/controls/hazard_button.lua b/graphics/elements/controls/HazardButton.lua
similarity index 92%
rename from graphics/elements/controls/hazard_button.lua
rename to graphics/elements/controls/HazardButton.lua
index 5a3d37f..7815ba3 100644
--- a/graphics/elements/controls/hazard_button.lua
+++ b/graphics/elements/controls/HazardButton.lua
@@ -18,10 +18,10 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new hazard button
+-- Create a new hazard button control element.
---@param args hazard_button_args
----@return graphics_element element, element_id id
-local function hazard_button(args)
+---@return HazardButton element, element_id id
+return function (args)
element.assert(type(args.text) == "string", "text is a required field")
element.assert(type(args.accent) == "number", "accent is a required field")
element.assert(type(args.callback) == "function", "callback is a required field")
@@ -32,7 +32,7 @@ local function hazard_button(args)
local timeout = args.timeout or 1.5
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- draw border
---@param accent color accent color
@@ -159,13 +159,6 @@ local function hazard_button(args)
end
end
- -- callback on request response
- ---@param result boolean true for success, false for failure
- function e.response_callback(result)
- tcd.abort(on_timeout)
- if result then on_success() else on_failure(0) end
- end
-
-- set the value (true simulates pressing the button)
---@param val boolean new value
function e.set_value(val)
@@ -198,10 +191,15 @@ local function hazard_button(args)
draw_border(args.accent)
end
- -- initial draw
- e.redraw()
+ ---@class HazardButton:graphics_element
+ local HazardButton, id = e.complete(true)
- return e.complete()
+ -- callback for request response
+ ---@param success boolean
+ function HazardButton.on_response(success)
+ tcd.abort(on_timeout)
+ if success then on_success() else on_failure(0) end
+ end
+
+ return HazardButton, id
end
-
-return hazard_button
diff --git a/graphics/elements/controls/multi_button.lua b/graphics/elements/controls/MultiButton.lua
similarity index 92%
rename from graphics/elements/controls/multi_button.lua
rename to graphics/elements/controls/MultiButton.lua
index d686b9d..4e44ebe 100644
--- a/graphics/elements/controls/multi_button.lua
+++ b/graphics/elements/controls/MultiButton.lua
@@ -25,10 +25,10 @@ local element = require("graphics.element")
---@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)
+-- Create a new multi button control element (latch selection, exclusively one button at a time).
---@param args multi_button_args
----@return graphics_element element, element_id id
-local function multi_button(args)
+---@return MultiButton element, element_id id
+return function (args)
element.assert(type(args.options) == "table", "options is a required field")
element.assert(#args.options > 0, "at least one option is required")
element.assert(type(args.callback) == "function", "callback is a required field")
@@ -52,7 +52,7 @@ local function multi_button(args)
args.width = (button_width * #args.options) + #args.options + 1
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- button state (convert nil to 1 if missing)
e.value = args.default or 1
@@ -126,10 +126,8 @@ local function multi_button(args)
e.redraw()
end
- -- initial draw
- e.redraw()
+ ---@class MultiButton:graphics_element
+ local MultiButton, id = e.complete(true)
- return e.complete()
+ return MultiButton, id
end
-
-return multi_button
diff --git a/graphics/elements/controls/spinbox_numeric.lua b/graphics/elements/controls/NumericSpinbox.lua
similarity index 94%
rename from graphics/elements/controls/spinbox_numeric.lua
rename to graphics/elements/controls/NumericSpinbox.lua
index e114c6a..0b530f4 100644
--- a/graphics/elements/controls/spinbox_numeric.lua
+++ b/graphics/elements/controls/NumericSpinbox.lua
@@ -20,10 +20,10 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new spinbox control (minimum value is 0)
+-- Create a new spinbox control element (minimum value is 0).
---@param args spinbox_args
----@return graphics_element element, element_id id
-local function spinbox(args)
+---@return NumericSpinbox element, element_id id
+return function (args)
-- properties
local digits = {}
local wn_prec = args.whole_num_precision
@@ -51,7 +51,7 @@ local function spinbox(args)
args.height = 3
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- set initial value
e.value = args.default or 0
@@ -179,10 +179,8 @@ local function spinbox(args)
draw_arrows(util.trinary(e.enabled, args.arrow_fg_bg.fgd, args.arrow_disable or colors.lightGray))
end
- -- initial draw
- e.redraw()
+ ---@class NumericSpinbox:graphics_element
+ local NumericSpinbox, id = e.complete(true)
- return e.complete()
+ return NumericSpinbox, id
end
-
-return spinbox
diff --git a/graphics/elements/controls/push_button.lua b/graphics/elements/controls/PushButton.lua
similarity index 94%
rename from graphics/elements/controls/push_button.lua
rename to graphics/elements/controls/PushButton.lua
index f060901..bc8b7dd 100644
--- a/graphics/elements/controls/push_button.lua
+++ b/graphics/elements/controls/PushButton.lua
@@ -25,10 +25,10 @@ local KEY_CLICK = core.events.KEY_CLICK
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new push button
+-- Create a new push button control element.
---@param args push_button_args
----@return graphics_element element, element_id id
-local function push_button(args)
+---@return PushButton element, element_id id
+return function (args)
element.assert(type(args.text) == "string", "text is a required field")
element.assert(type(args.callback) == "function", "callback is a required field")
element.assert(type(args.min_width) == "nil" or (type(args.min_width) == "number" and args.min_width > 0), "min_width must be nil or a number > 0")
@@ -48,7 +48,7 @@ local function push_button(args)
end
-- create new graphics element base object
- local e = element.new(args, constrain)
+ local e = element.new(args --[[@as graphics_args]], constrain)
local text_lines = util.strwrap(args.text, e.frame.w)
@@ -157,10 +157,8 @@ local function push_button(args)
e.on_focused = show_pressed
e.on_unfocused = show_unpressed
- -- initial draw
- e.redraw()
+ ---@class PushButton:graphics_element
+ local PushButton, id = e.complete(true)
- return e.complete()
+ return PushButton, id
end
-
-return push_button
diff --git a/graphics/elements/controls/radio_2d.lua b/graphics/elements/controls/Radio2D.lua
similarity index 95%
rename from graphics/elements/controls/radio_2d.lua
rename to graphics/elements/controls/Radio2D.lua
index 65d4c09..cf2da34 100644
--- a/graphics/elements/controls/radio_2d.lua
+++ b/graphics/elements/controls/Radio2D.lua
@@ -23,10 +23,10 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new 2D radio button list (latch selection, exclusively one color at a time)
+-- Create a new 2-dimensional (rows and columns of options) radio button list control element (latch selection, exclusively one color at a time).
---@param args radio_2d_args
----@return graphics_element element, element_id id
-local function radio_2d_button(args)
+---@return Radio2D element, element_id id
+return function (args)
element.assert(type(args.options) == "table" and #args.options > 0, "options should be a table with length >= 1")
element.assert(util.is_int(args.rows) and util.is_int(args.columns), "rows/columns must be integers")
element.assert((args.rows * args.columns) >= #args.options, "rows x columns size insufficient for provided number of options")
@@ -70,7 +70,7 @@ local function radio_2d_button(args)
args.height = max_rows
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- selected option (convert nil to 1 if missing)
e.value = args.default or 1
@@ -194,10 +194,8 @@ local function radio_2d_button(args)
e.on_enabled = e.redraw
e.on_disabled = e.redraw
- -- initial draw
- e.redraw()
+ ---@class Radio2D:graphics_element
+ local Radio2D, id = e.complete(true)
- return e.complete()
+ return Radio2D, id
end
-
-return radio_2d_button
diff --git a/graphics/elements/controls/radio_button.lua b/graphics/elements/controls/RadioButton.lua
similarity index 93%
rename from graphics/elements/controls/radio_button.lua
rename to graphics/elements/controls/RadioButton.lua
index be9b1ee..a2acffc 100644
--- a/graphics/elements/controls/radio_button.lua
+++ b/graphics/elements/controls/RadioButton.lua
@@ -21,10 +21,10 @@ local KEY_CLICK = core.events.KEY_CLICK
---@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)
+-- Create a new radio button list control element (latch selection, exclusively one button at a time).
---@param args radio_button_args
----@return graphics_element element, element_id id
-local function radio_button(args)
+---@return RadioButton element, element_id id
+return function (args)
element.assert(type(args.options) == "table", "options is a required field")
element.assert(#args.options > 0, "at least one option is required")
element.assert(type(args.radio_colors) == "table", "radio_colors is a required field")
@@ -49,7 +49,7 @@ local function radio_button(args)
args.height = #args.options -- one line per option
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
local focused_opt = 1
@@ -139,10 +139,8 @@ local function radio_button(args)
e.on_enabled = e.redraw
e.on_disabled = e.redraw
- -- initial draw
- e.redraw()
+ ---@class RadioButton:graphics_element
+ local RadioButton, id = e.complete(true)
- return e.complete()
+ return RadioButton, id
end
-
-return radio_button
diff --git a/graphics/elements/controls/sidebar.lua b/graphics/elements/controls/Sidebar.lua
similarity index 90%
rename from graphics/elements/controls/sidebar.lua
rename to graphics/elements/controls/Sidebar.lua
index 58e8b13..7c3eac6 100644
--- a/graphics/elements/controls/sidebar.lua
+++ b/graphics/elements/controls/Sidebar.lua
@@ -17,14 +17,14 @@ local MOUSE_CLICK = core.events.MOUSE_CLICK
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new sidebar tab selector
+-- Create a new sidebar tab selector control element.
---@param args sidebar_args
----@return graphics_element element, element_id id
-local function sidebar(args)
+---@return Sidebar element, element_id id
+return function (args)
args.width = 3
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- default to 1st tab
e.value = 1
@@ -129,8 +129,14 @@ local function sidebar(args)
end
-- update the sidebar navigation options
- ---@param items table sidebar entries
+ ---@param items sidebar_entry[] sidebar entries
function e.on_update(items)
+ ---@class sidebar_entry
+ ---@field label string
+ ---@field tall boolean
+ ---@field color cpair
+ ---@field callback function|nil
+
local next_y = 1
tabs = {}
@@ -160,9 +166,8 @@ local function sidebar(args)
-- element redraw
e.redraw = draw
- e.redraw()
+ ---@class Sidebar:graphics_element
+ local Sidebar, id = e.complete(true)
- return e.complete()
+ return Sidebar, id
end
-
-return sidebar
diff --git a/graphics/elements/controls/switch_button.lua b/graphics/elements/controls/SwitchButton.lua
similarity index 88%
rename from graphics/elements/controls/switch_button.lua
rename to graphics/elements/controls/SwitchButton.lua
index 8abf8a7..e23db03 100644
--- a/graphics/elements/controls/switch_button.lua
+++ b/graphics/elements/controls/SwitchButton.lua
@@ -17,10 +17,10 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new switch button (latch high/low)
+-- Create a new latching switch button control element.
---@param args switch_button_args
----@return graphics_element element, element_id id
-local function switch_button(args)
+---@return SwitchButton element, element_id id
+return function (args)
element.assert(type(args.text) == "string", "text is a required field")
element.assert(type(args.callback) == "function", "callback is a required field")
element.assert(type(args.active_fg_bg) == "table", "active_fg_bg is a required field")
@@ -33,7 +33,7 @@ local function switch_button(args)
args.width = math.max(text_width, args.min_width)
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = args.default or false
@@ -72,10 +72,8 @@ local function switch_button(args)
e.redraw()
end
- -- initial draw
- e.redraw()
+ ---@class SwitchButton:graphics_element
+ local SwitchButton, id = e.complete(true)
- return e.complete()
+ return SwitchButton, id
end
-
-return switch_button
diff --git a/graphics/elements/controls/tabbar.lua b/graphics/elements/controls/TabBar.lua
similarity index 93%
rename from graphics/elements/controls/tabbar.lua
rename to graphics/elements/controls/TabBar.lua
index c76781b..f6aa13c 100644
--- a/graphics/elements/controls/tabbar.lua
+++ b/graphics/elements/controls/TabBar.lua
@@ -23,10 +23,10 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new tab selector
+-- Create a new tab selector control element.
---@param args tabbar_args
----@return graphics_element element, element_id id
-local function tabbar(args)
+---@return TabBar element, element_id id
+return function (args)
element.assert(type(args.tabs) == "table", "tabs is a required field")
element.assert(#args.tabs > 0, "at least one tab is required")
element.assert(type(args.callback) == "function", "callback is a required field")
@@ -46,7 +46,7 @@ local function tabbar(args)
local button_width = math.max(max_width, args.min_width or 0)
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
element.assert(e.frame.w >= (button_width * #args.tabs), "width insufficent to display all tabs")
@@ -120,10 +120,8 @@ local function tabbar(args)
e.redraw()
end
- -- initial draw
- e.redraw()
+ ---@class TabBar:graphics_element
+ local TabBar, id = e.complete(true)
- return e.complete()
+ return TabBar, id
end
-
-return tabbar
diff --git a/graphics/elements/form/number_field.lua b/graphics/elements/form/NumberField.lua
similarity index 96%
rename from graphics/elements/form/number_field.lua
rename to graphics/elements/form/NumberField.lua
index 01a4dad..2653069 100644
--- a/graphics/elements/form/number_field.lua
+++ b/graphics/elements/form/NumberField.lua
@@ -27,10 +27,10 @@ local MOUSE_CLICK = core.events.MOUSE_CLICK
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new numeric entry field
+-- Create a new numeric entry field.
---@param args number_field_args
----@return graphics_element element, element_id id
-local function number_field(args)
+---@return NumberField element, element_id id
+return function (args)
element.assert(args.max_int_digits == nil or (util.is_int(args.max_int_digits) and args.max_int_digits > 0), "max_int_digits must be an integer greater than zero if supplied")
element.assert(args.max_frac_digits == nil or (util.is_int(args.max_frac_digits) and args.max_frac_digits > 0), "max_frac_digits must be an integer greater than zero if supplied")
@@ -38,7 +38,7 @@ local function number_field(args)
args.can_focus = true
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
local has_decimal = false
@@ -195,10 +195,8 @@ local function number_field(args)
e.on_disabled = ifield.show
e.redraw = ifield.show
- -- initial draw
- e.redraw()
+ ---@class NumberField:graphics_element
+ local NumberField, id = e.complete(true)
- return e.complete()
+ return NumberField, id
end
-
-return number_field
diff --git a/graphics/elements/form/text_field.lua b/graphics/elements/form/TextField.lua
similarity index 91%
rename from graphics/elements/form/text_field.lua
rename to graphics/elements/form/TextField.lua
index f912b9e..1382a11 100644
--- a/graphics/elements/form/text_field.lua
+++ b/graphics/elements/form/TextField.lua
@@ -19,15 +19,15 @@ local MOUSE_CLICK = core.events.MOUSE_CLICK
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new text entry field
+-- Create a new text entry field.
---@param args text_field_args
----@return graphics_element element, element_id id, function censor_ctl
-local function text_field(args)
+---@return TextField element, element_id id
+return function (args)
args.height = 1
args.can_focus = true
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- set initial value
e.value = args.value or ""
@@ -95,11 +95,10 @@ local function text_field(args)
e.on_disabled = ifield.show
e.redraw = ifield.show
- -- initial draw
- e.redraw()
+ ---@class TextField:graphics_element
+ local TextField, id = e.complete(true)
- local elem, id = e.complete()
- return elem, id, ifield.censor
+ TextField.censor = ifield.censor
+
+ return TextField, id
end
-
-return text_field
diff --git a/graphics/elements/indicators/alight.lua b/graphics/elements/indicators/AlarmLight.lua
similarity index 92%
rename from graphics/elements/indicators/alight.lua
rename to graphics/elements/indicators/AlarmLight.lua
index e05569c..7350462 100644
--- a/graphics/elements/indicators/alight.lua
+++ b/graphics/elements/indicators/AlarmLight.lua
@@ -20,11 +20,11 @@ local flasher = require("graphics.flasher")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new alarm indicator light
+-- Create a new alarm indicator light element.
---@nodiscard
---@param args alarm_indicator_light
----@return graphics_element element, element_id id
-local function alarm_indicator_light(args)
+---@return AlarmLight element, element_id id
+return function (args)
element.assert(type(args.label) == "string", "label is a required field")
element.assert(type(args.c1) == "number", "c1 is a required field")
element.assert(type(args.c2) == "number", "c2 is a required field")
@@ -49,7 +49,7 @@ local function alarm_indicator_light(args)
local c3 = colors.toBlit(args.c3)
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = 1
@@ -113,10 +113,8 @@ local function alarm_indicator_light(args)
e.w_write(args.label)
end
- -- initial draw
- e.redraw()
+ ---@class AlarmLight:graphics_element
+ local AlarmLight, id = e.complete(true)
- return e.complete()
+ return AlarmLight, id
end
-
-return alarm_indicator_light
diff --git a/graphics/elements/indicators/coremap.lua b/graphics/elements/indicators/CoreMap.lua
similarity index 94%
rename from graphics/elements/indicators/coremap.lua
rename to graphics/elements/indicators/CoreMap.lua
index 9084b99..071fdc0 100644
--- a/graphics/elements/indicators/coremap.lua
+++ b/graphics/elements/indicators/CoreMap.lua
@@ -13,11 +13,11 @@ local element = require("graphics.element")
---@field x? integer 1 if omitted
---@field y? integer auto incremented if omitted
--- new core map box
+-- Create a new core map diagram indicator element.
---@nodiscard
---@param args core_map_args
----@return graphics_element element, element_id id
-local function core_map(args)
+---@return CoreMap element, element_id id
+return function (args)
element.assert(util.is_int(args.reactor_l), "reactor_l is a required field")
element.assert(util.is_int(args.reactor_w), "reactor_w is a required field")
@@ -29,7 +29,7 @@ local function core_map(args)
args.fg_bg = core.cpair(args.parent.get_fg_bg().fgd, colors.gray)
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = 0
@@ -165,10 +165,8 @@ local function core_map(args)
draw_core(e.value)
end
- -- initial draw
- e.redraw()
+ ---@class CoreMap:graphics_element
+ local CoreMap, id = e.complete(true)
- return e.complete()
+ return CoreMap, id
end
-
-return core_map
diff --git a/graphics/elements/indicators/data.lua b/graphics/elements/indicators/DataIndicator.lua
similarity index 90%
rename from graphics/elements/indicators/data.lua
rename to graphics/elements/indicators/DataIndicator.lua
index 2304807..38a253a 100644
--- a/graphics/elements/indicators/data.lua
+++ b/graphics/elements/indicators/DataIndicator.lua
@@ -19,11 +19,11 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new data indicator
+-- Create new data indicator element.
---@nodiscard
---@param args data_indicator_args
----@return graphics_element element, element_id id
-local function data(args)
+---@return DataIndicator element, element_id id
+return function (args)
element.assert(type(args.label) == "string", "label is a required field")
element.assert(type(args.format) == "string", "format is a required field")
element.assert(args.value ~= nil, "value is a required field")
@@ -32,7 +32,7 @@ local function data(args)
args.height = 1
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = args.value
@@ -94,10 +94,8 @@ local function data(args)
e.on_update(e.value)
end
- -- initial draw
- e.redraw()
+ ---@class DataIndicator:graphics_element
+ local DataIndicator, id = e.complete(true)
- return e.complete()
+ return DataIndicator, id
end
-
-return data
diff --git a/graphics/elements/indicators/hbar.lua b/graphics/elements/indicators/HorizontalBar.lua
similarity index 93%
rename from graphics/elements/indicators/hbar.lua
rename to graphics/elements/indicators/HorizontalBar.lua
index eb4607a..892cac7 100644
--- a/graphics/elements/indicators/hbar.lua
+++ b/graphics/elements/indicators/HorizontalBar.lua
@@ -17,13 +17,13 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new horizontal bar
+-- Create a new horizontal fill bar indicator element.
---@nodiscard
---@param args hbar_args
---@return graphics_element element, element_id id
-local function hbar(args)
+return function (args)
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = 0.0
@@ -119,10 +119,8 @@ local function hbar(args)
e.on_update(e.value)
end
- -- initial draw
- e.redraw()
+ ---@class HorizontalBar:graphics_element
+ local HorizontalBar, id = e.complete(true)
- return e.complete()
+ return HorizontalBar, id
end
-
-return hbar
diff --git a/graphics/elements/indicators/icon.lua b/graphics/elements/indicators/IconIndicator.lua
similarity index 88%
rename from graphics/elements/indicators/icon.lua
rename to graphics/elements/indicators/IconIndicator.lua
index 15aef3a..377c447 100644
--- a/graphics/elements/indicators/icon.lua
+++ b/graphics/elements/indicators/IconIndicator.lua
@@ -18,11 +18,11 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new icon indicator
+-- Create a new icon indicator element.
---@nodiscard
---@param args icon_indicator_args
----@return graphics_element element, element_id id
-local function icon(args)
+---@return IconIndicator element, element_id id
+return function (args)
element.assert(type(args.label) == "string", "label is a required field")
element.assert(type(args.states) == "table", "states is a required field")
@@ -30,7 +30,7 @@ local function icon(args)
args.width = math.max(args.min_label_width or 1, string.len(args.label)) + 4
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = args.value or 1
if e.value == true then e.value = 2 end
@@ -71,10 +71,8 @@ local function icon(args)
e.on_update(e.value)
end
- -- initial draw
- e.redraw()
+ ---@class IconIndicator:graphics_element
+ local IconIndicator, id = e.complete(true)
- return e.complete()
+ return IconIndicator, id
end
-
-return icon
diff --git a/graphics/elements/indicators/light.lua b/graphics/elements/indicators/IndicatorLight.lua
similarity index 90%
rename from graphics/elements/indicators/light.lua
rename to graphics/elements/indicators/IndicatorLight.lua
index 290118c..15e3ddd 100644
--- a/graphics/elements/indicators/light.lua
+++ b/graphics/elements/indicators/IndicatorLight.lua
@@ -18,11 +18,11 @@ local flasher = require("graphics.flasher")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new indicator light
+-- Create a new indicator light element.
---@nodiscard
---@param args indicator_light_args
----@return graphics_element element, element_id id
-local function indicator_light(args)
+---@return IndicatorLight element, element_id id
+return function (args)
element.assert(type(args.label) == "string", "label is a required field")
element.assert(type(args.colors) == "table", "colors is a required field")
@@ -36,7 +36,7 @@ local function indicator_light(args)
local flash_on = true
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = false
@@ -93,10 +93,8 @@ local function indicator_light(args)
e.w_write(args.label)
end
- -- initial draw
- e.redraw()
+ ---@class IndicatorLight:graphics_element
+ local IndicatorLight, id = e.complete(true)
- return e.complete()
+ return IndicatorLight, id
end
-
-return indicator_light
diff --git a/graphics/elements/indicators/led.lua b/graphics/elements/indicators/LED.lua
similarity index 91%
rename from graphics/elements/indicators/led.lua
rename to graphics/elements/indicators/LED.lua
index 011ee62..9cdb072 100644
--- a/graphics/elements/indicators/led.lua
+++ b/graphics/elements/indicators/LED.lua
@@ -18,11 +18,11 @@ local flasher = require("graphics.flasher")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new indicator LED
+-- Create a new indicator LED element.
---@nodiscard
---@param args indicator_led_args
----@return graphics_element element, element_id id
-local function indicator_led(args)
+---@return LED element, element_id id
+return function (args)
element.assert(type(args.label) == "string", "label is a required field")
element.assert(type(args.colors) == "table", "colors is a required field")
@@ -36,7 +36,7 @@ local function indicator_led(args)
local flash_on = true
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = false
@@ -95,10 +95,8 @@ local function indicator_led(args)
end
end
- -- initial draw
- e.redraw()
+ ---@class LED:graphics_element
+ local LED, id = e.complete(true)
- return e.complete()
+ return LED, id
end
-
-return indicator_led
diff --git a/graphics/elements/indicators/ledpair.lua b/graphics/elements/indicators/LEDPair.lua
similarity index 89%
rename from graphics/elements/indicators/ledpair.lua
rename to graphics/elements/indicators/LEDPair.lua
index 1a81854..46e55c6 100644
--- a/graphics/elements/indicators/ledpair.lua
+++ b/graphics/elements/indicators/LEDPair.lua
@@ -20,11 +20,12 @@ local flasher = require("graphics.flasher")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new dual LED indicator light
+-- Create a new three-state LED indicator light. Two "active" states (colors c1 and c2) and an inactive state (off).
+-- Values: 1 = off, 2 = c1, 3 = c2
---@nodiscard
---@param args indicator_led_pair_args
----@return graphics_element element, element_id id
-local function indicator_led_pair(args)
+---@return LEDPair element, element_id id
+return function (args)
element.assert(type(args.label) == "string", "label is a required field")
element.assert(type(args.off) == "number", "off is a required field")
element.assert(type(args.c1) == "number", "c1 is a required field")
@@ -44,7 +45,7 @@ local function indicator_led_pair(args)
local c2 = colors.toBlit(args.c2)
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = 1
@@ -104,10 +105,8 @@ local function indicator_led_pair(args)
end
end
- -- initial draw
- e.redraw()
+ ---@class LEDPair:graphics_element
+ local LEDPair, id = e.complete(true)
- return e.complete()
+ return LEDPair, id
end
-
-return indicator_led_pair
diff --git a/graphics/elements/indicators/power.lua b/graphics/elements/indicators/PowerIndicator.lua
similarity index 87%
rename from graphics/elements/indicators/power.lua
rename to graphics/elements/indicators/PowerIndicator.lua
index 7a09f95..53c18aa 100644
--- a/graphics/elements/indicators/power.lua
+++ b/graphics/elements/indicators/PowerIndicator.lua
@@ -19,11 +19,11 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new power indicator
+-- Create a new power indicator. Variant of a data indicator with dynamic energy units.
---@nodiscard
---@param args power_indicator_args
----@return graphics_element element, element_id id
-local function power(args)
+---@return PowerIndicator element, element_id id
+return function (args)
element.assert(type(args.label) == "string", "label is a required field")
element.assert(type(args.unit) == "string", "unit is a required field")
element.assert(type(args.value) == "number", "value is a required field")
@@ -32,7 +32,7 @@ local function power(args)
args.height = 1
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = args.value
@@ -82,10 +82,8 @@ local function power(args)
e.on_update(e.value)
end
- -- initial draw
- e.redraw()
+ ---@class PowerIndicator:graphics_element
+ local PowerIndicator, id = e.complete(true)
- return e.complete()
+ return PowerIndicator, id
end
-
-return power
diff --git a/graphics/elements/indicators/ledrgb.lua b/graphics/elements/indicators/RGBLED.lua
similarity index 85%
rename from graphics/elements/indicators/ledrgb.lua
rename to graphics/elements/indicators/RGBLED.lua
index 406e0cc..aacd484 100644
--- a/graphics/elements/indicators/ledrgb.lua
+++ b/graphics/elements/indicators/RGBLED.lua
@@ -13,11 +13,11 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new RGB LED indicator light
+-- Create a new RGB LED indicator light element.
---@nodiscard
---@param args indicator_led_rgb_args
----@return graphics_element element, element_id id
-local function indicator_led_rgb(args)
+---@return RGBLED element, element_id id
+return function (args)
element.assert(type(args.label) == "string", "label is a required field")
element.assert(type(args.colors) == "table", "colors is a required field")
@@ -25,7 +25,7 @@ local function indicator_led_rgb(args)
args.width = math.max(args.min_label_width or 0, string.len(args.label)) + 2
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = 1
@@ -52,10 +52,8 @@ local function indicator_led_rgb(args)
end
end
- -- initial draw
- e.redraw()
+ ---@class RGBLED:graphics_element
+ local RGBLED, id = e.complete(true)
- return e.complete()
+ return RGBLED, id
end
-
-return indicator_led_rgb
diff --git a/graphics/elements/indicators/rad.lua b/graphics/elements/indicators/RadIndicator.lua
similarity index 87%
rename from graphics/elements/indicators/rad.lua
rename to graphics/elements/indicators/RadIndicator.lua
index 545ea41..73fc9b3 100644
--- a/graphics/elements/indicators/rad.lua
+++ b/graphics/elements/indicators/RadIndicator.lua
@@ -19,11 +19,11 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new radiation indicator
+-- Create a new radiation indicator element. Variant of a data indicator using dynamic Sievert unit precision.
---@nodiscard
---@param args rad_indicator_args
----@return graphics_element element, element_id id
-local function rad(args)
+---@return RadIndicator element, element_id id
+return function (args)
element.assert(type(args.label) == "string", "label is a required field")
element.assert(type(args.format) == "string", "format is a required field")
element.assert(util.is_int(args.width), "width is a required field")
@@ -31,7 +31,7 @@ local function rad(args)
args.height = 1
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = args.value or types.new_zero_radiation_reading()
@@ -83,10 +83,8 @@ local function rad(args)
e.on_update(e.value)
end
- -- initial draw
- e.redraw()
+ ---@class RadIndicator:graphics_element
+ local RadIndicator, id = e.complete(true)
- return e.complete()
+ return RadIndicator, id
end
-
-return rad
diff --git a/graphics/elements/indicators/signal.lua b/graphics/elements/indicators/SignalBar.lua
similarity index 90%
rename from graphics/elements/indicators/signal.lua
rename to graphics/elements/indicators/SignalBar.lua
index 7e9c1b8..37d1359 100644
--- a/graphics/elements/indicators/signal.lua
+++ b/graphics/elements/indicators/SignalBar.lua
@@ -15,16 +15,16 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors (foreground is used for high signal quality)
---@field hidden? boolean true to hide on initial draw
--- new signal bar
+-- Create a new signal bar indicator element.
---@nodiscard
---@param args signal_bar_args
----@return graphics_element element, element_id id
-local function signal_bar(args)
+---@return SignalBar element, element_id id
+return function (args)
args.height = 1
args.width = util.trinary(args.compact, 1, 2)
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = 0
@@ -76,10 +76,8 @@ local function signal_bar(args)
end
end
- -- initial draw
- e.redraw()
+ ---@class SignalBar:graphics_element
+ local SignalBar, id = e.complete(true)
- return e.complete()
+ return SignalBar, id
end
-
-return signal_bar
diff --git a/graphics/elements/indicators/state.lua b/graphics/elements/indicators/StateIndicator.lua
similarity index 88%
rename from graphics/elements/indicators/state.lua
rename to graphics/elements/indicators/StateIndicator.lua
index f2dc134..8ee2cdc 100644
--- a/graphics/elements/indicators/state.lua
+++ b/graphics/elements/indicators/StateIndicator.lua
@@ -20,11 +20,11 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new state indicator
+-- Create a new state indicator element.
---@nodiscard
---@param args state_indicator_args
----@return graphics_element element, element_id id
-local function state_indicator(args)
+---@return StateIndicator element, element_id id
+return function (args)
element.assert(type(args.states) == "table", "states is a required field")
if util.is_int(args.height) then
@@ -52,7 +52,7 @@ local function state_indicator(args)
end
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = args.value or 1
@@ -74,10 +74,8 @@ local function state_indicator(args)
---@param val integer indicator state
function e.set_value(val) e.on_update(val) end
- -- initial draw
- e.redraw()
+ ---@class StateIndicator:graphics_element
+ local StateIndicator, id = e.complete(true)
- return e.complete()
+ return StateIndicator, id
end
-
-return state_indicator
diff --git a/graphics/elements/indicators/trilight.lua b/graphics/elements/indicators/TriIndicatorLight.lua
similarity index 91%
rename from graphics/elements/indicators/trilight.lua
rename to graphics/elements/indicators/TriIndicatorLight.lua
index f5d441c..e01d12d 100644
--- a/graphics/elements/indicators/trilight.lua
+++ b/graphics/elements/indicators/TriIndicatorLight.lua
@@ -20,11 +20,11 @@ local flasher = require("graphics.flasher")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new tri-state indicator light
+-- Create a new tri-state indicator light element.
---@nodiscard
---@param args tristate_indicator_light_args
----@return graphics_element element, element_id id
-local function tristate_indicator_light(args)
+---@return TriIndicatorLight element, element_id id
+return function (args)
element.assert(type(args.label) == "string", "label is a required field")
element.assert(type(args.c1) == "number", "c1 is a required field")
element.assert(type(args.c2) == "number", "c2 is a required field")
@@ -38,7 +38,7 @@ local function tristate_indicator_light(args)
args.width = math.max(args.min_label_width or 1, string.len(args.label)) + 2
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = 1
@@ -102,10 +102,8 @@ local function tristate_indicator_light(args)
e.w_write(args.label)
end
- -- initial draw
- e.redraw()
+ ---@class TriIndicatorLight:graphics_element
+ local TriIndicatorLight, id = e.complete(true)
- return e.complete()
+ return TriIndicatorLight, id
end
-
-return tristate_indicator_light
diff --git a/graphics/elements/indicators/vbar.lua b/graphics/elements/indicators/VerticalBar.lua
similarity index 90%
rename from graphics/elements/indicators/vbar.lua
rename to graphics/elements/indicators/VerticalBar.lua
index afe56fc..d04c286 100644
--- a/graphics/elements/indicators/vbar.lua
+++ b/graphics/elements/indicators/VerticalBar.lua
@@ -15,13 +15,13 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new vertical bar
+-- Create a new vertical fill bar indicator element.
---@nodiscard
---@param args vbar_args
----@return graphics_element element, element_id id
-local function vbar(args)
+---@return VerticalBar element, element_id id
+return function (args)
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = 0.0
@@ -98,10 +98,8 @@ local function vbar(args)
e.redraw()
end
- -- initial draw
- e.redraw()
+ ---@class VerticalBar:graphics_element
+ local VerticalBar, id = e.complete(true)
- return e.complete()
+ return VerticalBar, id
end
-
-return vbar
diff --git a/graphics/flasher.lua b/graphics/flasher.lua
index 9412ac7..624822b 100644
--- a/graphics/flasher.lua
+++ b/graphics/flasher.lua
@@ -18,7 +18,7 @@ local PERIOD = {
flasher.PERIOD = PERIOD
local active = false
-local registry = { {}, {}, {} } -- one registry table per period
+local registry = { {}, {}, {} } ---@type [ function[], function[], function [] ] one registry table per period
local callback_counter = 0
-- blink registered indicators
diff --git a/pocket/configure.lua b/pocket/configure.lua
index 0e91caa..e2585a6 100644
--- a/pocket/configure.lua
+++ b/pocket/configure.lua
@@ -9,18 +9,18 @@ local util = require("scada-common.util")
local core = require("graphics.core")
local themes = require("graphics.themes")
-local DisplayBox = require("graphics.elements.displaybox")
-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 DisplayBox = require("graphics.elements.DisplayBox")
+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.push_button")
-local RadioButton = require("graphics.elements.controls.radio_button")
+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.number_field")
-local TextField = require("graphics.elements.form.text_field")
+local NumberField = require("graphics.elements.form.NumberField")
+local TextField = require("graphics.elements.form.TextField")
local println = util.println
local tri = util.trinary
@@ -58,8 +58,8 @@ local tool_ctl = {
viewing_config = false,
importing_legacy = false,
- view_cfg = nil, ---@type graphics_element
- settings_apply = nil, ---@type graphics_element
+ view_cfg = nil, ---@type PushButton
+ settings_apply = nil, ---@type PushButton
set_networked = nil, ---@type function
bundled_emcool = nil, ---@type function
@@ -68,8 +68,8 @@ local tool_ctl = {
load_legacy = nil, ---@type function
show_auth_key = nil, ---@type function
- show_key_btn = nil, ---@type graphics_element
- auth_key_textbox = nil, ---@type graphics_element
+ show_key_btn = nil, ---@type PushButton
+ auth_key_textbox = nil, ---@type TextBox
auth_key_value = ""
}
@@ -122,7 +122,7 @@ local function load_settings(target, raw)
end
-- create the config view
----@param display graphics_element
+---@param display DisplayBox
local function config_view(display)
---@diagnostic disable-next-line: undefined-field
local function exit() os.queueEvent("terminate") end
@@ -282,14 +282,14 @@ local function config_view(display)
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, _, censor = 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 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) censor(util.trinary(enable, "*", nil)) end
+ 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}
+ 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)
@@ -323,7 +323,7 @@ local function config_view(display)
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)}
+ 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}
diff --git a/pocket/iocontrol.lua b/pocket/iocontrol.lua
index b04f64d..89b96c5 100644
--- a/pocket/iocontrol.lua
+++ b/pocket/iocontrol.lua
@@ -39,15 +39,6 @@ local io = {
ps = psil.create()
}
--- luacheck: no unused args
-
--- placeholder acknowledge function for type hinting
----@param success boolean
----@diagnostic disable-next-line: unused-local
-local function __generic_ack(success) end
-
--- luacheck: unused args
-
local config = nil ---@type pkt_config
local comms = nil ---@type pocket_comms
@@ -92,10 +83,10 @@ function iocontrol.init_core(pkt_comms, nav, cfg)
get_tone_states = function () comms.diag__get_alarm_tones() end,
- ready_warn = nil, ---@type graphics_element
- tone_buttons = {},
- alarm_buttons = {},
- tone_indicators = {} -- indicators to update from supervisor tone states
+ ready_warn = nil, ---@type TextBox
+ tone_buttons = {}, ---@type SwitchButton[]
+ alarm_buttons = {}, ---@type Checkbox[]
+ tone_indicators = {} ---@type IndicatorLight[] indicators to update from supervisor tone states
}
-- API access
@@ -166,24 +157,21 @@ function iocontrol.init_fac(conf)
radiation = types.new_zero_radiation_reading(),
- start_ack = __generic_ack,
- stop_ack = __generic_ack,
- scram_ack = __generic_ack,
- ack_alarms_ack = __generic_ack,
+ start_ack = nil, ---@type fun(success: boolean)
+ stop_ack = nil, ---@type fun(success: boolean)
+ scram_ack = nil, ---@type fun(success: boolean)
+ ack_alarms_ack = nil, ---@type fun(success: boolean)
ps = psil.create(),
- induction_ps_tbl = {},
- induction_data_tbl = {},
+ induction_ps_tbl = {}, ---@type psil[]
+ induction_data_tbl = {}, ---@type imatrix_session_db[]
- sps_ps_tbl = {},
- sps_data_tbl = {},
+ sps_ps_tbl = {}, ---@type psil[]
+ sps_data_tbl = {}, ---@type sps_session_db[]
- tank_ps_tbl = {},
- tank_data_tbl = {},
-
- env_d_ps = psil.create(),
- env_d_data = {}
+ tank_ps_tbl = {}, ---@type psil[]
+ tank_data_tbl = {} ---@type dynamicv_session_db[]
}
-- create induction and SPS tables (currently only 1 of each is supported)
@@ -192,107 +180,14 @@ function iocontrol.init_fac(conf)
table.insert(io.facility.sps_ps_tbl, psil.create())
table.insert(io.facility.sps_data_tbl, {})
- -- determine tank information
- if io.facility.tank_mode == 0 then
- io.facility.tank_defs = {}
- -- on facility tank mode 0, setup tank defs to match unit tank option
- for i = 1, conf.num_units do
- io.facility.tank_defs[i] = util.trinary(conf.cooling.r_cool[i].TankConnection, 1, 0)
- end
-
- io.facility.tank_list = { table.unpack(io.facility.tank_defs) }
- else
- -- decode the layout of tanks from the connections definitions
- local tank_mode = io.facility.tank_mode
- local tank_defs = io.facility.tank_defs
- local tank_list = { table.unpack(tank_defs) }
-
- local function calc_fdef(start_idx, end_idx)
- local first = 4
- for i = start_idx, end_idx do
- if io.facility.tank_defs[i] == 2 then
- if i < first then first = i end
- end
- end
- return first
- end
-
- if tank_mode == 1 then
- -- (1) 1 total facility tank (A A A A)
- local first_fdef = calc_fdef(1, #tank_defs)
- for i = 1, #tank_defs do
- if i > first_fdef and tank_defs[i] == 2 then
- tank_list[i] = 0
- end
- end
- elseif tank_mode == 2 then
- -- (2) 2 total facility tanks (A A A B)
- local first_fdef = calc_fdef(1, math.min(3, #tank_defs))
- for i = 1, #tank_defs do
- if (i ~= 4) and (i > first_fdef) and (tank_defs[i] == 2) then
- tank_list[i] = 0
- end
- end
- elseif tank_mode == 3 then
- -- (3) 2 total facility tanks (A A B B)
- for _, a in pairs({ 1, 3 }) do
- local b = a + 1
- if (tank_defs[a] == 2) and (tank_defs[b] == 2) then
- tank_list[b] = 0
- end
- end
- elseif tank_mode == 4 then
- -- (4) 2 total facility tanks (A B B B)
- local first_fdef = calc_fdef(2, #tank_defs)
- for i = 1, #tank_defs do
- if (i ~= 1) and (i > first_fdef) and (tank_defs[i] == 2) then
- tank_list[i] = 0
- end
- end
- elseif tank_mode == 5 then
- -- (5) 3 total facility tanks (A A B C)
- local first_fdef = calc_fdef(1, math.min(2, #tank_defs))
- for i = 1, #tank_defs do
- if (not (i == 3 or i == 4)) and (i > first_fdef) and (tank_defs[i] == 2) then
- tank_list[i] = 0
- end
- end
- elseif tank_mode == 6 then
- -- (6) 3 total facility tanks (A B B C)
- local first_fdef = calc_fdef(2, math.min(3, #tank_defs))
- for i = 1, #tank_defs do
- if (not (i == 1 or i == 4)) and (i > first_fdef) and (tank_defs[i] == 2) then
- tank_list[i] = 0
- end
- end
- elseif tank_mode == 7 then
- -- (7) 3 total facility tanks (A B C C)
- local first_fdef = calc_fdef(3, #tank_defs)
- for i = 1, #tank_defs do
- if (not (i == 1 or i == 2)) and (i > first_fdef) and (tank_defs[i] == 2) then
- tank_list[i] = 0
- end
- end
- end
-
- io.facility.tank_list = tank_list
- end
-
- -- create facility tank tables
- for i = 1, #io.facility.tank_list do
- if io.facility.tank_list[i] == 2 then
- table.insert(io.facility.tank_ps_tbl, psil.create())
- table.insert(io.facility.tank_data_tbl, {})
- end
- end
-
-- create unit data structures
- io.units = {}
+ io.units = {} ---@type pioctl_unit[]
for i = 1, conf.num_units do
---@class pioctl_unit
local entry = {
unit_id = i,
connected = false,
+ ---@type { boilers: { connected: boolean, faulted: boolean }[], turbines: { connected: boolean, faulted: boolean }[] }
rtu_hw = {},
num_boilers = 0,
@@ -323,27 +218,27 @@ function iocontrol.init_fac(conf)
ack_alarms = function () process.ack_all_alarms(i) end,
set_burn = function (rate) process.set_rate(i, rate) end, ---@param rate number burn rate
- start_ack = __generic_ack,
- scram_ack = __generic_ack,
- reset_rps_ack = __generic_ack,
- ack_alarms_ack = __generic_ack,
+ start_ack = nil, ---@type fun(success: boolean)
+ scram_ack = nil, ---@type fun(success: boolean)
+ reset_rps_ack = nil, ---@type fun(success: boolean)
+ ack_alarms_ack = nil, ---@type fun(success: boolean)
- ---@type alarms
+ ---@type { [ALARM]: ALARM_STATE }
alarms = { ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE },
- annunciator = {}, ---@type annunciator
+ annunciator = {}, ---@type annunciator
unit_ps = psil.create(),
- reactor_data = {}, ---@type reactor_db
+ reactor_data = {}, ---@type reactor_db
- boiler_ps_tbl = {},
- boiler_data_tbl = {},
+ boiler_ps_tbl = {}, ---@type psil[]
+ boiler_data_tbl = {}, ---@type boilerv_session_db[]
- turbine_ps_tbl = {},
- turbine_data_tbl = {},
+ turbine_ps_tbl = {}, ---@type psil[]
+ turbine_data_tbl = {}, ---@type turbinev_session_db[]
- tank_ps_tbl = {},
- tank_data_tbl = {}
+ tank_ps_tbl = {}, ---@type psil[]
+ tank_data_tbl = {} ---@type dynamicv_session_db[]
}
-- on other facility modes, overwrite unit TANK option with facility tank defs
@@ -485,7 +380,7 @@ end
-- update unit status data from API_GET_UNIT
---@param data table
function iocontrol.record_unit_data(data)
- local unit = io.units[data[1]] ---@type pioctl_unit
+ local unit = io.units[data[1]]
unit.connected = data[2]
unit.rtu_hw = data[3]
@@ -650,8 +545,8 @@ function iocontrol.record_unit_data(data)
unit.boiler_data_tbl = data[8]
for id = 1, #unit.boiler_data_tbl do
- local boiler = unit.boiler_data_tbl[id] ---@type boilerv_session_db
- local ps = unit.boiler_ps_tbl[id] ---@type psil
+ local boiler = unit.boiler_data_tbl[id]
+ local ps = unit.boiler_ps_tbl[id]
local boiler_status = 1
local computed_status = 1
@@ -683,8 +578,8 @@ function iocontrol.record_unit_data(data)
unit.turbine_data_tbl = data[9]
for id = 1, #unit.turbine_data_tbl do
- local turbine = unit.turbine_data_tbl[id] ---@type turbinev_session_db
- local ps = unit.turbine_ps_tbl[id] ---@type psil
+ local turbine = unit.turbine_data_tbl[id]
+ local ps = unit.turbine_ps_tbl[id]
local turbine_status = 1
local computed_status = 1
diff --git a/pocket/pocket.lua b/pocket/pocket.lua
index 80a2cb5..e759160 100644
--- a/pocket/pocket.lua
+++ b/pocket/pocket.lua
@@ -100,22 +100,22 @@ pocket.APP_ID = APP_ID
---@class nav_tree_page
---@field _p nav_tree_page|nil page's parent
----@field _c table page's children
+---@field _c nav_tree_page[] page's children
---@field nav_to function function to navigate to this page
---@field switcher function|nil function to switch between children
----@field tasks table tasks to run while viewing this page
+---@field tasks function[] tasks to run while viewing this page
-- initialize the page navigation system
---@param smem pkt_shared_memory
function pocket.init_nav(smem)
local self = {
- pane = nil, ---@type graphics_element
- sidebar = nil, ---@type graphics_element
- apps = {},
- containers = {},
- help_map = {},
- help_return = nil,
- loader_return = nil,
+ pane = nil, ---@type AppMultiPane|MultiPane|nil
+ sidebar = nil, ---@type Sidebar|nil
+ apps = {}, ---@type pocket_app[]
+ containers = {}, ---@type Container[]
+ help_map = {}, ---@type { [string]: function }
+ help_return = nil, ---@type POCKET_APP_ID|nil
+ loader_return = nil, ---@type POCKET_APP_ID|nil
cur_app = APP_ID.ROOT
}
@@ -125,27 +125,27 @@ function pocket.init_nav(smem)
local nav = {}
-- set the root pane element to switch between apps with
- ---@param root_pane graphics_element
+ ---@param root_pane MultiPane
function nav.set_pane(root_pane) self.pane = root_pane end
-- link sidebar element
- ---@param sidebar graphics_element
+ ---@param sidebar Sidebar
function nav.set_sidebar(sidebar) self.sidebar = sidebar end
-- register an app
---@param app_id POCKET_APP_ID app ID
- ---@param container graphics_element element that contains this app (usually a Div)
- ---@param pane? graphics_element multipane if this is a simple paned app, then nav_to must be a number
+ ---@param container Container element that contains this app (usually a Div)
+ ---@param pane? AppMultiPane|MultiPane multipane if this is a simple paned app, then nav_to must be a number
---@param require_sv? boolean true to specifiy if this app should be unloaded when the supervisor connection is lost
---@param require_api? boolean true to specifiy if this app should be unloaded when the api connection is lost
function nav.register_app(app_id, container, pane, require_sv, require_api)
---@class pocket_app
local app = {
loaded = false,
- cur_page = nil, ---@type nav_tree_page
+ cur_page = nil, ---@type nav_tree_page
pane = pane,
- paned_pages = {},
- sidebar_items = {}
+ paned_pages = {}, ---@type nav_tree_page[]
+ sidebar_items = {} ---@type sidebar_entry[]
}
app.load = function () app.loaded = true end
@@ -159,13 +159,13 @@ function pocket.init_nav(smem)
function app.requires_conn() return require_sv or require_api or false end
-- delayed set of the pane if it wasn't ready at the start
- ---@param root_pane graphics_element multipane
+ ---@param root_pane AppMultiPane|MultiPane multipane
function app.set_root_pane(root_pane)
app.pane = root_pane
end
-- configure the sidebar
- ---@param items table
+ ---@param items sidebar_entry[]
function app.set_sidebar(items)
app.sidebar_items = items
if self.sidebar then self.sidebar.update(items) end
@@ -263,7 +263,7 @@ function pocket.init_nav(smem)
-- reset help return on navigating out of an app
if app_id == APP_ID.ROOT then self.help_return = nil end
- local app = self.apps[app_id] ---@type pocket_app
+ local app = self.apps[app_id]
if app then
if app.requires_conn() and not smem.pkt_sys.pocket_comms.is_linked() then
-- bring up the app loader
@@ -339,7 +339,7 @@ function pocket.init_nav(smem)
return
end
- local app = self.apps[self.cur_app] ---@type pocket_app
+ local app = self.apps[self.cur_app]
log.debug("attempting app nav up for app " .. self.cur_app)
if not app.nav_up() then
@@ -359,6 +359,7 @@ function pocket.init_nav(smem)
end
-- link the help map from the guide app
+ ---@param map { [string]: function }
function nav.link_help(map) self.help_map = map end
return nav
diff --git a/pocket/renderer.lua b/pocket/renderer.lua
index bc16037..727a74b 100644
--- a/pocket/renderer.lua
+++ b/pocket/renderer.lua
@@ -8,7 +8,7 @@ local style = require("pocket.ui.style")
local core = require("graphics.core")
local flasher = require("graphics.flasher")
-local DisplayBox = require("graphics.elements.displaybox")
+local DisplayBox = require("graphics.elements.DisplayBox")
---@class pocket_renderer
local renderer = {}
diff --git a/pocket/startup.lua b/pocket/startup.lua
index 28b37d9..c31b599 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.1-alpha"
+local POCKET_VERSION = "v0.12.2-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 4066603..a9129b4 100644
--- a/pocket/ui/apps/control.lua
+++ b/pocket/ui/apps/control.lua
@@ -13,19 +13,19 @@ local style = require("pocket.ui.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local MultiPane = require("graphics.elements.multipane")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local MultiPane = require("graphics.elements.MultiPane")
+local TextBox = require("graphics.elements.TextBox")
-local WaitingAnim = require("graphics.elements.animations.waiting")
+local WaitingAnim = require("graphics.elements.animations.Waiting")
-local HazardButton = require("graphics.elements.controls.hazard_button")
-local PushButton = require("graphics.elements.controls.push_button")
+local HazardButton = require("graphics.elements.controls.HazardButton")
+local PushButton = require("graphics.elements.controls.PushButton")
-local NumberField = require("graphics.elements.form.number_field")
+local NumberField = require("graphics.elements.form.NumberField")
-local DataIndicator = require("graphics.elements.indicators.data")
-local IconIndicator = require("graphics.elements.indicators.icon")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
+local IconIndicator = require("graphics.elements.indicators.IconIndicator")
local AUTO_GROUP = types.AUTO_GROUP
@@ -42,7 +42,7 @@ local hzd_fg_bg = cpair(colors.white, colors.gray)
local dis_colors = cpair(colors.white, colors.lightGray)
-- new unit control page view
----@param root graphics_element parent
+---@param root Container parent
local function new_view(root)
local db = iocontrol.get_db()
@@ -63,7 +63,7 @@ local function new_view(root)
local btn_fg_bg = cpair(colors.green, colors.black)
local btn_active = cpair(colors.white, colors.black)
- local page_div = nil ---@type nil|graphics_element
+ local page_div = nil ---@type Div|nil
-- set sidebar to display unit-specific fields based on a specified unit
local function set_sidebar()
@@ -83,7 +83,7 @@ local function new_view(root)
local function load()
page_div = Div{parent=main,y=2,width=main.get_width()}
- local panes = {}
+ local panes = {} ---@type Div[]
local active_unit = 1
@@ -108,7 +108,7 @@ local function new_view(root)
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] ---@type pioctl_unit
+ local unit = db.units[i]
local u_ps = unit.unit_ps
-- refresh data callback, every 500ms it will re-send the query
diff --git a/pocket/ui/apps/diag_apps.lua b/pocket/ui/apps/diag_apps.lua
index 79b3c12..ba2bed3 100644
--- a/pocket/ui/apps/diag_apps.lua
+++ b/pocket/ui/apps/diag_apps.lua
@@ -7,14 +7,14 @@ local pocket = require("pocket.pocket")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local TextBox = require("graphics.elements.TextBox")
-local IndicatorLight = require("graphics.elements.indicators.light")
+local IndicatorLight = require("graphics.elements.indicators.IndicatorLight")
-local Checkbox = require("graphics.elements.controls.checkbox")
-local PushButton = require("graphics.elements.controls.push_button")
-local SwitchButton = require("graphics.elements.controls.switch_button")
+local Checkbox = require("graphics.elements.controls.Checkbox")
+local PushButton = require("graphics.elements.controls.PushButton")
+local SwitchButton = require("graphics.elements.controls.SwitchButton")
local ALIGN = core.ALIGN
local cpair = core.cpair
@@ -22,7 +22,7 @@ local cpair = core.cpair
local APP_ID = pocket.APP_ID
-- create diagnostic app pages
----@param root graphics_element parent
+---@param root Container parent
local function create_pages(root)
local db = iocontrol.get_db()
diff --git a/pocket/ui/apps/dummy_app.lua b/pocket/ui/apps/dummy_app.lua
index 6e92493..a564761 100644
--- a/pocket/ui/apps/dummy_app.lua
+++ b/pocket/ui/apps/dummy_app.lua
@@ -7,13 +7,13 @@ local pocket = require("pocket.pocket")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local TextBox = require("graphics.elements.TextBox")
local APP_ID = pocket.APP_ID
-- create placeholder app page
----@param root graphics_element parent
+---@param root Container parent
local function create_pages(root)
local db = iocontrol.get_db()
diff --git a/pocket/ui/apps/guide.lua b/pocket/ui/apps/guide.lua
index 768824a..660fcc4 100644
--- a/pocket/ui/apps/guide.lua
+++ b/pocket/ui/apps/guide.lua
@@ -15,16 +15,16 @@ local guide_section = require("pocket.ui.pages.guide_section")
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 Div = require("graphics.elements.Div")
+local ListBox = require("graphics.elements.ListBox")
+local MultiPane = require("graphics.elements.MultiPane")
+local TextBox = require("graphics.elements.TextBox")
-local WaitingAnim = require("graphics.elements.animations.waiting")
+local WaitingAnim = require("graphics.elements.animations.Waiting")
-local PushButton = require("graphics.elements.controls.push_button")
+local PushButton = require("graphics.elements.controls.PushButton")
-local TextField = require("graphics.elements.form.text_field")
+local TextField = require("graphics.elements.form.TextField")
local ALIGN = core.ALIGN
local cpair = core.cpair
@@ -36,7 +36,7 @@ local APP_ID = pocket.APP_ID
-- local text_fg = style.text_fg
-- new system guide view
----@param root graphics_element parent
+---@param root Container parent
local function new_view(root)
local db = iocontrol.get_db()
@@ -58,7 +58,7 @@ local function new_view(root)
app.set_sidebar({{ label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = function () db.nav.open_app(APP_ID.ROOT) end }})
- local page_div = nil ---@type nil|graphics_element
+ local page_div = nil ---@type Div|nil
-- load the app (create the elements)
local function load()
@@ -88,12 +88,11 @@ local function new_view(root)
local fps = Div{parent=page_div,x=2,width=p_width}
local gls = Div{parent=page_div,x=2,width=p_width}
local lnk = Div{parent=page_div,x=2,width=p_width}
- local panes = { home, search, use, uis, fps, gls, lnk }
+ local panes = { home, search, use, uis, fps, gls, lnk } ---@type Div[]
- local doc_map = {}
- local search_db = {}
+ local doc_map = {} ---@type { [string]: function }
+ local search_db = {} ---@type [ string, string, string, function ][]
- ---@class _guide_section_constructor_data
local sect_construct_data = { app, page_div, panes, doc_map, search_db, btn_fg_bg, btn_active }
TextBox{parent=home,y=1,text="cc-mek-scada Guide",alignment=ALIGN.CENTER}
@@ -117,7 +116,7 @@ local function new_view(root)
function func_ref.run_search()
local query = string.lower(query_field.get_value())
- local s_results = { {}, {}, {}, {} }
+ local s_results = { {}, {}, {}, {} } ---@type [ string, string, string, function ][][]
search_results.remove_all()
diff --git a/pocket/ui/apps/loader.lua b/pocket/ui/apps/loader.lua
index 8ea72f0..7a45a7a 100644
--- a/pocket/ui/apps/loader.lua
+++ b/pocket/ui/apps/loader.lua
@@ -9,16 +9,16 @@ local conn_waiting = require("pocket.ui.components.conn_waiting")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local MultiPane = require("graphics.elements.multipane")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local MultiPane = require("graphics.elements.MultiPane")
+local TextBox = require("graphics.elements.TextBox")
local APP_ID = pocket.APP_ID
local LINK_STATE = iocontrol.LINK_STATE
-- create the connecting to SV & API page
----@param root graphics_element parent
+---@param root Container parent
local function create_pages(root)
local db = iocontrol.get_db()
diff --git a/pocket/ui/apps/sys_apps.lua b/pocket/ui/apps/sys_apps.lua
index 197a4f6..d797caf 100644
--- a/pocket/ui/apps/sys_apps.lua
+++ b/pocket/ui/apps/sys_apps.lua
@@ -12,12 +12,12 @@ local pocket = require("pocket.pocket")
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 Div = require("graphics.elements.Div")
+local ListBox = require("graphics.elements.ListBox")
+local MultiPane = require("graphics.elements.MultiPane")
+local TextBox = require("graphics.elements.TextBox")
-local PushButton = require("graphics.elements.controls.push_button")
+local PushButton = require("graphics.elements.controls.PushButton")
local ALIGN = core.ALIGN
local cpair = core.cpair
@@ -25,7 +25,7 @@ local cpair = core.cpair
local APP_ID = pocket.APP_ID
-- create system app pages
----@param root graphics_element parent
+---@param root Container parent
local function create_pages(root)
local db = iocontrol.get_db()
diff --git a/pocket/ui/apps/unit.lua b/pocket/ui/apps/unit.lua
index 94f3341..2f97bf9 100644
--- a/pocket/ui/apps/unit.lua
+++ b/pocket/ui/apps/unit.lua
@@ -15,17 +15,17 @@ local turbine = require("pocket.ui.pages.unit_turbine")
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 Div = require("graphics.elements.Div")
+local ListBox = require("graphics.elements.ListBox")
+local MultiPane = require("graphics.elements.MultiPane")
+local TextBox = require("graphics.elements.TextBox")
-local WaitingAnim = require("graphics.elements.animations.waiting")
+local WaitingAnim = require("graphics.elements.animations.Waiting")
-local PushButton = require("graphics.elements.controls.push_button")
+local PushButton = require("graphics.elements.controls.PushButton")
-local DataIndicator = require("graphics.elements.indicators.data")
-local IconIndicator = require("graphics.elements.indicators.icon")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
+local IconIndicator = require("graphics.elements.indicators.IconIndicator")
local ALIGN = core.ALIGN
local cpair = core.cpair
@@ -47,7 +47,7 @@ local emc_ind_s = {
}
-- new unit page view
----@param root graphics_element parent
+---@param root Container parent
local function new_view(root)
local db = iocontrol.get_db()
@@ -69,11 +69,11 @@ local function new_view(root)
local btn_active = cpair(colors.white, colors.black)
local nav_links = {}
- local page_div = nil ---@type nil|graphics_element
+ local page_div = nil ---@type Div|nil
-- set sidebar to display unit-specific fields based on a specified unit
local function set_sidebar(id)
- local unit = db.units[id] ---@type pioctl_unit
+ local unit = db.units[id]
local list = {
{ label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = function () db.nav.open_app(APP_ID.ROOT) end },
@@ -99,7 +99,7 @@ local function new_view(root)
local function load()
page_div = Div{parent=main,y=2,width=main.get_width()}
- local panes = {}
+ local panes = {} ---@type Div[]
local active_unit = 1
@@ -127,7 +127,7 @@ local function new_view(root)
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] ---@type pioctl_unit
+ local unit = db.units[i]
local u_ps = unit.unit_ps
-- refresh data callback, every 500ms it will re-send the query
diff --git a/pocket/ui/components/conn_waiting.lua b/pocket/ui/components/conn_waiting.lua
index b55f067..6050241 100644
--- a/pocket/ui/components/conn_waiting.lua
+++ b/pocket/ui/components/conn_waiting.lua
@@ -8,17 +8,17 @@ local style = require("pocket.ui.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local TextBox = require("graphics.elements.TextBox")
-local WaitingAnim = require("graphics.elements.animations.waiting")
+local WaitingAnim = require("graphics.elements.animations.Waiting")
local ALIGN = core.ALIGN
local cpair = core.cpair
-- create a waiting view
----@param parent graphics_element parent
+---@param parent Container parent
---@param y integer y offset
local function init(parent, y, is_api)
-- root div
diff --git a/pocket/ui/main.lua b/pocket/ui/main.lua
index bf66f9b..eb9c7f1 100644
--- a/pocket/ui/main.lua
+++ b/pocket/ui/main.lua
@@ -21,16 +21,16 @@ local style = require("pocket.ui.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local MultiPane = require("graphics.elements.multipane")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local MultiPane = require("graphics.elements.MultiPane")
+local TextBox = require("graphics.elements.TextBox")
-local WaitingAnim = require("graphics.elements.animations.waiting")
+local WaitingAnim = require("graphics.elements.animations.Waiting")
-local PushButton = require("graphics.elements.controls.push_button")
-local Sidebar = require("graphics.elements.controls.sidebar")
+local PushButton = require("graphics.elements.controls.PushButton")
+local Sidebar = require("graphics.elements.controls.Sidebar")
-local SignalBar = require("graphics.elements.indicators.signal")
+local SignalBar = require("graphics.elements.indicators.SignalBar")
local ALIGN = core.ALIGN
local cpair = core.cpair
@@ -38,7 +38,7 @@ local cpair = core.cpair
local APP_ID = pocket.APP_ID
-- create new main view
----@param main graphics_element main displaybox
+---@param main DisplayBox main displaybox
local function init(main)
local db = iocontrol.get_db()
diff --git a/pocket/ui/pages/guide_section.lua b/pocket/ui/pages/guide_section.lua
index c14a6ab..76ceaf6 100644
--- a/pocket/ui/pages/guide_section.lua
+++ b/pocket/ui/pages/guide_section.lua
@@ -5,14 +5,14 @@ local docs = require("pocket.ui.docs")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local ListBox = require("graphics.elements.listbox")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local ListBox = require("graphics.elements.ListBox")
+local TextBox = require("graphics.elements.TextBox")
-local PushButton = require("graphics.elements.controls.push_button")
+local PushButton = require("graphics.elements.controls.PushButton")
-local IndicatorLight = require("graphics.elements.indicators.light")
-local LED = require("graphics.elements.indicators.led")
+local IndicatorLight = require("graphics.elements.indicators.IndicatorLight")
+local LED = require("graphics.elements.indicators.LED")
local ALIGN = core.ALIGN
local cpair = core.cpair
@@ -21,14 +21,14 @@ local DOC_TYPE = docs.DOC_ITEM_TYPE
local LIST_TYPE = docs.DOC_LIST_TYPE
-- new guide documentation section
----@param data _guide_section_constructor_data
+---@param data { [1]: pocket_app, [2]: Div, [3]: Div[], [4]: { [string]: function }, [5]: [ string, string, string, function ][], [6]: cpair, [7]: cpair }
---@param base_page nav_tree_page
---@param title string
---@param items table
---@param scroll_height integer
---@return nav_tree_page
return function (data, base_page, title, items, scroll_height)
- local app, page_div, panes, doc_map, search_db, btn_fg_bg, btn_active = table.unpack(data)
+ local app, page_div, panes, doc_map, search_db, btn_fg_bg, btn_active = data[1], data[2], data[3], data[4], data[5], data[6], data[7]
local section_page = app.new_page(base_page, #panes + 1)
local section_div = Div{parent=page_div,x=2}
diff --git a/pocket/ui/pages/home_page.lua b/pocket/ui/pages/home_page.lua
index 38385be..80c7a24 100644
--- a/pocket/ui/pages/home_page.lua
+++ b/pocket/ui/pages/home_page.lua
@@ -7,11 +7,11 @@ local pocket = require("pocket.pocket")
local core = require("graphics.core")
-local AppMultiPane = require("graphics.elements.appmultipane")
-local Div = require("graphics.elements.div")
-local TextBox = require("graphics.elements.textbox")
+local AppMultiPane = require("graphics.elements.AppMultiPane")
+local Div = require("graphics.elements.Div")
+local TextBox = require("graphics.elements.TextBox")
-local App = require("graphics.elements.controls.app")
+local App = require("graphics.elements.controls.App")
local ALIGN = core.ALIGN
local cpair = core.cpair
@@ -19,7 +19,7 @@ local cpair = core.cpair
local APP_ID = pocket.APP_ID
-- new home page view
----@param root graphics_element parent
+---@param root Container parent
local function new_view(root)
local db = iocontrol.get_db()
diff --git a/pocket/ui/pages/unit_boiler.lua b/pocket/ui/pages/unit_boiler.lua
index 4ac3993..1790268 100644
--- a/pocket/ui/pages/unit_boiler.lua
+++ b/pocket/ui/pages/unit_boiler.lua
@@ -7,15 +7,15 @@ local style = require("pocket.ui.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local TextBox = require("graphics.elements.TextBox")
-local PushButton = require("graphics.elements.controls.push_button")
+local PushButton = require("graphics.elements.controls.PushButton")
-local DataIndicator = require("graphics.elements.indicators.data")
-local StateIndicator = require("graphics.elements.indicators.state")
-local IconIndicator = require("graphics.elements.indicators.icon")
-local VerticalBar = require("graphics.elements.indicators.vbar")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
+local StateIndicator = require("graphics.elements.indicators.StateIndicator")
+local IconIndicator = require("graphics.elements.indicators.IconIndicator")
+local VerticalBar = require("graphics.elements.indicators.VerticalBar")
local ALIGN = core.ALIGN
local cpair = core.cpair
@@ -29,8 +29,8 @@ local yel_ind_s = style.icon_states.yel_ind_s
-- create a boiler view in the unit app
---@param app pocket_app
---@param u_page nav_tree_page
----@param panes table
----@param blr_pane graphics_element
+---@param panes Div[]
+---@param blr_pane Div
---@param b_id integer boiler ID
---@param ps psil
---@param update function
diff --git a/pocket/ui/pages/unit_reactor.lua b/pocket/ui/pages/unit_reactor.lua
index 56b0378..a3333f5 100644
--- a/pocket/ui/pages/unit_reactor.lua
+++ b/pocket/ui/pages/unit_reactor.lua
@@ -7,15 +7,15 @@ local style = require("pocket.ui.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local TextBox = require("graphics.elements.TextBox")
-local PushButton = require("graphics.elements.controls.push_button")
+local PushButton = require("graphics.elements.controls.PushButton")
-local DataIndicator = require("graphics.elements.indicators.data")
-local StateIndicator = require("graphics.elements.indicators.state")
-local IconIndicator = require("graphics.elements.indicators.icon")
-local VerticalBar = require("graphics.elements.indicators.vbar")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
+local StateIndicator = require("graphics.elements.indicators.StateIndicator")
+local IconIndicator = require("graphics.elements.indicators.IconIndicator")
+local VerticalBar = require("graphics.elements.indicators.VerticalBar")
local ALIGN = core.ALIGN
local cpair = core.cpair
@@ -29,8 +29,8 @@ local yel_ind_s = style.icon_states.yel_ind_s
-- create a reactor view in the unit app
---@param app pocket_app
---@param u_page nav_tree_page
----@param panes table
----@param page_div graphics_element
+---@param panes Div[]
+---@param page_div Div
---@param u_ps psil
---@param update function
return function (app, u_page, panes, page_div, u_ps, update)
diff --git a/pocket/ui/pages/unit_turbine.lua b/pocket/ui/pages/unit_turbine.lua
index df90061..94541ad 100644
--- a/pocket/ui/pages/unit_turbine.lua
+++ b/pocket/ui/pages/unit_turbine.lua
@@ -6,16 +6,16 @@ local style = require("pocket.ui.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local TextBox = require("graphics.elements.TextBox")
-local PushButton = require("graphics.elements.controls.push_button")
+local PushButton = require("graphics.elements.controls.PushButton")
-local DataIndicator = require("graphics.elements.indicators.data")
-local IconIndicator = require("graphics.elements.indicators.icon")
-local PowerIndicator = require("graphics.elements.indicators.power")
-local StateIndicator = require("graphics.elements.indicators.state")
-local VerticalBar = require("graphics.elements.indicators.vbar")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
+local IconIndicator = require("graphics.elements.indicators.IconIndicator")
+local PowerIndicator = require("graphics.elements.indicators.PowerIndicator")
+local StateIndicator = require("graphics.elements.indicators.StateIndicator")
+local VerticalBar = require("graphics.elements.indicators.VerticalBar")
local ALIGN = core.ALIGN
local cpair = core.cpair
@@ -30,8 +30,8 @@ local yel_ind_s = style.icon_states.yel_ind_s
-- create a turbine view in the unit app
---@param app pocket_app
---@param u_page nav_tree_page
----@param panes table
----@param tbn_pane graphics_element
+---@param panes Div[]
+---@param tbn_pane Div
---@param u_id integer unit ID
---@param t_id integer turbine ID
---@param ps psil
diff --git a/reactor-plc/config/check.lua b/reactor-plc/config/check.lua
index 106a51d..7a964fe 100644
--- a/reactor-plc/config/check.lua
+++ b/reactor-plc/config/check.lua
@@ -8,11 +8,11 @@ local plc = require("reactor-plc.plc")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local ListBox = require("graphics.elements.listbox")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local ListBox = require("graphics.elements.ListBox")
+local TextBox = require("graphics.elements.TextBox")
-local PushButton = require("graphics.elements.controls.push_button")
+local PushButton = require("graphics.elements.controls.PushButton")
local tri = util.trinary
@@ -33,8 +33,8 @@ local self = {
settings = nil, ---@type plc_config
- run_test_btn = nil, ---@type graphics_element
- sc_log = nil, ---@type graphics_element
+ run_test_btn = nil, ---@type PushButton
+ sc_log = nil, ---@type ListBox
self_check_msg = nil ---@type function
}
@@ -160,7 +160,7 @@ local function self_check()
end
-- exit self check back home
----@param main_pane graphics_element
+---@param main_pane MultiPane
local function exit_self_check(main_pane)
tcd.abort(handle_timeout)
self.net_listen = false
@@ -172,10 +172,10 @@ end
local check = {}
-- create the self-check view
----@param main_pane graphics_element
+---@param main_pane MultiPane
---@param settings_cfg plc_config
----@param check_sys graphics_element
----@param style table
+---@param check_sys Div
+---@param style { [string]: cpair }
function check.create(main_pane, settings_cfg, check_sys, style)
local bw_fg_bg = style.bw_fg_bg
local g_lg_fg_bg = style.g_lg_fg_bg
diff --git a/reactor-plc/config/system.lua b/reactor-plc/config/system.lua
index f612f9e..7ad213f 100644
--- a/reactor-plc/config/system.lua
+++ b/reactor-plc/config/system.lua
@@ -5,20 +5,20 @@ local util = require("scada-common.util")
local core = require("graphics.core")
local themes = require("graphics.themes")
-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 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.push_button")
-local Radio2D = require("graphics.elements.controls.radio_2d")
-local RadioButton = require("graphics.elements.controls.radio_button")
+local Checkbox = require("graphics.elements.controls.Checkbox")
+local PushButton = require("graphics.elements.controls.PushButton")
+local Radio2D = require("graphics.elements.controls.Radio2D")
+local RadioButton = require("graphics.elements.controls.RadioButton")
-local NumberField = require("graphics.elements.form.number_field")
-local TextField = require("graphics.elements.form.text_field")
+local NumberField = require("graphics.elements.form.NumberField")
+local TextField = require("graphics.elements.form.TextField")
-local IndLight = require("graphics.elements.indicators.light")
+local IndLight = require("graphics.elements.indicators.IndicatorLight")
local cpair = core.cpair
@@ -31,8 +31,8 @@ local self = {
bundled_emcool = nil, ---@type function
show_auth_key = nil, ---@type function
- show_key_btn = nil, ---@type graphics_element
- auth_key_textbox = nil, ---@type graphics_element
+ show_key_btn = nil, ---@type PushButton
+ auth_key_textbox = nil, ---@type TextBox
auth_key_value = ""
}
@@ -61,17 +61,14 @@ local system = {}
-- create the system configuration view
---@param tool_ctl _plc_cfg_tool_ctl
----@param main_pane graphics_element
----@param cfg_sys table
----@param divs table
----@param style table
+---@param main_pane MultiPane
+---@param cfg_sys [ plc_config, plc_config, plc_config, table, function ]
+---@param divs Div[]
+---@param style { [string]: cpair }
---@param exit function
function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
- ---@type plc_config, plc_config, plc_config, table, function
- local settings_cfg, ini_cfg, tmp_cfg, fields, load_settings = table.unpack(cfg_sys)
-
- ---@type graphics_element, graphics_element, graphics_element, graphics_element, graphics_element
- local plc_cfg, net_cfg, log_cfg, clr_cfg, summary = table.unpack(divs)
+ 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 plc_cfg, net_cfg, log_cfg, clr_cfg, summary = divs[1], divs[2], divs[3], divs[4], divs[5]
local bw_fg_bg = style.bw_fg_bg
local g_lg_fg_bg = style.g_lg_fg_bg
@@ -93,7 +90,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
TextBox{parent=plc_c_1,x=1,y=1,text="Would you like to set this PLC as networked?"}
TextBox{parent=plc_c_1,x=1,y=3,height=4,text="If you have a supervisor, select the box. You will later be prompted to select the network configuration. If you instead want to use this as a standalone safety system, don't select the box.",fg_bg=g_lg_fg_bg}
- local networked = CheckBox{parent=plc_c_1,x=1,y=8,label="Networked",default=ini_cfg.Networked,box_fg_bg=cpair(colors.orange,colors.black)}
+ local networked = Checkbox{parent=plc_c_1,x=1,y=8,label="Networked",default=ini_cfg.Networked,box_fg_bg=cpair(colors.orange,colors.black)}
local function submit_networked()
self.set_networked(networked.get_value())
@@ -131,7 +128,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
TextBox{parent=plc_c_3,x=1,y=1,height=4,text="When networked, the supervisor takes care of emergency coolant via RTUs. However, you can configure independent emergency coolant via the PLC."}
TextBox{parent=plc_c_3,x=1,y=6,height=5,text="This independent control can be used with or without a supervisor. To configure, you would next select the interface of the redstone output connected to one or more mekanism pipes.",fg_bg=g_lg_fg_bg}
- local en_em_cool = CheckBox{parent=plc_c_3,x=1,y=11,label="Enable PLC Emergency Coolant Control",default=ini_cfg.EmerCoolEnable,box_fg_bg=cpair(colors.orange,colors.black)}
+ local en_em_cool = Checkbox{parent=plc_c_3,x=1,y=11,label="Enable PLC Emergency Coolant Control",default=ini_cfg.EmerCoolEnable,box_fg_bg=cpair(colors.orange,colors.black)}
local function next_from_plc()
if tmp_cfg.Networked then main_pane.set_value(3) else main_pane.set_value(4) end
@@ -149,7 +146,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
local side = Radio2D{parent=plc_c_4,x=1,y=2,rows=2,columns=3,default=side_to_idx(ini_cfg.EmerCoolSide),options=side_options,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.orange}
TextBox{parent=plc_c_4,x=1,y=5,text="Bundled Redstone Configuration"}
- local bundled = CheckBox{parent=plc_c_4,x=1,y=6,label="Is Bundled?",default=ini_cfg.EmerCoolColor~=nil,box_fg_bg=cpair(colors.orange,colors.black),callback=function(v)self.bundled_emcool(v)end}
+ local bundled = Checkbox{parent=plc_c_4,x=1,y=6,label="Is Bundled?",default=ini_cfg.EmerCoolColor~=nil,box_fg_bg=cpair(colors.orange,colors.black),callback=function(v)self.bundled_emcool(v)end}
local color = Radio2D{parent=plc_c_4,x=1,y=8,rows=4,columns=4,default=color_to_idx(ini_cfg.EmerCoolColor),options=color_options,radio_colors=cpair(colors.lightGray,colors.black),color_map=color_options_map,disable_color=colors.gray,disable_fg_bg=g_lg_fg_bg}
if ini_cfg.EmerCoolColor == nil then color.disable() end
@@ -243,11 +240,11 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
TextBox{parent=net_c_3,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra compution (can slow things down).",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_3,x=1,y=11,text="Facility Auth Key"}
- local key, _, censor = TextField{parent=net_c_3,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg}
+ local key, _ = TextField{parent=net_c_3,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg}
- local function censor_key(enable) censor(util.trinary(enable, "*", nil)) end
+ local function censor_key(enable) key.censor(util.trinary(enable, "*", nil)) end
- local hide_key = CheckBox{parent=net_c_3,x=34,y=12,label="Hide",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key}
+ local hide_key = Checkbox{parent=net_c_3,x=34,y=12,label="Hide",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key}
hide_key.set_value(true)
censor_key(true)
@@ -282,7 +279,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
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=49,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 Logging Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)}
+ local en_dbg = Checkbox{parent=log_c_1,x=1,y=10,default=ini_cfg.LogDebug,label="Enable Logging Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)}
TextBox{parent=log_c_1,x=3,y=11,height=2,text="This results in much larger log files. It is best to only use this when there is a problem.",fg_bg=g_lg_fg_bg}
local path_err = TextBox{parent=log_c_1,x=8,y=14,width=35,text="Please provide a log file path.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
diff --git a/reactor-plc/configure.lua b/reactor-plc/configure.lua
index 81933f9..e8b32d1 100644
--- a/reactor-plc/configure.lua
+++ b/reactor-plc/configure.lua
@@ -12,13 +12,13 @@ local system = require("reactor-plc.config.system")
local core = require("graphics.core")
local themes = require("graphics.themes")
-local DisplayBox = require("graphics.elements.displaybox")
-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 DisplayBox = require("graphics.elements.DisplayBox")
+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 PushButton = require("graphics.elements.controls.push_button")
+local PushButton = require("graphics.elements.controls.PushButton")
local println = util.println
local tri = util.trinary
@@ -58,11 +58,11 @@ local tool_ctl = {
viewing_config = false,
jumped_to_color = false,
- view_cfg = nil, ---@type graphics_element
- color_cfg = nil, ---@type graphics_element
- color_next = nil, ---@type graphics_element
- color_apply = nil, ---@type graphics_element
- settings_apply = nil, ---@type graphics_element
+ view_cfg = nil, ---@type PushButton
+ color_cfg = nil, ---@type PushButton
+ color_next = nil, ---@type PushButton
+ color_apply = nil, ---@type PushButton
+ settings_apply = nil, ---@type PushButton
gen_summary = nil, ---@type function
load_legacy = nil, ---@type function
@@ -125,7 +125,7 @@ local function load_settings(target, raw)
end
-- create the config view
----@param display graphics_element
+---@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
diff --git a/reactor-plc/databus.lua b/reactor-plc/databus.lua
index 7436dbb..b2bd1c2 100644
--- a/reactor-plc/databus.lua
+++ b/reactor-plc/databus.lua
@@ -77,7 +77,7 @@ end
-- transmit RPS data across the bus
---@param tripped boolean RPS tripped
----@param status table RPS status
+---@param status boolean[] RPS status
---@param emer_cool_active boolean RPS activated the emergency coolant
function databus.tx_rps(tripped, status, emer_cool_active)
databus.ps.publish("rps_scram", tripped)
diff --git a/reactor-plc/panel/front_panel.lua b/reactor-plc/panel/front_panel.lua
index d07395f..8bb6a0f 100644
--- a/reactor-plc/panel/front_panel.lua
+++ b/reactor-plc/panel/front_panel.lua
@@ -13,15 +13,15 @@ local style = require("reactor-plc.panel.style")
local core = require("graphics.core")
local flasher = require("graphics.flasher")
-local Div = require("graphics.elements.div")
-local Rectangle = require("graphics.elements.rectangle")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local Rectangle = require("graphics.elements.Rectangle")
+local TextBox = require("graphics.elements.TextBox")
-local PushButton = require("graphics.elements.controls.push_button")
+local PushButton = require("graphics.elements.controls.PushButton")
-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.RGBLED")
local LINK_STATE = types.PANEL_LINK_STATE
@@ -34,7 +34,7 @@ local ind_grn = style.ind_grn
local ind_red = style.ind_red
-- create new front panel view
----@param panel graphics_element main displaybox
+---@param panel DisplayBox main displaybox
local function init(panel)
local s_hi_box = style.theme.highlight_box
diff --git a/reactor-plc/plc.lua b/reactor-plc/plc.lua
index eee2bc6..73a1126 100644
--- a/reactor-plc/plc.lua
+++ b/reactor-plc/plc.lua
@@ -110,22 +110,8 @@ end
---@param reactor table
---@param is_formed boolean
function plc.rps_init(reactor, is_formed)
- local state_keys = {
- high_dmg = 1,
- high_temp = 2,
- low_coolant = 3,
- ex_waste = 4,
- ex_hcoolant = 5,
- no_fuel = 6,
- fault = 7,
- timeout = 8,
- manual = 9,
- automatic = 10,
- sys_fail = 11,
- force_disabled = 12
- }
-
local self = {
+ ---@type boolean[] check states
state = { false, false, false, false, false, false, false, false, false, false, false, false },
reactor_enabled = false,
enabled_at = 0,
@@ -136,12 +122,27 @@ function plc.rps_init(reactor, is_formed)
trip_cause = "ok" ---@type rps_trip_cause
}
+ local CHK = {
+ HIGH_DMG = 1,
+ HIGH_TEMP = 2,
+ LOW_COOLANT = 3,
+ EX_WASTE = 4,
+ EX_HCOOLANT = 5,
+ NO_FUEL = 6,
+ FAULT = 7,
+ TIMEOUT = 8,
+ MANUAL = 9,
+ AUTOMATIC = 10,
+ SYS_FAIL = 11,
+ FORCE_DISABLED = 12
+ }
+
-- PRIVATE FUNCTIONS --
-- set reactor access fault flag
local function _set_fault()
if reactor.__p_last_fault() ~= "Terminated" then
- self.state[state_keys.fault] = true
+ self.state[CHK.FAULT] = true
end
end
@@ -203,8 +204,8 @@ function plc.rps_init(reactor, is_formed)
end
-- always update, since some ppm failures constitute not being formed
- if not self.state[state_keys.sys_fail] then
- self.state[state_keys.sys_fail] = not self.formed
+ if not self.state[CHK.SYS_FAIL] then
+ self.state[CHK.SYS_FAIL] = not self.formed
end
end
@@ -214,8 +215,8 @@ function plc.rps_init(reactor, is_formed)
if _check_and_handle_ppm_call(disabled) then
self.force_disabled = disabled
- if not self.state[state_keys.force_disabled] then
- self.state[state_keys.force_disabled] = disabled
+ if not self.state[CHK.FORCE_DISABLED] then
+ self.state[CHK.FORCE_DISABLED] = disabled
end
end
end
@@ -223,8 +224,8 @@ function plc.rps_init(reactor, is_formed)
-- check for high damage
local function _high_damage()
local damage_percent = reactor.getDamagePercent()
- if _check_and_handle_ppm_call(damage_percent) and not self.state[state_keys.high_dmg] then
- self.state[state_keys.high_dmg] = damage_percent >= RPS_LIMITS.MAX_DAMAGE_PERCENT
+ if _check_and_handle_ppm_call(damage_percent) and not self.state[CHK.HIGH_DMG] then
+ self.state[CHK.HIGH_DMG] = damage_percent >= RPS_LIMITS.MAX_DAMAGE_PERCENT
end
end
@@ -232,40 +233,40 @@ function plc.rps_init(reactor, is_formed)
local function _high_temp()
-- mekanism: MAX_DAMAGE_TEMPERATURE = 1200K
local temp = reactor.getTemperature()
- if _check_and_handle_ppm_call(temp) and not self.state[state_keys.high_temp] then
- self.state[state_keys.high_temp] = temp >= RPS_LIMITS.MAX_DAMAGE_TEMPERATURE
+ if _check_and_handle_ppm_call(temp) and not self.state[CHK.HIGH_TEMP] then
+ self.state[CHK.HIGH_TEMP] = temp >= RPS_LIMITS.MAX_DAMAGE_TEMPERATURE
end
end
-- check if there is very low coolant
local function _low_coolant()
local coolant_filled = reactor.getCoolantFilledPercentage()
- if _check_and_handle_ppm_call(coolant_filled) and not self.state[state_keys.low_coolant] then
- self.state[state_keys.low_coolant] = coolant_filled < RPS_LIMITS.MIN_COOLANT_FILL
+ if _check_and_handle_ppm_call(coolant_filled) and not self.state[CHK.LOW_COOLANT] then
+ self.state[CHK.LOW_COOLANT] = coolant_filled < RPS_LIMITS.MIN_COOLANT_FILL
end
end
-- check for excess waste (>80% filled)
local function _excess_waste()
local w_filled = reactor.getWasteFilledPercentage()
- if _check_and_handle_ppm_call(w_filled) and not self.state[state_keys.ex_waste] then
- self.state[state_keys.ex_waste] = w_filled > RPS_LIMITS.MAX_WASTE_FILL
+ if _check_and_handle_ppm_call(w_filled) and not self.state[CHK.EX_WASTE] then
+ self.state[CHK.EX_WASTE] = w_filled > RPS_LIMITS.MAX_WASTE_FILL
end
end
-- check for heated coolant backup (>95% filled)
local function _excess_heated_coolant()
local hc_filled = reactor.getHeatedCoolantFilledPercentage()
- if _check_and_handle_ppm_call(hc_filled) and not self.state[state_keys.ex_hcoolant] then
- self.state[state_keys.ex_hcoolant] = hc_filled > RPS_LIMITS.MAX_HEATED_COLLANT_FILL
+ if _check_and_handle_ppm_call(hc_filled) and not self.state[CHK.EX_HCOOLANT] then
+ self.state[CHK.EX_HCOOLANT] = hc_filled > RPS_LIMITS.MAX_HEATED_COLLANT_FILL
end
end
-- check if there is no fuel
local function _insufficient_fuel()
local fuel = reactor.getFuelFilledPercentage()
- if _check_and_handle_ppm_call(fuel) and not self.state[state_keys.no_fuel] then
- self.state[state_keys.no_fuel] = fuel <= RPS_LIMITS.NO_FUEL_FILL
+ if _check_and_handle_ppm_call(fuel) and not self.state[CHK.NO_FUEL] then
+ self.state[CHK.NO_FUEL] = fuel <= RPS_LIMITS.NO_FUEL_FILL
end
end
@@ -287,23 +288,23 @@ function plc.rps_init(reactor, is_formed)
-- trip for a PLC comms timeout
function public.trip_timeout()
- self.state[state_keys.timeout] = true
+ self.state[CHK.TIMEOUT] = true
end
-- manually SCRAM the reactor
function public.trip_manual()
- self.state[state_keys.manual] = true
+ self.state[CHK.MANUAL] = true
end
-- automatic SCRAM commanded by supervisor
function public.trip_auto()
- self.state[state_keys.automatic] = true
+ self.state[CHK.AUTOMATIC] = true
end
-- trip for unformed reactor
function public.trip_sys_fail()
- self.state[state_keys.fault] = true
- self.state[state_keys.sys_fail] = true
+ self.state[CHK.FAULT] = true
+ self.state[CHK.SYS_FAIL] = true
end
-- SCRAM the reactor now
@@ -350,7 +351,7 @@ function plc.rps_init(reactor, is_formed)
function public.auto_activate()
-- clear automatic SCRAM if it was the cause
if self.tripped and self.trip_cause == "automatic" then
- self.state[state_keys.automatic] = true
+ self.state[CHK.AUTOMATIC] = true
self.trip_cause = RPS_TRIP_CAUSE.OK
self.tripped = false
@@ -388,40 +389,40 @@ function plc.rps_init(reactor, is_formed)
-- check system states in order of severity
if self.tripped then
status = self.trip_cause
- elseif self.state[state_keys.sys_fail] then
+ elseif self.state[CHK.SYS_FAIL] then
log.warning("RPS: system failure, reactor not formed")
status = RPS_TRIP_CAUSE.SYS_FAIL
- elseif self.state[state_keys.force_disabled] then
+ elseif self.state[CHK.FORCE_DISABLED] then
log.warning("RPS: reactor was force disabled")
status = RPS_TRIP_CAUSE.FORCE_DISABLED
- elseif self.state[state_keys.high_dmg] then
+ elseif self.state[CHK.HIGH_DMG] then
log.warning("RPS: high damage")
status = RPS_TRIP_CAUSE.HIGH_DMG
- elseif self.state[state_keys.high_temp] then
+ elseif self.state[CHK.HIGH_TEMP] then
log.warning("RPS: high temperature")
status = RPS_TRIP_CAUSE.HIGH_TEMP
- elseif self.state[state_keys.low_coolant] then
+ elseif self.state[CHK.LOW_COOLANT] then
log.warning("RPS: low coolant")
status = RPS_TRIP_CAUSE.LOW_COOLANT
- elseif self.state[state_keys.ex_waste] then
+ elseif self.state[CHK.EX_WASTE] then
log.warning("RPS: full waste")
status = RPS_TRIP_CAUSE.EX_WASTE
- elseif self.state[state_keys.ex_hcoolant] then
+ elseif self.state[CHK.EX_HCOOLANT] then
log.warning("RPS: heated coolant backup")
status = RPS_TRIP_CAUSE.EX_HCOOLANT
- elseif self.state[state_keys.no_fuel] then
+ elseif self.state[CHK.NO_FUEL] then
log.warning("RPS: no fuel")
status = RPS_TRIP_CAUSE.NO_FUEL
- elseif self.state[state_keys.fault] then
+ elseif self.state[CHK.FAULT] then
log.warning("RPS: reactor access fault")
status = RPS_TRIP_CAUSE.FAULT
- elseif self.state[state_keys.timeout] then
+ elseif self.state[CHK.TIMEOUT] then
log.warning("RPS: supervisor connection timeout")
status = RPS_TRIP_CAUSE.TIMEOUT
- elseif self.state[state_keys.manual] then
+ elseif self.state[CHK.MANUAL] then
log.warning("RPS: manual SCRAM requested")
status = RPS_TRIP_CAUSE.MANUAL
- elseif self.state[state_keys.automatic] then
+ elseif self.state[CHK.AUTOMATIC] then
log.warning("RPS: automatic SCRAM requested")
status = RPS_TRIP_CAUSE.AUTOMATIC
else
@@ -449,7 +450,7 @@ function plc.rps_init(reactor, is_formed)
end
-- update emergency coolant control if configured
- _set_emer_cool(self.state[state_keys.low_coolant])
+ _set_emer_cool(self.state[CHK.LOW_COOLANT])
-- report RPS status
databus.tx_rps(self.tripped, self.state, self.emer_cool_active)
@@ -465,7 +466,7 @@ function plc.rps_init(reactor, is_formed)
---@nodiscard
function public.get_trip_cause() return self.trip_cause end
---@nodiscard
- function public.is_low_coolant() return self.states[state_keys.low_coolant] end
+ function public.is_low_coolant() return self.states[CHK.LOW_COOLANT] end
---@nodiscard
function public.is_active() return self.reactor_enabled end
@@ -495,16 +496,16 @@ function plc.rps_init(reactor, is_formed)
self.tripped = false
self.trip_cause = RPS_TRIP_CAUSE.OK
- self.state[state_keys.fault] = false
- self.state[state_keys.sys_fail] = false
+ self.state[CHK.FAULT] = false
+ self.state[CHK.SYS_FAIL] = false
log.info("RPS: partial reset on formed")
end
-- reset the automatic and timeout trip flags, then clear trip if that was the trip cause
function public.auto_reset()
- self.state[state_keys.automatic] = false
- self.state[state_keys.timeout] = false
+ self.state[CHK.AUTOMATIC] = false
+ self.state[CHK.TIMEOUT] = false
if self.trip_cause == RPS_TRIP_CAUSE.AUTOMATIC or self.trip_cause == RPS_TRIP_CAUSE.TIMEOUT then
self.trip_cause = RPS_TRIP_CAUSE.OK
diff --git a/reactor-plc/renderer.lua b/reactor-plc/renderer.lua
index aa62e63..f8a8044 100644
--- a/reactor-plc/renderer.lua
+++ b/reactor-plc/renderer.lua
@@ -8,7 +8,7 @@ local style = require("reactor-plc.panel.style")
local core = require("graphics.core")
local flasher = require("graphics.flasher")
-local DisplayBox = require("graphics.elements.displaybox")
+local DisplayBox = require("graphics.elements.DisplayBox")
---@class reactor_plc_renderer
local renderer = {}
diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua
index cb40ead..61af7cc 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.8"
+local R_PLC_VERSION = "v1.8.9"
local println = util.println
local println_ts = util.println_ts
diff --git a/reactor-plc/threads.lua b/reactor-plc/threads.lua
index b3a0251..b56ccc7 100644
--- a/reactor-plc/threads.lua
+++ b/reactor-plc/threads.lua
@@ -144,6 +144,7 @@ function threads.thread__main(smem, init)
plc_state.no_reactor = true
plc_state.degraded = true
elseif networked and type == "modem" then
+ ---@cast device Modem
-- we only care if this is our wireless modem
-- note, check init_ok first since nic will be nil if it is false
if plc_state.init_ok and nic.is_modem(device) then
@@ -208,6 +209,7 @@ function threads.thread__main(smem, init)
rps.reset_formed()
end
elseif networked and type == "modem" then
+ ---@cast device Modem
-- note, check init_ok first since nic will be nil if it is false
if device.isWireless() and not (plc_state.init_ok and nic.is_connected()) then
-- reconnected modem
@@ -628,9 +630,10 @@ function threads.thread__setpoint_control(smem)
local reactor = plc_dev.reactor
if plc_state.init_ok and (not plc_state.no_reactor) then
+ ---@cast reactor table won't be nil
+
-- check if we should start ramping
if setpoints.burn_rate_en and (setpoints.burn_rate ~= last_burn_sp) then
----@diagnostic disable-next-line: need-check-nil
local cur_burn_rate = reactor.getBurnRate()
if (type(cur_burn_rate) == "number") and (setpoints.burn_rate ~= cur_burn_rate) and rps.is_active() then
@@ -644,7 +647,6 @@ function threads.thread__setpoint_control(smem)
log.debug(util.c("SPCTL: starting burn rate ramp from ", cur_burn_rate, " mB/t to ", setpoints.burn_rate, " mB/t"))
else
log.debug(util.c("SPCTL: setting burn rate directly to ", setpoints.burn_rate, " mB/t"))
----@diagnostic disable-next-line: need-check-nil
reactor.setBurnRate(setpoints.burn_rate)
end
end
@@ -658,7 +660,6 @@ function threads.thread__setpoint_control(smem)
-- adjust burn rate (setpoints.burn_rate)
if setpoints.burn_rate_en then
if rps.is_active() then
----@diagnostic disable-next-line: need-check-nil
local current_burn_rate = reactor.getBurnRate()
-- we yielded, check enable again
@@ -679,7 +680,6 @@ function threads.thread__setpoint_control(smem)
running = running or (new_burn_rate ~= setpoints.burn_rate)
-- set the burn rate
----@diagnostic disable-next-line: need-check-nil
reactor.setBurnRate(new_burn_rate)
end
else
diff --git a/rtu/configure.lua b/rtu/configure.lua
index 0c571de..c0d45a5 100644
--- a/rtu/configure.lua
+++ b/rtu/configure.lua
@@ -12,21 +12,21 @@ local util = require("scada-common.util")
local core = require("graphics.core")
local themes = require("graphics.themes")
-local DisplayBox = require("graphics.elements.displaybox")
-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 DisplayBox = require("graphics.elements.DisplayBox")
+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.push_button")
-local Radio2D = require("graphics.elements.controls.radio_2d")
-local RadioButton = require("graphics.elements.controls.radio_button")
+local Checkbox = require("graphics.elements.controls.Checkbox")
+local PushButton = require("graphics.elements.controls.PushButton")
+local Radio2D = require("graphics.elements.controls.Radio2D")
+local RadioButton = require("graphics.elements.controls.RadioButton")
-local NumberField = require("graphics.elements.form.number_field")
-local TextField = require("graphics.elements.form.text_field")
+local NumberField = require("graphics.elements.form.NumberField")
+local TextField = require("graphics.elements.form.TextField")
-local IndLight = require("graphics.elements.indicators.light")
+local IndLight = require("graphics.elements.indicators.IndicatorLight")
local println = util.println
local tri = util.trinary
@@ -88,17 +88,17 @@ local changes = {
{ "v1.10.2", { "Re-organized peripheral configuration UI, resulting in some input fields being re-ordered" } }
}
+---@class rtu_peri_definition
+---@field unit integer|nil
+---@field index integer|nil
+---@field name string
+
---@class rtu_rs_definition
---@field unit integer|nil
---@field port IO_PORT
---@field side side
---@field color color|nil
----@class rtu_peri_definition
----@field unit integer|nil
----@field index integer|nil
----@field name string
-
local RTU_DEV_TYPES = { "boilerValve", "turbineValve", "dynamicValve", "inductionPort", "spsPort", "solarNeutronActivator", "environmentDetector" }
local NEEDS_UNIT = { "boilerValve", "turbineValve", "dynamicValve", "solarNeutronActivator", "environmentDetector" }
@@ -130,14 +130,14 @@ local tool_ctl = {
rs_cfg_port = IO.F_SCRAM, ---@type IO_PORT
rs_cfg_editing = false, ---@type integer|false
- view_gw_cfg = nil, ---@type graphics_element
- dev_cfg = nil, ---@type graphics_element
- rs_cfg = nil, ---@type graphics_element
- color_cfg = nil, ---@type graphics_element
- color_next = nil, ---@type graphics_element
- color_apply = nil, ---@type graphics_element
- settings_apply = nil, ---@type graphics_element
- settings_confirm = nil, ---@type graphics_element
+ view_gw_cfg = nil, ---@type PushButton
+ dev_cfg = nil, ---@type PushButton
+ rs_cfg = nil, ---@type PushButton
+ color_cfg = nil, ---@type PushButton
+ color_next = nil, ---@type PushButton
+ color_apply = nil, ---@type PushButton
+ settings_apply = nil, ---@type PushButton
+ settings_confirm = nil, ---@type PushButton
go_home = nil, ---@type function
gen_summary = nil, ---@type function
@@ -149,33 +149,33 @@ local tool_ctl = {
gen_rs_summary = nil, ---@type function
show_auth_key = nil, ---@type function
- show_key_btn = nil, ---@type graphics_element
- auth_key_textbox = nil, ---@type graphics_element
+ show_key_btn = nil, ---@type PushButton
+ auth_key_textbox = nil, ---@type TextBox
auth_key_value = "",
- ppm_devs = nil, ---@type graphics_element
- p_name_msg = nil, ---@type graphics_element
- p_prompt = nil, ---@type graphics_element
- p_idx = nil, ---@type graphics_element
- p_unit = nil, ---@type graphics_element
- p_assign_btn = nil, ---@type graphics_element
- p_desc = nil, ---@type graphics_element
- p_desc_ext = nil, ---@type graphics_element
- p_err = nil, ---@type graphics_element
+ ppm_devs = nil, ---@type ListBox
+ p_name_msg = nil, ---@type TextBox
+ p_prompt = nil, ---@type TextBox
+ p_idx = nil, ---@type NumberField
+ p_unit = nil, ---@type NumberField
+ p_assign_btn = nil, ---@type RadioButton
+ p_desc = nil, ---@type TextBox
+ p_desc_ext = nil, ---@type TextBox
+ p_err = nil, ---@type TextBox
- rs_cfg_selection = nil, ---@type graphics_element
- rs_cfg_unit_l = nil, ---@type graphics_element
- rs_cfg_unit = nil, ---@type graphics_element
- rs_cfg_side_l = nil, ---@type graphics_element
- rs_cfg_color = nil, ---@type graphics_element
- rs_cfg_shortcut = nil ---@type graphics_element
+ rs_cfg_selection = nil, ---@type TextBox
+ rs_cfg_unit_l = nil, ---@type TextBox
+ rs_cfg_unit = nil, ---@type NumberField
+ rs_cfg_side_l = nil, ---@type TextBox
+ rs_cfg_color = nil, ---@type Radio2D
+ rs_cfg_shortcut = nil ---@type TextBox
}
---@class rtu_config
local tmp_cfg = {
SpeakerVolume = 1.0,
- Peripherals = {},
- Redstone = {},
+ Peripherals = {}, ---@type rtu_peri_definition[]
+ Redstone = {}, ---@type rtu_rs_definition[]
SVR_Channel = nil, ---@type integer
RTU_Channel = nil, ---@type integer
ConnTimeout = nil, ---@type number
@@ -259,7 +259,7 @@ local function load_settings(target, raw)
end
-- create the config view
----@param display graphics_element
+---@param display DisplayBox
local function config_view(display)
---@diagnostic disable-next-line: undefined-field
local function exit() os.queueEvent("terminate") end
@@ -446,11 +446,11 @@ local function config_view(display)
TextBox{parent=net_c_3,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra compution (can slow things down).",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_3,x=1,y=11,text="Facility Auth Key"}
- local key, _, censor = TextField{parent=net_c_3,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg}
+ local key, _ = TextField{parent=net_c_3,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg}
- local function censor_key(enable) censor(tri(enable, "*", nil)) end
+ local function censor_key(enable) key.censor(tri(enable, "*", nil)) end
- local hide_key = CheckBox{parent=net_c_3,x=34,y=12,label="Hide",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key}
+ local hide_key = Checkbox{parent=net_c_3,x=34,y=12,label="Hide",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key}
hide_key.set_value(true)
censor_key(true)
@@ -485,7 +485,7 @@ local function config_view(display)
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=49,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 Logging Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)}
+ local en_dbg = Checkbox{parent=log_c_1,x=1,y=10,default=ini_cfg.LogDebug,label="Enable Logging Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)}
TextBox{parent=log_c_1,x=3,y=11,height=2,text="This results in much larger log files. It is best to only use this when there is a problem.",fg_bg=g_lg_fg_bg}
local path_err = TextBox{parent=log_c_1,x=8,y=14,width=35,text="Please provide a log file path.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
@@ -1198,7 +1198,7 @@ local function config_view(display)
tool_ctl.rs_cfg_shortcut = TextBox{parent=rs_c_3,x=1,y=9,height=4,text="This shortcut will add entries for each of the 4 waste outputs. If you select bundled, 4 colors will be assigned to the selected side. Otherwise, 4 default sides will be used."}
tool_ctl.rs_cfg_shortcut.hide(true)
- local bundled = CheckBox{parent=rs_c_3,x=1,y=7,label="Is Bundled?",default=false,box_fg_bg=cpair(colors.red,colors.black),callback=set_bundled}
+ local bundled = Checkbox{parent=rs_c_3,x=1,y=7,label="Is Bundled?",default=false,box_fg_bg=cpair(colors.red,colors.black),callback=set_bundled}
tool_ctl.rs_cfg_color = Radio2D{parent=rs_c_3,x=1,y=9,rows=4,columns=4,default=1,options=color_options,radio_colors=cpair(colors.lightGray,colors.black),color_map=color_options_map,disable_color=colors.gray,disable_fg_bg=g_lg_fg_bg}
tool_ctl.rs_cfg_color.disable()
@@ -1296,7 +1296,7 @@ local function config_view(display)
local ini_unit = tri(for_facility, nil, entry.for_reactor)
local def = { name = entry.name, unit = ini_unit, index = entry.index }
- local mount = mounts[def.name] ---@type ppm_entry|nil
+ local mount = mounts[def.name]
local status = " \x13 not connected, please re-config later"
local color = colors.orange
@@ -1497,7 +1497,7 @@ local function config_view(display)
peri_list.remove_all()
for i = 1, #cfg.Peripherals do
- local def = cfg.Peripherals[i] ---@type rtu_peri_definition
+ local def = cfg.Peripherals[i]
local t = ppm.get_type(def.name)
local t_str = " (connect to edit)"
@@ -1529,7 +1529,7 @@ local function config_view(display)
end
local function edit_rs_entry(idx)
- local def = tmp_cfg.Redstone[idx] ---@type rtu_rs_definition
+ local def = tmp_cfg.Redstone[idx]
tool_ctl.rs_cfg_shortcut.hide(true)
tool_ctl.rs_cfg_color.show()
diff --git a/rtu/databus.lua b/rtu/databus.lua
index 4fe183a..0d086f4 100644
--- a/rtu/databus.lua
+++ b/rtu/databus.lua
@@ -10,15 +10,15 @@ local databus = {}
-- databus PSIL
databus.ps = psil.create()
----@enum RTU_UNIT_HW_STATE
-local RTU_UNIT_HW_STATE = {
+---@enum RTU_HW_STATE
+local RTU_HW_STATE = {
OFFLINE = 1,
FAULTED = 2,
UNFORMED = 3,
OK = 4
}
-databus.RTU_UNIT_HW_STATE = RTU_UNIT_HW_STATE
+databus.RTU_HW_STATE = RTU_HW_STATE
-- call to toggle heartbeat signal
function databus.heartbeat() databus.ps.toggle("heartbeat") end
@@ -52,7 +52,7 @@ end
-- transmit unit hardware status across the bus
---@param uid integer unit ID
----@param status RTU_UNIT_HW_STATE
+---@param status RTU_HW_STATE
function databus.tx_unit_hw_status(uid, status)
databus.ps.publish("unit_hw_" .. uid, status)
end
diff --git a/rtu/panel/front_panel.lua b/rtu/panel/front_panel.lua
index b5b773a..6fc40e5 100644
--- a/rtu/panel/front_panel.lua
+++ b/rtu/panel/front_panel.lua
@@ -11,13 +11,13 @@ local style = require("rtu.panel.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local TextBox = require("graphics.elements.TextBox")
-local DataIndicator = require("graphics.elements.indicators.data")
-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.DataIndicator")
+local LED = require("graphics.elements.indicators.LED")
+local LEDPair = require("graphics.elements.indicators.LEDPair")
+local RGBLED = require("graphics.elements.indicators.RGBLED")
local LINK_STATE = types.PANEL_LINK_STATE
@@ -30,8 +30,8 @@ local ind_grn = style.ind_grn
local UNIT_TYPE_LABELS = { "UNKNOWN", "REDSTONE", "BOILER", "TURBINE", "DYNAMIC TANK", "IND MATRIX", "SPS", "SNA", "ENV DETECTOR" }
-- create new front panel view
----@param panel graphics_element main displaybox
----@param units table unit list
+---@param panel DisplayBox main displaybox
+---@param units rtu_registry_entry[] unit list
local function init(panel, units)
local disabled_fg = style.fp.disabled_fg
@@ -135,7 +135,7 @@ local function init(panel, units)
-- show hardware statuses
for i = 1, list_length do
- local unit = units[i] ---@type rtu_unit_registry_entry
+ local unit = units[i]
-- hardware status
local unit_hw = RGBLED{parent=unit_hw_statuses,y=i,label="",colors={colors.red,colors.orange,colors.yellow,colors.green}}
diff --git a/rtu/renderer.lua b/rtu/renderer.lua
index bdbc25b..dd86a06 100644
--- a/rtu/renderer.lua
+++ b/rtu/renderer.lua
@@ -8,7 +8,7 @@ local style = require("rtu.panel.style")
local core = require("graphics.core")
local flasher = require("graphics.flasher")
-local DisplayBox = require("graphics.elements.displaybox")
+local DisplayBox = require("graphics.elements.DisplayBox")
---@class rtu_renderer
local renderer = {}
@@ -18,7 +18,7 @@ local ui = {
}
-- try to start the UI
----@param units table RTU units
+---@param units rtu_registry_entry[] RTU entries
---@param theme FP_THEME front panel theme
---@param color_mode COLOR_MODE color mode
---@return boolean success, any error_msg
diff --git a/rtu/rtu.lua b/rtu/rtu.lua
index dc398b2..0ea1779 100644
--- a/rtu/rtu.lua
+++ b/rtu/rtu.lua
@@ -235,7 +235,7 @@ function rtu.init_unit(device)
end
-- create an alarm speaker sounder
----@param speaker table device peripheral
+---@param speaker Speaker device peripheral
function rtu.init_sounder(speaker)
---@class rtu_speaker_sounder
local spkr_ctl = {
@@ -322,13 +322,13 @@ function rtu.comms(version, nic, conn_watchdog)
-- generate device advertisement table
---@nodiscard
- ---@param units table
+ ---@param units rtu_registry_entry[]
---@return table advertisement
local function _generate_advertisement(units)
local advertisement = {}
for i = 1, #units do
- local unit = units[i] ---@type rtu_unit_registry_entry
+ local unit = units[i]
if unit.type ~= nil then
local advert = { unit.type, unit.index, unit.reactor }
@@ -429,9 +429,9 @@ function rtu.comms(version, nic, conn_watchdog)
-- handle a MODBUS/SCADA packet
---@param packet modbus_frame|mgmt_frame
- ---@param units table RTU units
+ ---@param units rtu_registry_entry[] RTU entries
---@param rtu_state rtu_state
- ---@param sounders table speaker alarm sounders
+ ---@param sounders rtu_speaker_sounder[] speaker alarm sounders
function public.handle_packet(packet, units, rtu_state, sounders)
-- print a log message to the terminal as long as the UI isn't running
local function println_ts(message) if not rtu_state.fp_ok then util.println_ts(message) end end
@@ -467,7 +467,7 @@ function rtu.comms(version, nic, conn_watchdog)
-- handle MODBUS instruction
if packet.unit_id <= #units then
- local unit = units[packet.unit_id] ---@type rtu_unit_registry_entry
+ local unit = units[packet.unit_id]
local unit_dbg_tag = " (unit " .. packet.unit_id .. ")"
if unit.name == "redstone_io" then
@@ -538,11 +538,9 @@ function rtu.comms(version, nic, conn_watchdog)
if (packet.length == 1) and type(packet.data[1] == "table") and (#packet.data[1] == 8) then
local states = packet.data[1]
+ -- set tone states
for i = 1, #sounders do
- local s = sounders[i] ---@type rtu_speaker_sounder
-
- -- set tone states
- for id = 1, #states do s.stream.set_active(id, states[id] == true) end
+ for id = 1, #states do sounders[i].stream.set_active(id, states[id] == true) end
end
end
else
diff --git a/rtu/startup.lua b/rtu/startup.lua
index cb0d4ea..7a30f42 100644
--- a/rtu/startup.lua
+++ b/rtu/startup.lua
@@ -31,10 +31,10 @@ 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.8"
+local RTU_VERSION = "v1.10.9"
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
-local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE
+local RTU_HW_STATE = databus.RTU_HW_STATE
local println = util.println
local println_ts = util.println_ts
@@ -109,7 +109,7 @@ local function main()
-- RTU gateway devices (not RTU units)
rtu_dev = {
modem = ppm.get_wireless_modem(),
- sounders = {}
+ sounders = {} ---@type rtu_speaker_sounder[]
},
-- system objects
@@ -117,7 +117,7 @@ local function main()
nic = nil, ---@type nic
rtu_comms = nil, ---@type rtu_comms
conn_watchdog = nil, ---@type watchdog
- units = {}
+ units = {} ---@type rtu_registry_entry[]
},
-- message queues
@@ -143,11 +143,11 @@ local function main()
-- configure RTU gateway based on settings file definitions
local function sys_config()
-- redstone interfaces
- local rs_rtus = {}
+ local rs_rtus = {} ---@type { rtu: rtu_rs_device, capabilities: IO_PORT[] }[]
-- go through redstone definitions list
for entry_idx = 1, #rtu_redstone do
- local entry = rtu_redstone[entry_idx] ---@type rtu_rs_definition
+ local entry = rtu_redstone[entry_idx]
local assignment
local for_reactor = entry.unit
local iface_name = util.trinary(entry.color ~= nil, util.c(entry.side, "/", rsio.color_name(entry.color)), entry.side)
@@ -227,21 +227,21 @@ local function main()
-- create unit entries for redstone RTUs
for for_reactor, def in pairs(rs_rtus) do
- ---@class rtu_unit_registry_entry
+ ---@class rtu_registry_entry
local unit = {
- uid = 0, ---@type integer
- name = "redstone_io", ---@type string
- type = RTU_UNIT_TYPE.REDSTONE, ---@type RTU_UNIT_TYPE
- index = false, ---@type integer|false
- reactor = for_reactor, ---@type integer
- device = def.capabilities, ---@type table use device field for redstone ports
- is_multiblock = false, ---@type boolean
- formed = nil, ---@type boolean|nil
- hw_state = RTU_UNIT_HW_STATE.OK, ---@type RTU_UNIT_HW_STATE
- rtu = def.rtu, ---@type rtu_device|rtu_rs_device
+ uid = 0, ---@type integer
+ name = "redstone_io", ---@type string
+ type = RTU_UNIT_TYPE.REDSTONE, ---@type RTU_UNIT_TYPE
+ index = false, ---@type integer|false
+ reactor = for_reactor, ---@type integer
+ device = def.capabilities, ---@type IO_PORT[] use device field for redstone ports
+ is_multiblock = false, ---@type boolean
+ formed = nil, ---@type boolean|nil
+ hw_state = RTU_HW_STATE.OK, ---@type RTU_HW_STATE
+ rtu = def.rtu, ---@type rtu_device|rtu_rs_device
modbus_io = modbus.new(def.rtu, false),
- pkt_queue = nil, ---@type mqueue|nil
- thread = nil ---@type parallel_thread|nil
+ pkt_queue = nil, ---@type mqueue|nil
+ thread = nil ---@type parallel_thread|nil
}
table.insert(units, unit)
@@ -440,21 +440,21 @@ local function main()
end
end
- ---@class rtu_unit_registry_entry
+ ---@class rtu_registry_entry
local rtu_unit = {
- uid = 0, ---@type integer
- name = name, ---@type string
- type = rtu_type, ---@type RTU_UNIT_TYPE
- index = index or false, ---@type integer|false
- reactor = for_reactor, ---@type integer
- device = device, ---@type table
- is_multiblock = is_multiblock, ---@type boolean
- formed = formed, ---@type boolean|nil
- hw_state = RTU_UNIT_HW_STATE.OFFLINE, ---@type RTU_UNIT_HW_STATE
- rtu = rtu_iface, ---@type rtu_device|rtu_rs_device
+ uid = 0, ---@type integer
+ name = name, ---@type string
+ type = rtu_type, ---@type RTU_UNIT_TYPE
+ index = index or false, ---@type integer|false
+ reactor = for_reactor, ---@type integer
+ device = device, ---@type table peripheral reference
+ is_multiblock = is_multiblock, ---@type boolean
+ formed = formed, ---@type boolean|nil
+ hw_state = RTU_HW_STATE.OFFLINE, ---@type RTU_HW_STATE
+ rtu = rtu_iface, ---@type rtu_device|rtu_rs_device
modbus_io = modbus.new(rtu_iface, true),
- pkt_queue = mqueue.new(), ---@type mqueue|nil
- thread = nil ---@type parallel_thread|nil
+ pkt_queue = mqueue.new(), ---@type mqueue|nil
+ thread = nil ---@type parallel_thread|nil
}
rtu_unit.thread = threads.thread__unit_comms(__shared_memory, rtu_unit)
@@ -473,14 +473,14 @@ local function main()
-- determine hardware status
if rtu_unit.type == RTU_UNIT_TYPE.VIRTUAL then
- rtu_unit.hw_state = RTU_UNIT_HW_STATE.OFFLINE
+ rtu_unit.hw_state = RTU_HW_STATE.OFFLINE
else
if rtu_unit.is_multiblock then
- rtu_unit.hw_state = util.trinary(rtu_unit.formed == true, RTU_UNIT_HW_STATE.OK, RTU_UNIT_HW_STATE.UNFORMED)
+ rtu_unit.hw_state = util.trinary(rtu_unit.formed == true, RTU_HW_STATE.OK, RTU_HW_STATE.UNFORMED)
elseif faulted then
- rtu_unit.hw_state = RTU_UNIT_HW_STATE.FAULTED
+ rtu_unit.hw_state = RTU_HW_STATE.FAULTED
else
- rtu_unit.hw_state = RTU_UNIT_HW_STATE.OK
+ rtu_unit.hw_state = RTU_HW_STATE.OK
end
end
diff --git a/rtu/threads.lua b/rtu/threads.lua
index 011b617..4ad5fcb 100644
--- a/rtu/threads.lua
+++ b/rtu/threads.lua
@@ -23,7 +23,7 @@ local core = require("graphics.core")
local threads = {}
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
-local UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE
+local RTU_HW_STATE = databus.RTU_HW_STATE
local MAIN_CLOCK = 0.5 -- (2Hz, 10 ticks)
local COMMS_SLEEP = 100 -- (100ms, 2 ticks)
@@ -33,7 +33,7 @@ local COMMS_SLEEP = 100 -- (100ms, 2 ticks)
---@param iface string
---@param type string
---@param device table
----@param unit rtu_unit_registry_entry
+---@param unit rtu_registry_entry
local function handle_unit_mount(smem, println_ts, iface, type, device, unit)
local sys = smem.rtu_sys
@@ -106,7 +106,7 @@ local function handle_unit_mount(smem, println_ts, iface, type, device, unit)
-- if disconnected on startup, config wouldn't have been validated
-- checking now that it has connected; the config isn't valid, so don't connect it
if invalid then
- unit.hw_state = UNIT_HW_STATE.OFFLINE
+ unit.hw_state = RTU_HW_STATE.OFFLINE
databus.tx_unit_hw_status(unit.uid, unit.hw_state)
return
end
@@ -138,16 +138,16 @@ local function handle_unit_mount(smem, println_ts, iface, type, device, unit)
end
if unit.is_multiblock then
- unit.hw_state = UNIT_HW_STATE.UNFORMED
+ unit.hw_state = RTU_HW_STATE.UNFORMED
if unit.formed == false then
log.info(util.c("assuming ", unit.name, " is not formed due to PPM faults while initializing"))
end
elseif faulted then
- unit.hw_state = UNIT_HW_STATE.FAULTED
+ unit.hw_state = RTU_HW_STATE.FAULTED
elseif not unknown then
- unit.hw_state = UNIT_HW_STATE.OK
+ unit.hw_state = RTU_HW_STATE.OK
else
- unit.hw_state = UNIT_HW_STATE.OFFLINE
+ unit.hw_state = RTU_HW_STATE.OFFLINE
end
databus.tx_unit_hw_status(unit.uid, unit.hw_state)
@@ -245,6 +245,7 @@ function threads.thread__main(smem)
if type ~= nil and device ~= nil then
if type == "modem" then
+ ---@cast device Modem
-- we only care if this is our wireless modem
if nic.is_modem(device) then
nic.disconnect()
@@ -263,6 +264,7 @@ function threads.thread__main(smem)
log.warning("non-comms modem disconnected")
end
elseif type == "speaker" then
+ ---@cast device Speaker
for i = 1, #sounders do
if sounders[i].speaker == device then
table.remove(sounders, i)
@@ -279,13 +281,13 @@ function threads.thread__main(smem)
-- find disconnected device
if units[i].device == device then
-- will let the PPM prevent crashes, which will indicate failures in MODBUS queries
- local unit = units[i] ---@type rtu_unit_registry_entry
+ local unit = units[i]
local type_name = types.rtu_type_to_string(unit.type)
println_ts(util.c("lost the ", type_name, " on interface ", unit.name))
log.warning(util.c("lost the ", type_name, " unit peripheral on interface ", unit.name))
- unit.hw_state = UNIT_HW_STATE.OFFLINE
+ unit.hw_state = RTU_HW_STATE.OFFLINE
databus.tx_unit_hw_status(unit.uid, unit.hw_state)
break
end
@@ -298,6 +300,7 @@ function threads.thread__main(smem)
if type ~= nil and device ~= nil then
if type == "modem" then
+ ---@cast device Modem
if device.isWireless() and not nic.is_connected() then
-- reconnected modem
nic.connect(device)
@@ -312,6 +315,7 @@ function threads.thread__main(smem)
log.info("wired modem reconnected")
end
elseif type == "speaker" then
+ ---@cast device Speaker
table.insert(sounders, rtu.init_sounder(device))
println_ts("speaker connected")
@@ -332,7 +336,7 @@ function threads.thread__main(smem)
elseif event == "speaker_audio_empty" then
-- handle empty speaker audio buffer
for i = 1, #sounders do
- local sounder = sounders[i] ---@type rtu_speaker_sounder
+ local sounder = sounders[i]
if sounder.name == param1 then
sounder.continue()
break
@@ -460,7 +464,7 @@ end
-- per-unit communications handler thread
---@nodiscard
---@param smem rtu_shared_memory
----@param unit rtu_unit_registry_entry
+---@param unit rtu_registry_entry
function threads.thread__unit_comms(smem, unit)
---@class parallel_thread
local public = {}
@@ -523,13 +527,13 @@ function threads.thread__unit_comms(smem, unit)
if unit.formed == nil then
unit.formed = is_formed
- if is_formed then unit.hw_state = UNIT_HW_STATE.OK end
+ if is_formed then unit.hw_state = RTU_HW_STATE.OK end
elseif not unit.formed then
- unit.hw_state = UNIT_HW_STATE.UNFORMED
+ unit.hw_state = RTU_HW_STATE.UNFORMED
end
if (is_formed == true) and not unit.formed then
- unit.hw_state = UNIT_HW_STATE.OK
+ unit.hw_state = RTU_HW_STATE.OK
log.info(util.c(detail_name, " is now formed"))
rtu_comms.send_remounted(unit.uid)
elseif (is_formed == false) and unit.formed then
@@ -541,9 +545,9 @@ function threads.thread__unit_comms(smem, unit)
-- check hardware status
if unit.device.__p_is_healthy() then
- if unit.hw_state == UNIT_HW_STATE.FAULTED then unit.hw_state = UNIT_HW_STATE.OK end
+ if unit.hw_state == RTU_HW_STATE.FAULTED then unit.hw_state = RTU_HW_STATE.OK end
else
- if unit.hw_state == UNIT_HW_STATE.OK then unit.hw_state = UNIT_HW_STATE.FAULTED end
+ if unit.hw_state == RTU_HW_STATE.OK then unit.hw_state = RTU_HW_STATE.FAULTED end
end
-- update hw status
diff --git a/scada-common/audio.lua b/scada-common/audio.lua
index 019b510..e1a6958 100644
--- a/scada-common/audio.lua
+++ b/scada-common/audio.lua
@@ -6,10 +6,10 @@
-- note: max samples = 0x20000 (128 * 1024 samples)
-local _2_PI = 2 * math.pi -- 2 whole pies, hope you're hungry
-local _DRATE = 48000 -- 48kHz audio
-local _MAX_VAL = 127 / 2 -- max signed integer in this 8-bit audio
-local _05s_SAMPLES = 24000 -- half a second worth of samples
+local _2_PI = 2 * math.pi -- 2 whole pies, hope you're hungry
+local _DRATE = 48000 -- 48kHz audio data rate
+local _MAX_VAL = 127 / 2 -- max signed integer in this 8-bit audio
+local _05s_SAMPLES = 24000 -- half a second worth of samples
---@class audio
local audio = {}
@@ -28,6 +28,7 @@ local TONE = {
audio.TONE = TONE
+---@type integer[][][]
local tone_data = {
{ {}, {}, {}, {} }, -- 340Hz @ 2Hz Intermittent
{ {}, {}, {}, {} }, -- 544Hz 100mS / 440Hz 400mS Alternating
@@ -214,7 +215,14 @@ end
-- generate all 8 tone sequences
function audio.generate_tones()
- gen_tone_1(); gen_tone_2(); gen_tone_3(); gen_tone_4(); gen_tone_5(); gen_tone_6(); gen_tone_7(); gen_tone_8()
+ gen_tone_1()
+ gen_tone_2()
+ gen_tone_3()
+ gen_tone_4()
+ gen_tone_5()
+ gen_tone_6()
+ gen_tone_7()
+ gen_tone_8()
end
-- hard audio limiter
@@ -226,7 +234,7 @@ local function limit(output)
end
-- clear output buffer
----@param buffer table quad buffer
+---@param buffer integer[][] quad buffer
local function clear(buffer)
for i = 1, 4 do
for s = 1, _05s_SAMPLES do buffer[i][s] = 0 end
@@ -239,7 +247,7 @@ function audio.new_stream()
any_active = false,
need_recompute = false,
next_block = 1,
- -- split audio up into 0.5s samples, so specific components can be ended quicker
+ ---@type integer[][] split audio up into 0.5s samples, so specific components can be ended quicker
quad_buffer = { {}, {}, {}, {} },
-- all tone enable states
tone_active = { false, false, false, false, false, false, false, false }
@@ -263,14 +271,17 @@ function audio.new_stream()
-- check if a tone is active
---@param index TONE tone index
function public.is_active(index)
- if self.tone_active[index] then return self.tone_active[index] end
- return false
+ return self.tone_active[index] or false
end
-- set all tones inactive, reset next block, and clear output buffer
function public.stop()
- for i = 1, #self.tone_active do self.tone_active[i] = false end
+ for i = 1, #self.tone_active do
+ self.tone_active[i] = false
+ end
+
self.next_block = 1
+
clear(self.quad_buffer)
end
@@ -287,9 +298,11 @@ function audio.new_stream()
for id = 1, #tone_data do
if self.tone_active[id] then
self.any_active = true
+
for i = 1, 4 do
local buffer = self.quad_buffer[i]
local values = tone_data[id][i]
+
for s = 1, _05s_SAMPLES do self.quad_buffer[i][s] = limit(buffer[s] + values[s]) end
end
end
@@ -305,8 +318,13 @@ function audio.new_stream()
-- get the next audio block
function public.get_next_block()
local block = self.quad_buffer[self.next_block]
+
self.next_block = self.next_block + 1
- if self.next_block > 4 then self.next_block = 1 end
+
+ if self.next_block > 4 then
+ self.next_block = 1
+ end
+
return block
end
diff --git a/scada-common/comms.lua b/scada-common/comms.lua
index 6a82228..6f12fb2 100644
--- a/scada-common/comms.lua
+++ b/scada-common/comms.lua
@@ -405,7 +405,7 @@ function comms.modbus_packet()
self.raw = { self.txn_id, self.unit_id, self.func_code }
for i = 1, self.length do insert(self.raw, data[i]) end
else
- log.error("comms.modbus_packet.make(): data not table")
+ log.error("comms.modbus_packet.make(): data not a table")
end
end
@@ -491,7 +491,7 @@ function comms.rplc_packet()
self.raw = { self.id, self.type }
for i = 1, #data do insert(self.raw, data[i]) end
else
- log.error("comms.rplc_packet.make(): data not table")
+ log.error("comms.rplc_packet.make(): data not a table")
end
end
@@ -573,7 +573,7 @@ function comms.mgmt_packet()
self.raw = { self.type }
for i = 1, #data do insert(self.raw, data[i]) end
else
- log.error("comms.mgmt_packet.make(): data not table")
+ log.error("comms.mgmt_packet.make(): data not a table")
end
end
@@ -652,7 +652,7 @@ function comms.crdn_packet()
self.raw = { self.type }
for i = 1, #data do insert(self.raw, data[i]) end
else
- log.error("comms.crdn_packet.make(): data not table")
+ log.error("comms.crdn_packet.make(): data not a table")
end
end
diff --git a/scada-common/log.lua b/scada-common/log.lua
index f876eaa..0df1efc 100644
--- a/scada-common/log.lua
+++ b/scada-common/log.lua
@@ -4,10 +4,14 @@
local util = require("scada-common.util")
+-- constant strings for speed
+local DBG_TAG, INF_TAG, WRN_TAG, ERR_TAG, FTL_TAG = "[DBG] ", "[INF] ", "[WRN] ", "[ERR] ", "[FTL] "
+local COLON, FUNC, ARROW = ":", "():", " > "
+
---@class logger
local log = {}
----@alias MODE integer
+---@enum MODE
local MODE = { APPEND = 0, NEW = 1 }
log.MODE = MODE
@@ -18,7 +22,7 @@ local logger = {
mode = MODE.APPEND,
debug = false,
file = nil, ---@type table|nil
- dmesg_out = nil,
+ dmesg_out = nil, ---@type Redirect|nil
dmesg_restore_coord = { 1, 1 },
dmesg_scroll_count = 0
}
@@ -31,13 +35,13 @@ local free_space = fs.getFreeSpace
-----------------------
-- private log write function
----@param msg string
-local function _log(msg)
+---@param msg_bits any[]
+local function _log(msg_bits)
if logger.not_ready then return end
local out_of_space = false
- local time_stamp = os.date("[%c] ")
- local stamped = time_stamp .. util.strval(msg)
+ local time_stamp = os.date("[%c] ")
+ local stamped = util.c(time_stamp, table.unpack(msg_bits))
-- attempt to write log
local status, result = pcall(function ()
@@ -80,7 +84,7 @@ end
---@param path string file path
---@param write_mode MODE file write mode
---@param include_debug boolean whether or not to include debug logs
----@param dmesg_redirect? table terminal/window to direct dmesg to
+---@param dmesg_redirect? Redirect terminal/window to direct dmesg to
function log.init(path, write_mode, include_debug, dmesg_redirect)
logger.path = path
logger.mode = write_mode
@@ -102,16 +106,14 @@ function log.init(path, write_mode, include_debug, dmesg_redirect)
end
-- close the log file handle
-function log.close()
- logger.file.close()
-end
+function log.close() logger.file.close() end
-- direct dmesg output to a monitor/window
----@param window table window or terminal reference
+---@param window Window window or terminal reference
function log.direct_dmesg(window) logger.dmesg_out = window end
-- dmesg style logging for boot because I like linux-y things
----@param msg string message
+---@param msg any message
---@param tag? string log tag
---@param tag_color? integer log tag color
---@return dmesg_ts_coord coordinates line area to place working indicator
@@ -120,8 +122,7 @@ function log.dmesg(msg, tag, tag_color)
local ts_coord = { x1 = 2, x2 = 3, y = 1 }
msg = util.strval(msg)
- tag = tag or ""
- tag = util.strval(tag)
+ tag = util.strval(tag or "")
local t_stamp = string.format("%12.2f", os.clock())
local out = logger.dmesg_out
@@ -209,7 +210,7 @@ function log.dmesg(msg, tag, tag_color)
logger.dmesg_restore_coord = { out.getCursorPos() }
- _log(util.c("[", t_stamp, "] [", tag, "] ", msg))
+ _log{"[", t_stamp, "] [", tag, "] ", msg}
end
return ts_coord
@@ -291,63 +292,51 @@ function log.dmesg_working(msg, tag, tag_color)
end
-- log debug messages
----@param msg string message
+---@param msg any message
---@param trace? boolean include file trace
function log.debug(msg, trace)
if logger.debug then
- local dbg_info = ""
-
if trace then
local info = debug.getinfo(2)
- local name = ""
if info.name ~= nil then
- name = ":" .. info.name .. "():"
+ _log{DBG_TAG, info.short_src, COLON, info.name, FUNC, info.currentline, ARROW, msg}
+ else
+ _log{DBG_TAG, info.short_src, COLON, info.currentline, ARROW, msg}
end
-
- dbg_info = info.short_src .. ":" .. name .. info.currentline .. " > "
+ else
+ _log{DBG_TAG, msg}
end
-
- _log("[DBG] " .. dbg_info .. util.strval(msg))
end
end
-- log info messages
----@param msg string message
-function log.info(msg)
- _log("[INF] " .. util.strval(msg))
-end
+---@param msg any message
+function log.info(msg) _log{INF_TAG, msg} end
-- log warning messages
----@param msg string message
-function log.warning(msg)
- _log("[WRN] " .. util.strval(msg))
-end
+---@param msg any message
+function log.warning(msg) _log{WRN_TAG, msg} end
-- log error messages
----@param msg string message
+---@param msg any message
---@param trace? boolean include file trace
function log.error(msg, trace)
- local dbg_info = ""
-
if trace then
local info = debug.getinfo(2)
- local name = ""
if info.name ~= nil then
- name = ":" .. info.name .. "():"
+ _log{ERR_TAG, info.short_src, COLON, info.name, FUNC, info.currentline, ARROW, msg}
+ else
+ _log{ERR_TAG, info.short_src, COLON, info.currentline, ARROW, msg}
end
-
- dbg_info = info.short_src .. ":" .. name .. info.currentline .. " > "
+ else
+ _log{ERR_TAG, msg}
end
-
- _log("[ERR] " .. dbg_info .. util.strval(msg))
end
-- log fatal errors
----@param msg string message
-function log.fatal(msg)
- _log("[FTL] " .. util.strval(msg))
-end
+---@param msg any message
+function log.fatal(msg) _log{FTL_TAG, msg} end
return log
diff --git a/scada-common/mqueue.lua b/scada-common/mqueue.lua
index fc60a1e..db09509 100644
--- a/scada-common/mqueue.lua
+++ b/scada-common/mqueue.lua
@@ -27,6 +27,7 @@ local remove = table.remove
-- create a new message queue
---@nodiscard
function mqueue.new()
+ ---@type queue_item[]
local queue = {}
---@class mqueue
diff --git a/scada-common/network.lua b/scada-common/network.lua
index c34a1d5..7eccff7 100644
--- a/scada-common/network.lua
+++ b/scada-common/network.lua
@@ -77,26 +77,14 @@ end
-- NIC: Network Interface Controller
-- utilizes HMAC-MD5 for message authentication, if enabled
----@param modem table modem to use
+---@param modem Modem modem to use
function network.nic(modem)
local self = {
connected = true, -- used to avoid costly MAC calculations if modem isn't even present
channels = {}
}
- ---@class nic
- ---@field open function
- ---@field isOpen function
- ---@field close function
- ---@field closeAll function
- ---@field isWireless function
- ---@field getNameLocal function
- ---@field getNamesRemote function
- ---@field isPresentRemote function
- ---@field getTypeRemote function
- ---@field hasTypeRemote function
- ---@field getMethodsRemote function
- ---@field callRemote function
+ ---@class nic:Modem
local public = {}
-- check if this NIC has a connected modem
@@ -104,7 +92,7 @@ function network.nic(modem)
function public.is_connected() return self.connected end
-- connect to a modem peripheral
- ---@param reconnected_modem table
+ ---@param reconnected_modem Modem
function public.connect(reconnected_modem)
modem = reconnected_modem
self.connected = true
diff --git a/scada-common/ppm.lua b/scada-common/ppm.lua
index e6a95e8..7d6071e 100644
--- a/scada-common/ppm.lua
+++ b/scada-common/ppm.lua
@@ -23,7 +23,7 @@ ppm.VIRTUAL_DEVICE_TYPE = VIRTUAL_DEVICE_TYPE
local REPORT_FREQUENCY = 20 -- log every 20 faults per function
local ppm_sys = {
- mounts = {},
+ mounts = {}, ---@type { [string]: ppm_entry }
next_vid = 0,
auto_cf = false,
faulted = false,
@@ -40,10 +40,10 @@ local function peri_init(iface)
local self = {
faulted = false,
last_fault = "",
- fault_counts = {},
+ fault_counts = {}, ---@type { [string]: integer }
auto_cf = true,
- type = VIRTUAL_DEVICE_TYPE,
- device = {}
+ type = VIRTUAL_DEVICE_TYPE, ---@type string
+ device = {} ---@type { [string]: function }
}
if iface ~= "__virtual__" then
@@ -181,7 +181,7 @@ local function peri_init(iface)
setmetatable(self.device, mt)
---@class ppm_entry
- local entry = { type = self.type, dev = self.device }
+ local entry = { type = self.type, dev = self.device }
return entry
end
@@ -284,10 +284,10 @@ end
---@param device table device table
function ppm.unmount(device)
if device then
- for side, data in pairs(ppm_sys.mounts) do
+ for iface, data in pairs(ppm_sys.mounts) do
if data.dev == device then
- log.warning(util.c("PPM: manually unmounted ", data.type, " mounted to ", side))
- ppm_sys.mounts[side] = nil
+ log.warning(util.c("PPM: manually unmounted ", data.type, " mounted to ", iface))
+ ppm_sys.mounts[iface] = nil
break
end
end
@@ -334,12 +334,12 @@ end
-- list all available peripherals
---@nodiscard
----@return table names
+---@return string[] names
function ppm.list_avail() return peripheral.getNames() end
-- list mounted peripherals
---@nodiscard
----@return table mounts
+---@return { [string]: ppm_entry } mounts
function ppm.list_mounts()
local list = {}
for k, v in pairs(ppm_sys.mounts) do list[k] = v end
@@ -352,8 +352,8 @@ end
---@return string|nil iface CC peripheral interface
function ppm.get_iface(device)
if device then
- for side, data in pairs(ppm_sys.mounts) do
- if data.dev == device then return side end
+ for iface, data in pairs(ppm_sys.mounts) do
+ if data.dev == device then return iface end
end
end
@@ -363,7 +363,7 @@ end
-- get a mounted peripheral by side/interface
---@nodiscard
---@param iface string CC peripheral interface
----@return table|nil device function table
+---@return { [string]: function }|nil device function table
function ppm.get_periph(iface)
if ppm_sys.mounts[iface] then
return ppm_sys.mounts[iface].dev
@@ -423,7 +423,7 @@ function ppm.get_fission_reactor() return ppm.get_device("fissionReactorLogicAda
-- get the wireless modem (if multiple, returns the first)
-- if this is in a CraftOS emulated environment, wired modems will be used instead
---@nodiscard
----@return table|nil modem function table
+---@return Modem|nil modem function table
function ppm.get_wireless_modem()
local w_modem = nil
local emulated_env = periphemu ~= nil
@@ -440,7 +440,7 @@ end
-- list all connected monitors
---@nodiscard
----@return table monitors
+---@return { [string]: ppm_entry } monitors
function ppm.get_monitor_list()
local list = {}
diff --git a/scada-common/psil.lua b/scada-common/psil.lua
index 09686bf..f3d810a 100644
--- a/scada-common/psil.lua
+++ b/scada-common/psil.lua
@@ -6,9 +6,10 @@ local util = require("scada-common.util")
local psil = {}
--- instantiate a new PSI layer
+-- instantiate a new interconnect layer
---@nodiscard
function psil.create()
+ ---@type { [string]: { subscribers: { notify: fun(param: any) }[], value: any } } interconnect table
local ic = {}
-- allocate a new interconnect field
diff --git a/scada-common/rsio.lua b/scada-common/rsio.lua
index fb3a50a..b88180a 100644
--- a/scada-common/rsio.lua
+++ b/scada-common/rsio.lua
@@ -113,10 +113,13 @@ assert(#dup_chk == rsio.NUM_PORTS, "port list malformed")
local IO = IO_PORT
-- list of all port names
+---@type string[]
local PORT_NAMES = {}
+
for k, v in pairs(IO) do PORT_NAMES[v] = k end
-- list of all port I/O modes
+---@type { [IO_PORT]: IO_MODE }
local MODES = {
[IO.F_SCRAM] = IO_MODE.DIGITAL_IN,
[IO.F_ACK] = IO_MODE.DIGITAL_IN,
@@ -233,6 +236,7 @@ end
--#region Generic Checks
+---@type string[]
local RS_SIDES = rs.getSides()
-- check if a port is valid
diff --git a/scada-common/tcd.lua b/scada-common/tcd.lua
index a3c920f..f11c2d8 100644
--- a/scada-common/tcd.lua
+++ b/scada-common/tcd.lua
@@ -7,6 +7,7 @@ local util = require("scada-common.util")
local tcd = {}
+---@type { callback: function, duration: number, expiry: number }[]
local registry = {}
-- request a function to be called after the specified time
diff --git a/scada-common/types.lua b/scada-common/types.lua
index 2bf6ae1..29c52c5 100644
--- a/scada-common/types.lua
+++ b/scada-common/types.lua
@@ -5,6 +5,66 @@
---@class types
local types = {}
+--#region CC: TWEAKED CLASSES https://tweaked.cc
+
+---@class Redirect
+---@field write fun(text: string) Write text at the current cursor position, moving the cursor to the end of the text.
+---@field scroll fun(y: integer) Move all positions up (or down) by y pixels.
+---@field getCursorPos fun() : x: integer, y: integer Get the position of the cursor.
+---@field setCursorPos fun(x: integer, y: integer) Set the position of the cursor.
+---@field getCursorBlink fun() : boolean Checks if the cursor is currently blinking.
+---@field setCursorBlink fun(blink: boolean) Sets whether the cursor should be visible (and blinking) at the current cursor position.
+---@field getSize fun() : width: integer, height: integer Get the size of the terminal.
+---@field clear fun() Clears the terminal, filling it with the current background color.
+---@field clearLine fun() Clears the line the cursor is currently on, filling it with the current background color.
+---@field getTextColor fun() : color Return the color that new text will be written as.
+---@field setTextColor fun(color: color) Set the colour that new text will be written as.
+---@field getBackgroundColor fun() : color Return the current background color.
+---@field setBackgroundColor fun(color: color) set the current background color.
+---@field isColor fun() Determine if this terminal supports color.
+---@field blit fun(text: string, textColor: string, backgroundColor: string) Writes text to the terminal with the specific foreground and background colors.
+---@diagnostic disable-next-line: duplicate-doc-field
+---@field setPaletteColor fun(index: color, color: integer) Set the palette for a specific color.
+---@diagnostic disable-next-line: duplicate-doc-field
+---@field setPaletteColor fun(index: color, r: number, g: number, b:number) Set the palette for a specific color. R/G/B are 0 to 1.
+---@field getPaletteColor fun(color: color) : r: number, g: number, b:number Get the current palette for a specific color.
+
+---@class Window:Redirect
+---@field getLine fun(y: integer) : content: string, fg: string, bg: string Get the buffered contents of a line in this window.
+---@field setVisible fun(visible: boolean) Set whether this window is visible. Invisible windows will not be drawn to the screen until they are made visible again.
+---@field isVisible fun() : visible: boolean Get whether this window is visible. Invisible windows will not be drawn to the screen until they are made visible again.
+---@field redraw fun() Draw this window. This does nothing if the window is not visible.
+---@field restoreCursor fun() Set the current terminal's cursor to where this window's cursor is. This does nothing if the window is not visible.
+---@field getPosition fun() : x: integer, y: integer Get the position of the top left corner of this window.
+---@field reposition fun(new_x: integer, new_y: integer, new_width?: integer, new_height?: integer, new_parent?: Redirect) Reposition or resize the given window.
+
+---@class Monitor:Redirect
+---@field setTextScale fun(scale: number) Set the scale of this monitor.
+---@field getTextScale fun() : number Get the monitor's current text scale.
+
+---@class Modem
+---@field open fun(channel: integer) Open a channel on a modem.
+---@field isOpen fun(channel: integer) : boolean Check if a channel is open.
+---@field close fun(channel: integer) Close an open channel, meaning it will no longer receive messages.
+---@field closeAll fun() Close all open channels.
+---@field transmit fun(channel: integer, replyChannel: integer, payload: any) Sends a modem message on a certain channel.
+---@field isWireless fun() : boolean Determine if this is a wired or wireless modem.
+---@field getNamesRemote fun() : string[] List all remote peripherals on the wired network.
+---@field isPresentRemote fun(name: string) : boolean Determine if a peripheral is available on this wired network.
+---@field getTypeRemote fun(name: string) : string|nil Get the type of a peripheral is available on this wired network.
+---@field hasTypeRemote fun(name: string, type: string) : boolean|nil Check a peripheral is of a particular .
+---@field getMethodsRemote fun(name: string) : string[] Get all available methods for the remote peripheral with the given name.
+---@field callRemote fun(remoteName: string, method: string, ...) : table Call a method on a peripheral on this wired network.
+---@field getNameLocal fun() : string|nil Returns the network name of the current computer, if the modem is on.
+
+---@class Speaker
+---@field playNote fun(instrument: string, volume?: number, pitch?: number) : success: boolean Plays a note block note through the speaker.
+---@field playSound fun(name: string, volume?: number, pitch?: number) : success: boolean Plays a Minecraft sound through the speaker.
+---@field playAudio fun(audio: number[], volume?: number) : success: boolean Attempt to stream some audio data to the speaker.
+---@field stop fun() Stop all audio being played by this speaker.
+
+--#endregion
+
--#region CLASSES
---@class tank_fluid
@@ -65,7 +125,7 @@ function types.new_zero_coordinate() return { x = 0, y = 0, z = 0 } end
---@field type RTU_UNIT_TYPE
---@field index integer|false
---@field reactor integer
----@field rsio table|nil
+---@field rsio IO_PORT[]|nil
--#endregion
diff --git a/scada-common/util.lua b/scada-common/util.lua
index 36a73fc..2ae76a7 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.4"
+util.version = "1.4.5"
util.TICK_TIME_S = 0.05
util.TICK_TIME_MS = 50
@@ -33,9 +33,9 @@ util.TICK_TIME_MS = 50
-- trinary operator
---@nodiscard
----@param cond boolean|nil condition
----@param a any return if true
----@param b any return if false
+---@param cond any condition
+---@param a any return if evaluated as true
+---@param b any return if false or nil
---@return any value
function util.trinary(cond, a, b)
if cond then return a else return b end
@@ -84,7 +84,7 @@ end
-- does not behave exactly like C's strtok
---@param str string string to tokenize
---@param sep string separator to tokenize by
----@return table token_list
+---@return string[] token_list
function util.strtok(str, sep)
local list = {}
for part in string.gmatch(str, "([^" .. sep .. "]+)") do t_insert(list, part) end
@@ -123,7 +123,7 @@ end
---@nodiscard
---@param str string
---@param limit integer line limit, must be greater than 0
----@return table lines
+---@return string[] lines
function util.strwrap(str, limit)
assert(limit > 0, "util.strwrap() limit not greater than 0")
return cc_strings.wrap(str, limit)
@@ -138,7 +138,7 @@ function util.strminw(str, width) return cc_strings.ensure_width(str, width) end
-- concatenation with built-in to string
---@nodiscard
----@vararg any
+---@param ... any
---@return string
function util.concat(...)
local args, strings = t_pack(...), {}
@@ -152,7 +152,7 @@ util.c = util.concat
-- sprintf implementation
---@nodiscard
---@param format string
----@vararg any
+---@param ... any
function util.sprintf(format, ...) return string.format(format, ...) end
-- format a number string with commas as the thousands separator
@@ -343,8 +343,9 @@ end
-- delete elements from a table if the passed function returns false when passed a table element
-- put briefly: deletes elements that return false, keeps elements that return true
----@param t table table to remove elements from
----@param f function should return false to delete an element when passed the element: f(elem) = true|false
+---@generic Type
+---@param t Type[] table to remove elements from
+---@param f fun(t_elem: Type) : boolean should return false to delete an element when passed the element
---@param on_delete? function optional function to execute on deletion, passed the table element to be deleted as the parameter
function util.filter_table(t, f, on_delete)
local move_to = 1
@@ -366,9 +367,10 @@ function util.filter_table(t, f, on_delete)
end
-- check if a table contains the provided element
+---@generic Type
---@nodiscard
----@param t table table to check
----@param element any element to check for
+---@param t Type[] table to check
+---@param element Type element to check for
function util.table_contains(t, element)
for i = 1, #t do
if t[i] == element then return true end
diff --git a/supervisor/configure.lua b/supervisor/configure.lua
index 0c90538..362c41d 100644
--- a/supervisor/configure.lua
+++ b/supervisor/configure.lua
@@ -9,21 +9,21 @@ local util = require("scada-common.util")
local core = require("graphics.core")
local themes = require("graphics.themes")
-local DisplayBox = require("graphics.elements.displaybox")
-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 DisplayBox = require("graphics.elements.DisplayBox")
+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.push_button")
-local Radio2D = require("graphics.elements.controls.radio_2d")
-local RadioButton = require("graphics.elements.controls.radio_button")
+local Checkbox = require("graphics.elements.controls.Checkbox")
+local PushButton = require("graphics.elements.controls.PushButton")
+local Radio2D = require("graphics.elements.controls.Radio2D")
+local RadioButton = require("graphics.elements.controls.RadioButton")
-local NumberField = require("graphics.elements.form.number_field")
-local TextField = require("graphics.elements.form.text_field")
+local NumberField = require("graphics.elements.form.NumberField")
+local TextField = require("graphics.elements.form.TextField")
-local IndLight = require("graphics.elements.indicators.light")
+local IndLight = require("graphics.elements.indicators.IndicatorLight")
local println = util.println
local tri = util.trinary
@@ -62,46 +62,46 @@ local tool_ctl = {
importing_legacy = false,
jumped_to_color = false,
- view_cfg = nil, ---@type graphics_element
- color_cfg = nil, ---@type graphics_element
- color_next = nil, ---@type graphics_element
- color_apply = nil, ---@type graphics_element
- settings_apply = nil, ---@type graphics_element
+ view_cfg = nil, ---@type PushButton
+ color_cfg = nil, ---@type PushButton
+ color_next = nil, ---@type PushButton
+ color_apply = nil, ---@type PushButton
+ settings_apply = nil, ---@type PushButton
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 graphics_element
- auth_key_textbox = nil, ---@type graphics_element
+ show_key_btn = nil, ---@type PushButton
+ auth_key_textbox = nil, ---@type TextBox
auth_key_value = "",
- cooling_elems = {},
- tank_elems = {},
+ cooling_elems = {}, ---@type { line: Div, turbines: NumberField, boilers: NumberField, tank: Checkbox }[]
+ tank_elems = {}, ---@type { div: Div, tank_opt: Radio2D, no_tank: TextBox }[]
- vis_ftanks = {},
- vis_utanks = {}
+ vis_ftanks = {}, ---@type { line: Div, pipe_conn?: TextBox, pipe_chain?: TextBox, pipe_direct?: TextBox, label?: TextBox }[]
+ vis_utanks = {} ---@type { line: Div, label: TextBox }[]
}
---@class svr_config
local tmp_cfg = {
UnitCount = 1,
- CoolingConfig = {},
+ CoolingConfig = {}, ---@type { TurbineCount: integer, BoilerCount: integer, TankConnection: boolean }[]
FacilityTankMode = 0,
- FacilityTankDefs = {},
+ FacilityTankDefs = {}, ---@type integer[]
ExtChargeIdling = false,
- SVR_Channel = nil, ---@type integer
- PLC_Channel = nil, ---@type integer
- RTU_Channel = nil, ---@type integer
- CRD_Channel = nil, ---@type integer
- PKT_Channel = nil, ---@type integer
- PLC_Timeout = nil, ---@type number
- RTU_Timeout = nil, ---@type number
- CRD_Timeout = nil, ---@type number
- PKT_Timeout = nil, ---@type number
- TrustedRange = nil, ---@type number
- AuthKey = nil, ---@type string|nil
+ SVR_Channel = nil, ---@type integer
+ PLC_Channel = nil, ---@type integer
+ RTU_Channel = nil, ---@type integer
+ CRD_Channel = nil, ---@type integer
+ PKT_Channel = nil, ---@type integer
+ PLC_Timeout = nil, ---@type number
+ RTU_Timeout = nil, ---@type number
+ CRD_Timeout = nil, ---@type number
+ PKT_Timeout = nil, ---@type number
+ TrustedRange = nil, ---@type number
+ AuthKey = nil, ---@type string|nil
LogMode = 0,
LogPath = "",
LogDebug = false,
@@ -153,7 +153,7 @@ local function load_settings(target, raw)
end
-- create the config view
----@param display graphics_element
+---@param display DisplayBox
local function config_view(display)
---@diagnostic disable-next-line: undefined-field
local function exit() os.queueEvent("terminate") end
@@ -271,7 +271,7 @@ local function config_view(display)
TextBox{parent=line,text="Unit "..i,width=6}
local turbines = NumberField{parent=line,x=9,y=1,width=5,max_chars=2,default=num_t,min=1,max=3,fg_bg=bw_fg_bg}
local boilers = NumberField{parent=line,x=20,y=1,width=5,max_chars=2,default=num_b,min=0,max=2,fg_bg=bw_fg_bg}
- local tank = CheckBox{parent=line,x=30,y=1,label="Is Connected",default=has_t,box_fg_bg=cpair(colors.yellow,colors.black)}
+ local tank = Checkbox{parent=line,x=30,y=1,label="Is Connected",default=has_t,box_fg_bg=cpair(colors.yellow,colors.black)}
tool_ctl.cooling_elems[i] = { line = line, turbines = turbines, boilers = boilers, tank = tank }
end
@@ -294,7 +294,13 @@ local function config_view(display)
tmp_cfg.CoolingConfig = {}
for i = 1, tmp_cfg.UnitCount do
local conf = tool_ctl.cooling_elems[i]
- tmp_cfg.CoolingConfig[i] = { TurbineCount = tonumber(conf.turbines.get_value()), BoilerCount = tonumber(conf.boilers.get_value()), TankConnection = conf.tank.get_value() }
+ -- already verified fields are numbers
+ tmp_cfg.CoolingConfig[i] = {
+ TurbineCount = tonumber(conf.turbines.get_value()) --[[@as number]],
+ BoilerCount = tonumber(conf.boilers.get_value()) --[[@as number]],
+ TankConnection = conf.tank.get_value()
+ }
+
if conf.tank.get_value() then any_has_tank = true end
end
@@ -322,7 +328,7 @@ local function config_view(display)
TextBox{parent=svr_c_3,x=1,y=1,height=6,text="You have set one or more of your units to use dynamic tanks for emergency coolant. You have two paths for configuration. The first is to assign dynamic tanks to reactor units; one tank per reactor, only connected to that reactor. RTU configurations must also assign it as such."}
TextBox{parent=svr_c_3,x=1,y=8,height=3,text="Alternatively, you can configure them as facility tanks to connect to multiple reactor units. These can intermingle with unit-specific tanks."}
- local en_fac_tanks = CheckBox{parent=svr_c_3,x=1,y=12,label="Use Facility Dynamic Tanks",default=ini_cfg.FacilityTankMode>0,box_fg_bg=cpair(colors.yellow,colors.black)}
+ local en_fac_tanks = Checkbox{parent=svr_c_3,x=1,y=12,label="Use Facility Dynamic Tanks",default=ini_cfg.FacilityTankMode>0,box_fg_bg=cpair(colors.yellow,colors.black)}
local function submit_en_fac_tank()
if en_fac_tanks.get_value() then
@@ -583,7 +589,7 @@ local function config_view(display)
TextBox{parent=svr_c_7,height=6,text="Charge control provides automatic control to maintain an induction matrix charge level. In order to have smoother control, reactors that were activated will be held on at 0.01 mB/t for a short period before allowing them to turn off. This minimizes overshooting the charge target."}
TextBox{parent=svr_c_7,y=8,height=3,text="You can extend this to a full minute to minimize reactors flickering on/off, but there may be more overshoot of the target."}
- local ext_idling = CheckBox{parent=svr_c_7,x=1,y=12,label="Enable Extended Idling",default=ini_cfg.ExtChargeIdling,box_fg_bg=cpair(colors.yellow,colors.black)}
+ local ext_idling = Checkbox{parent=svr_c_7,x=1,y=12,label="Enable Extended Idling",default=ini_cfg.ExtChargeIdling,box_fg_bg=cpair(colors.yellow,colors.black)}
local function back_from_idling()
svr_pane.set_value(util.trinary(tmp_cfg.FacilityTankMode == 0, 3, 5))
@@ -704,11 +710,11 @@ local function config_view(display)
TextBox{parent=net_c_4,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra compution (can slow things down).",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_4,x=1,y=11,text="Facility Auth Key"}
- local key, _, censor = TextField{parent=net_c_4,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg}
+ local key, _ = TextField{parent=net_c_4,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg}
- local function censor_key(enable) censor(util.trinary(enable, "*", nil)) end
+ local function censor_key(enable) key.censor(util.trinary(enable, "*", nil)) end
- local hide_key = CheckBox{parent=net_c_4,x=34,y=12,label="Hide",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key}
+ local hide_key = Checkbox{parent=net_c_4,x=34,y=12,label="Hide",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key}
hide_key.set_value(true)
censor_key(true)
@@ -743,7 +749,7 @@ local function config_view(display)
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=49,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 Logging Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)}
+ local en_dbg = Checkbox{parent=log_c_1,x=1,y=10,default=ini_cfg.LogDebug,label="Enable Logging Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)}
TextBox{parent=log_c_1,x=3,y=11,height=2,text="This results in much larger log files. It is best to only use this when there is a problem.",fg_bg=g_lg_fg_bg}
local path_err = TextBox{parent=log_c_1,x=8,y=14,width=35,text="Please provide a log file path.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
diff --git a/supervisor/facility.lua b/supervisor/facility.lua
index 7b786a2..3ec2b82 100644
--- a/supervisor/facility.lua
+++ b/supervisor/facility.lua
@@ -40,7 +40,7 @@ local facility = {}
function facility.new(config)
---@class _facility_self
local self = {
- units = {},
+ units = {}, ---@type reactor_unit[]
types = { AUTO_SCRAM = AUTO_SCRAM, START_STATUS = START_STATUS },
status_text = { "START UP", "initializing..." },
all_sys_ok = false,
@@ -51,16 +51,16 @@ function facility.new(config)
r_cool = config.CoolingConfig,
fac_tank_mode = config.FacilityTankMode,
fac_tank_defs = config.FacilityTankDefs,
- fac_tank_list = {}
+ fac_tank_list = {} ---@type integer[]
},
-- rtus
- rtu_conn_count = 0,
- rtu_list = {},
- redstone = {},
- induction = {},
- sps = {},
- tanks = {},
- envd = {},
+ rtu_gw_conn_count = 0,
+ rtu_list = {}, ---@type unit_session[][]
+ redstone = {}, ---@type redstone_session[]
+ induction = {}, ---@type imatrix_session[]
+ sps = {}, ---@type sps_session[]
+ tanks = {}, ---@type dynamicv_session[]
+ envd = {}, ---@type envd_session[]
-- redstone I/O control
io_ctl = nil, ---@type rs_controller
-- process control
@@ -105,11 +105,11 @@ function facility.new(config)
sps_low_power = false,
disabled_sps = false,
-- alarm tones
- tone_states = {},
+ tone_states = {}, ---@type { [TONE]: boolean }
test_tone_set = false,
test_tone_reset = false,
- test_tone_states = {},
- test_alarm_states = {},
+ test_tone_states = {}, ---@type { [TONE]: boolean }
+ test_alarm_states = {}, ---@type { [ALARM]: boolean }
-- statistics
im_stat_init = false,
avg_charge = util.mov_avg(3), -- 3 seconds
@@ -350,7 +350,7 @@ function facility.new(config)
-- additionally sets the requested auto waste mode if applicable
function public.update_units()
for i = 1, #self.units do
- local u = self.units[i] ---@type reactor_unit
+ local u = self.units[i]
u.auto_set_waste(self.current_waste_product)
u.update()
end
@@ -363,16 +363,14 @@ function facility.new(config)
-- SCRAM all reactor units
function public.scram_all()
for i = 1, #self.units do
- local u = self.units[i] ---@type reactor_unit
- u.scram()
+ self.units[i].scram()
end
end
-- ack all alarms on all reactor units
function public.ack_all()
for i = 1, #self.units do
- local u = self.units[i] ---@type reactor_unit
- u.ack_all()
+ self.units[i].ack_all()
end
end
@@ -393,8 +391,7 @@ function facility.new(config)
-- load up current limits
local limits = {}
for i = 1, config.UnitCount do
- local u = self.units[i] ---@type reactor_unit
- limits[i] = u.get_control_inf().lim_br100 * 100
+ limits[i] = self.units[i].get_control_inf().lim_br100 * 100
end
-- only allow changes if not running
@@ -512,7 +509,7 @@ function facility.new(config)
-- attempt to set a test tone state
---@param id TONE|0 tone ID or 0 to disable all
---@param state boolean state
- ---@return boolean allow_testing, table test_tone_states
+ ---@return boolean allow_testing, { [TONE]: boolean } test_tone_states
function public.diag_set_test_tone(id, state)
if self.allow_testing then
self.test_tone_set = true
@@ -531,7 +528,7 @@ function facility.new(config)
-- attempt to set a test alarm state
---@param id ALARM|0 alarm ID or 0 to disable all
---@param state boolean state
- ---@return boolean allow_testing, table test_alarm_states
+ ---@return boolean allow_testing, { [ALARM]: boolean } test_alarm_states
function public.diag_set_test_alarm(id, state)
if self.allow_testing then
self.test_tone_set = true
@@ -565,7 +562,7 @@ function facility.new(config)
if all or type == RTU_UNIT_TYPE.IMATRIX then
build.induction = {}
for i = 1, #self.induction do
- local matrix = self.induction[i] ---@type unit_session
+ local matrix = self.induction[i]
build.induction[i] = { matrix.get_db().formed, matrix.get_db().build }
end
end
@@ -573,7 +570,7 @@ function facility.new(config)
if all or type == RTU_UNIT_TYPE.SPS then
build.sps = {}
for i = 1, #self.sps do
- local sps = self.sps[i] ---@type unit_session
+ local sps = self.sps[i]
build.sps[i] = { sps.get_db().formed, sps.get_db().build }
end
end
@@ -581,7 +578,7 @@ function facility.new(config)
if all or type == RTU_UNIT_TYPE.DYNAMIC_VALVE then
build.tanks = {}
for i = 1, #self.tanks do
- local tank = self.tanks[i] ---@type unit_session
+ local tank = self.tanks[i]
build.tanks[tank.get_device_idx()] = { tank.get_db().formed, tank.get_db().build }
end
end
@@ -636,7 +633,7 @@ function facility.new(config)
local status = {}
-- total count of all connected RTUs in the facility
- status.count = self.rtu_conn_count
+ status.count = self.rtu_gw_conn_count
-- power averages from induction matricies
status.power = {
@@ -649,8 +646,8 @@ function facility.new(config)
-- status of induction matricies (including tanks)
status.induction = {}
for i = 1, #self.induction do
- local matrix = self.induction[i] ---@type unit_session
- local db = matrix.get_db() ---@type imatrix_session_db
+ local matrix = self.induction[i]
+ local db = matrix.get_db()
status.induction[i] = { matrix.is_faulted(), db.formed, db.state, db.tanks }
@@ -662,24 +659,24 @@ function facility.new(config)
-- status of sps
status.sps = {}
for i = 1, #self.sps do
- local sps = self.sps[i] ---@type unit_session
- local db = sps.get_db() ---@type sps_session_db
+ local sps = self.sps[i]
+ local db = sps.get_db()
status.sps[i] = { sps.is_faulted(), db.formed, db.state, db.tanks }
end
-- status of dynamic tanks
status.tanks = {}
for i = 1, #self.tanks do
- local tank = self.tanks[i] ---@type unit_session
- local db = tank.get_db() ---@type dynamicv_session_db
+ local tank = self.tanks[i]
+ local db = tank.get_db()
status.tanks[tank.get_device_idx()] = { tank.is_faulted(), db.formed, db.state, db.tanks }
end
-- radiation monitors (environment detectors)
status.envds = {}
for i = 1, #self.envd do
- local envd = self.envd[i] ---@type unit_session
- local db = envd.get_db() ---@type envd_session_db
+ local envd = self.envd[i]
+ local db = envd.get_db()
status.envds[envd.get_device_idx()] = { envd.is_faulted(), db.radiation, db.radiation_raw }
end
@@ -688,9 +685,9 @@ function facility.new(config)
--#endregion
- -- supervisor sessions reporting the list of active RTU sessions
- ---@param rtu_sessions table session list of all connected RTUs
- function public.report_rtus(rtu_sessions) self.rtu_conn_count = #rtu_sessions end
+ -- supervisor sessions reporting the list of active RTU gateway sessions
+ ---@param sessions rtu_session_struct[] session list of all connected RTU gateways
+ function public.report_rtu_gateways(sessions) self.rtu_gw_conn_count = #sessions end
-- get the facility cooling configuration
function public.get_cooling_conf() return self.cooling_conf end
diff --git a/supervisor/facility_update.lua b/supervisor/facility_update.lua
index 43fe86b..6375077 100644
--- a/supervisor/facility_update.lua
+++ b/supervisor/facility_update.lua
@@ -84,7 +84,7 @@ local function allocate_burn_rate(burn_rate, ramp, abort_on_fault)
-- go through all reactor units in this group
for id = 1, #units do
- local u = units[id] ---@type reactor_unit
+ local u = units[id]
local ctl = u.get_control_inf()
local lim_br100 = u.auto_get_effective_limit()
@@ -139,7 +139,7 @@ function update.pre_auto()
-- check if test routines are allowed right now
self.allow_testing = true
for i = 1, #self.units do
- local u = self.units[i] ---@type reactor_unit
+ local u = self.units[i]
self.allow_testing = self.allow_testing and u.is_safe_idle()
end
@@ -149,8 +149,8 @@ function update.pre_auto()
-- calculate moving averages for induction matrix
if self.induction[1] ~= nil then
- local matrix = self.induction[1] ---@type unit_session
- local db = matrix.get_db() ---@type imatrix_session_db
+ local matrix = self.induction[1]
+ local db = matrix.get_db()
local build_update = db.build.last_update
rate_update = db.state.last_update
@@ -512,7 +512,7 @@ function update.auto_safety()
local astatus = self.ascram_status
if self.induction[1] ~= nil then
- local db = self.induction[1].get_db() ---@type imatrix_session_db
+ local db = self.induction[1].get_db()
-- clear matrix disconnected
if astatus.matrix_dc then
@@ -531,7 +531,7 @@ function update.auto_safety()
-- check for critical unit alarms
astatus.crit_alarm = false
for i = 1, #self.units do
- local u = self.units[i] ---@type reactor_unit
+ local u = self.units[i]
if u.has_alarm_min_prio(PRIO.CRITICAL) then
astatus.crit_alarm = true
@@ -544,8 +544,8 @@ function update.auto_safety()
local max_rad = 0
for i = 1, #self.envd do
- local envd = self.envd[i] ---@type unit_session
- local e_db = envd.get_db() ---@type envd_session_db
+ local envd = self.envd[i]
+ local e_db = envd.get_db()
if e_db.radiation_raw > max_rad then max_rad = e_db.radiation_raw end
end
@@ -620,7 +620,7 @@ function update.auto_safety()
-- reset PLC RPS trips if we should
for i = 1, #self.units do
- local u = self.units[i] ---@type reactor_unit
+ local u = self.units[i]
u.auto_cond_rps_reset()
end
end
@@ -647,7 +647,7 @@ function update.alarm_audio()
else
-- check all alarms for all units
for i = 1, #self.units do
- local u = self.units[i] ---@type reactor_unit
+ local u = self.units[i]
for id, alarm in pairs(u.get_alarms()) do
alarms[id] = alarms[id] or (alarm == ALARM_STATE.TRIPPED)
end
@@ -730,7 +730,7 @@ function update.redstone(ack_all)
-- handle facility SCRAM
if self.io_ctl.digital_read(IO.F_SCRAM) then
for i = 1, #self.units do
- local u = self.units[i] ---@type reactor_unit
+ local u = self.units[i]
u.cond_scram()
end
end
@@ -741,7 +741,7 @@ function update.redstone(ack_all)
-- update facility alarm outputs
local has_prio_alarm, has_any_alarm = false, false
for i = 1, #self.units do
- local u = self.units[i] ---@type reactor_unit
+ local u = self.units[i]
if u.has_alarm_min_prio(PRIO.EMERGENCY) then
has_prio_alarm, has_any_alarm = true, true
@@ -756,7 +756,7 @@ function update.redstone(ack_all)
-- update induction matrix related outputs
if self.induction[1] ~= nil then
- local db = self.induction[1].get_db() ---@type imatrix_session_db
+ local db = self.induction[1].get_db()
self.io_ctl.digital_write(IO.F_MATRIX_LOW, db.tanks.energy_fill < const.RS_THRESHOLDS.IMATRIX_CHARGE_LOW)
self.io_ctl.digital_write(IO.F_MATRIX_HIGH, db.tanks.energy_fill > const.RS_THRESHOLDS.IMATRIX_CHARGE_HIGH)
@@ -771,7 +771,7 @@ function update.unit_mgmt()
local need_emcool = false
for i = 1, #self.units do
- local u = self.units[i] ---@type reactor_unit
+ local u = self.units[i]
-- update auto waste processing
if u.get_control_inf().waste_mode == WASTE_MODE.AUTO then
@@ -791,7 +791,7 @@ function update.unit_mgmt()
self.current_waste_product = self.waste_product
if (not self.sps_low_power) and (self.waste_product == WASTE.ANTI_MATTER) and (self.induction[1] ~= nil) then
- local db = self.induction[1].get_db() ---@type imatrix_session_db
+ local db = self.induction[1].get_db()
if db.tanks.energy_fill >= 0.15 then
self.disabled_sps = false
@@ -812,8 +812,8 @@ function update.unit_mgmt()
-- there should be no need for any to be in fill only mode
if need_emcool then
for i = 1, #self.tanks do
- local session = self.tanks[i] ---@type unit_session
- local tank = session.get_db() ---@type dynamicv_session_db
+ local session = self.tanks[i]
+ local tank = session.get_db()
if tank.state.container_mode == CONTAINER_MODE.FILL then
session.get_cmd_queue().push_data(DTV_RTU_S_DATA.SET_CONT_MODE, CONTAINER_MODE.BOTH)
diff --git a/supervisor/panel/components/chk_entry.lua b/supervisor/panel/components/chk_entry.lua
index ff4a24b..eebba3b 100644
--- a/supervisor/panel/components/chk_entry.lua
+++ b/supervisor/panel/components/chk_entry.lua
@@ -8,15 +8,15 @@ local style = require("supervisor.panel.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local TextBox = require("graphics.elements.TextBox")
local ALIGN = core.ALIGN
local cpair = core.cpair
-- create an ID check list entry
----@param parent graphics_element parent
+---@param parent ListBox parent
---@param msg string message
---@param fail_code integer failure code
local function init(parent, msg, fail_code)
diff --git a/supervisor/panel/components/pdg_entry.lua b/supervisor/panel/components/pdg_entry.lua
index de68b8c..d160ef3 100644
--- a/supervisor/panel/components/pdg_entry.lua
+++ b/supervisor/panel/components/pdg_entry.lua
@@ -8,17 +8,17 @@ local style = require("supervisor.panel.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local TextBox = require("graphics.elements.TextBox")
-local DataIndicator = require("graphics.elements.indicators.data")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
local ALIGN = core.ALIGN
local cpair = core.cpair
-- create a pocket diagnostics list entry
----@param parent graphics_element parent
+---@param parent ListBox parent
---@param id integer PDG session ID
local function init(parent, id)
local s_hi_box = style.theme.highlight_box
diff --git a/supervisor/panel/components/rtu_entry.lua b/supervisor/panel/components/rtu_entry.lua
index edb9b3e..4ca4058 100644
--- a/supervisor/panel/components/rtu_entry.lua
+++ b/supervisor/panel/components/rtu_entry.lua
@@ -8,17 +8,17 @@ local style = require("supervisor.panel.style")
local core = require("graphics.core")
-local Div = require("graphics.elements.div")
-local TextBox = require("graphics.elements.textbox")
+local Div = require("graphics.elements.Div")
+local TextBox = require("graphics.elements.TextBox")
-local DataIndicator = require("graphics.elements.indicators.data")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
local ALIGN = core.ALIGN
local cpair = core.cpair
-- create an RTU list entry
----@param parent graphics_element parent
+---@param parent ListBox parent
---@param id integer RTU session ID
local function init(parent, id)
local s_hi_box = style.theme.highlight_box
diff --git a/supervisor/panel/front_panel.lua b/supervisor/panel/front_panel.lua
index 245122e..845ed84 100644
--- a/supervisor/panel/front_panel.lua
+++ b/supervisor/panel/front_panel.lua
@@ -16,15 +16,15 @@ local rtu_entry = require("supervisor.panel.components.rtu_entry")
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 Div = require("graphics.elements.Div")
+local ListBox = require("graphics.elements.ListBox")
+local MultiPane = require("graphics.elements.MultiPane")
+local TextBox = require("graphics.elements.TextBox")
-local TabBar = require("graphics.elements.controls.tabbar")
+local TabBar = require("graphics.elements.controls.TabBar")
-local LED = require("graphics.elements.indicators.led")
-local DataIndicator = require("graphics.elements.indicators.data")
+local LED = require("graphics.elements.indicators.LED")
+local DataIndicator = require("graphics.elements.indicators.DataIndicator")
local ALIGN = core.ALIGN
@@ -33,7 +33,7 @@ local cpair = core.cpair
local ind_grn = style.ind_grn
-- create new front panel view
----@param panel graphics_element main displaybox
+---@param panel DisplayBox main displaybox
local function init(panel)
local s_hi_box = style.theme.highlight_box
local s_hi_bright = style.theme.highlight_box_bright
diff --git a/supervisor/panel/pgi.lua b/supervisor/panel/pgi.lua
index 2d8ee93..5eb35c6 100644
--- a/supervisor/panel/pgi.lua
+++ b/supervisor/panel/pgi.lua
@@ -8,23 +8,28 @@ local util = require("scada-common.util")
local pgi = {}
local data = {
- rtu_list = nil, ---@type nil|graphics_element
- pdg_list = nil, ---@type nil|graphics_element
- chk_list = nil, ---@type nil|graphics_element
- rtu_entry = nil, ---@type function
- pdg_entry = nil, ---@type function
- chk_entry = nil, ---@type function
+ rtu_list = nil, ---@type ListBox|nil
+ pdg_list = nil, ---@type ListBox|nil
+ chk_list = nil, ---@type ListBox|nil
+ rtu_entry = nil, ---@type function
+ pdg_entry = nil, ---@type function
+ chk_entry = nil, ---@type function
-- list entries
- entries = { rtu = {}, pdg = {}, chk = {}, missing = {} }
+ entries = {
+ rtu = {}, ---@type Div[]
+ pdg = {}, ---@type Div[]
+ chk = {}, ---@type Div[][]
+ missing = {} ---@type Div[]
+ }
}
-- 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
----@param chk_list graphics_element CHK list element
----@param chk_entry function CHK entry constructor
+---@param rtu_list ListBox RTU list element
+---@param rtu_entry fun(parent: ListBox, id: integer) : Div RTU entry constructor
+---@param pdg_list ListBox pocket diagnostics list element
+---@param pdg_entry fun(parent: ListBox, id: integer) : Div pocket diagnostics entry constructor
+---@param chk_list ListBox CHK list element
+---@param chk_entry fun(parent: ListBox, msg: string, fail_code: integer) : Div CHK entry constructor
function pgi.link_elements(rtu_list, rtu_entry, pdg_list, pdg_entry, chk_list, chk_entry)
data.rtu_list = rtu_list
data.pdg_list = pdg_list
@@ -130,8 +135,8 @@ function pgi.create_chk_entry(unit, fail_code, msg)
end
end
--- delete a device ID check failure entry from the CHK list
----@note this assumes only one type of failure can occur per each RTU gateway session's RTU, which is the case
+-- delete a device ID check failure entry from the CHK list
+-- this assumes only one type of failure can occur per each RTU gateway session's RTU, which is the case
---@param unit unit_session RTU session
function pgi.delete_chk_entry(unit)
local gw_session = unit.get_session_id()
diff --git a/supervisor/renderer.lua b/supervisor/renderer.lua
index fde7fc3..57c6b4b 100644
--- a/supervisor/renderer.lua
+++ b/supervisor/renderer.lua
@@ -9,7 +9,7 @@ local style = require("supervisor.panel.style")
local core = require("graphics.core")
local flasher = require("graphics.flasher")
-local DisplayBox = require("graphics.elements.displaybox")
+local DisplayBox = require("graphics.elements.DisplayBox")
---@class supervisor_renderer
local renderer = {}
diff --git a/supervisor/session/coordinator.lua b/supervisor/session/coordinator.lua
index 8b9c0d9..771e210 100644
--- a/supervisor/session/coordinator.lua
+++ b/supervisor/session/coordinator.lua
@@ -128,7 +128,7 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim
local unit_builds = {}
for i = 1, #self.units do
- local unit = self.units[i] ---@type reactor_unit
+ local unit = self.units[i]
unit_builds[unit.get_id()] = unit.get_build()
end
@@ -145,7 +145,7 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim
local builds = {}
for i = 1, #self.units do
- local unit = self.units[i] ---@type reactor_unit
+ local unit = self.units[i]
builds[unit.get_id()] = unit.get_build()
end
@@ -168,7 +168,7 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim
local status = {}
for i = 1, #self.units do
- local unit = self.units[i] ---@type reactor_unit
+ local unit = self.units[i]
status[unit.get_id()] = {
unit.get_reactor_status(),
@@ -308,7 +308,7 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim
-- continue if valid unit id
if util.is_int(uid) and uid > 0 and uid <= #self.units then
- local unit = self.units[uid] ---@type reactor_unit
+ local unit = self.units[uid]
local manual = facility.get_group(uid) == AUTO_GROUP.MANUAL
if cmd == UNIT_COMMAND.SCRAM then
@@ -432,8 +432,7 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim
local unit_id = cmd.val
local builds = {}
- local unit = self.units[unit_id] ---@type reactor_unit
- builds[unit_id] = unit.get_build(-1)
+ builds[unit_id] = self.units[unit_id].get_build(-1)
_send(CRDN_TYPE.UNIT_BUILDS, { builds })
elseif cmd.key == CRD_S_DATA.RESEND_RTU_BUILD then
@@ -446,8 +445,7 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim
local builds = {}
- local unit = self.units[unit_id] ---@type reactor_unit
- builds[unit_id] = unit.get_build(cmd.val.type)
+ builds[unit_id] = self.units[unit_id].get_build(cmd.val.type)
_send(CRDN_TYPE.UNIT_BUILDS, { builds })
else
diff --git a/supervisor/session/rsctl.lua b/supervisor/session/rsctl.lua
index a369937..b270267 100644
--- a/supervisor/session/rsctl.lua
+++ b/supervisor/session/rsctl.lua
@@ -8,7 +8,7 @@ local rsctl = {}
-- create a new redstone RTU I/O controller
---@nodiscard
----@param redstone_rtus table redstone RTU sessions
+---@param redstone_rtus redstone_session[] redstone RTU sessions
function rsctl.new(redstone_rtus)
---@class rs_controller
local public = {}
@@ -18,8 +18,7 @@ function rsctl.new(redstone_rtus)
---@return boolean
function public.is_connected(port)
for i = 1, #redstone_rtus do
- local db = redstone_rtus[i].get_db() ---@type redstone_session_db
- if db.io[port] ~= nil then return true end
+ if redstone_rtus[i].get_db().io[port] ~= nil then return true end
end
return false
@@ -30,8 +29,7 @@ function rsctl.new(redstone_rtus)
---@param value boolean
function public.digital_write(port, value)
for i = 1, #redstone_rtus do
- local db = redstone_rtus[i].get_db() ---@type redstone_session_db
- local io = db.io[port] ---@type rs_db_dig_io|nil
+ local io = redstone_rtus[i].get_db().io[port]
if io ~= nil then io.write(value) end
end
end
@@ -42,9 +40,8 @@ function rsctl.new(redstone_rtus)
---@return boolean|nil
function public.digital_read(port)
for i = 1, #redstone_rtus do
- local db = redstone_rtus[i].get_db() ---@type redstone_session_db
- local io = db.io[port] ---@type rs_db_dig_io|nil
- if io ~= nil then return io.read() end
+ local io = redstone_rtus[i].get_db().io[port]
+ if io ~= nil then return io.read() --[[@as boolean|nil]] end
end
end
@@ -55,8 +52,7 @@ function rsctl.new(redstone_rtus)
---@param max number maximum value for scaling 0 to 15
function public.analog_write(port, value, min, max)
for i = 1, #redstone_rtus do
- local db = redstone_rtus[i].get_db() ---@type redstone_session_db
- local io = db.io[port] ---@type rs_db_ana_io|nil
+ local io = redstone_rtus[i].get_db().io[port]
if io ~= nil then io.write(rsio.analog_write(value, min, max)) end
end
end
diff --git a/supervisor/session/rtu.lua b/supervisor/session/rtu.lua
index 7d2494a..a38559c 100644
--- a/supervisor/session/rtu.lua
+++ b/supervisor/session/rtu.lua
@@ -63,7 +63,7 @@ function rtu.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, ad
keep_alive = 0,
alarm_tones = 0
},
- units = {}
+ units = {} ---@type unit_session[]
}
---@class rtu_session
@@ -80,13 +80,13 @@ function rtu.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, ad
_reset_config()
for i = 1, #self.fac_units do
- local unit = self.fac_units[i] ---@type reactor_unit
+ local unit = self.fac_units[i]
unit.purge_rtu_devices(id)
facility.purge_rtu_devices(id)
end
for i = 1, #self.advert do
- local unit = nil ---@type unit_session|nil
+ local unit = nil
---@type rtu_advertisement
local unit_advert = {
@@ -96,7 +96,7 @@ function rtu.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, ad
rsio = self.advert[i][4]
}
- local u_type = unit_advert.type ---@type integer|boolean
+ local u_type = unit_advert.type ---@type RTU_UNIT_TYPE|boolean
-- validate unit advertisement
@@ -127,7 +127,7 @@ function rtu.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, ad
log.debug(log_tag .. "_handle_advertisement(): advertisement unit validation failure")
else
if unit_advert.reactor > 0 then
- local target_unit = self.fac_units[unit_advert.reactor] ---@type reactor_unit
+ local target_unit = self.fac_units[unit_advert.reactor]
-- unit RTUs
if u_type == RTU_UNIT_TYPE.REDSTONE then
@@ -255,8 +255,7 @@ function rtu.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, ad
if pkt.scada_frame.protocol() == PROTOCOL.MODBUS_TCP then
---@cast pkt modbus_frame
if self.units[pkt.unit_id] ~= nil then
- local unit = self.units[pkt.unit_id] ---@type unit_session
- unit.handle_packet(pkt)
+ self.units[pkt.unit_id].handle_packet(pkt)
end
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
---@cast pkt mgmt_frame
@@ -298,8 +297,7 @@ function rtu.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, ad
if pkt.length == 1 then
local unit_id = pkt.data[1]
if self.units[unit_id] ~= nil then
- local unit = self.units[unit_id] ---@type unit_session
- unit.invalidate_cache()
+ self.units[unit_id].invalidate_cache()
end
else
log.debug(log_tag .. "SCADA RTU GW device re-mount packet length mismatch")
diff --git a/supervisor/session/rtu/boilerv.lua b/supervisor/session/rtu/boilerv.lua
index 26a8f2d..a1a1a99 100644
--- a/supervisor/session/rtu/boilerv.lua
+++ b/supervisor/session/rtu/boilerv.lua
@@ -99,6 +99,7 @@ function boilerv.new(session_id, unit_id, advert, out_queue)
}
}
+ ---@class boilerv_session:unit_session
local public = self.session.get()
-- PRIVATE FUNCTIONS --
diff --git a/supervisor/session/rtu/dynamicv.lua b/supervisor/session/rtu/dynamicv.lua
index 13239a7..0c06d7b 100644
--- a/supervisor/session/rtu/dynamicv.lua
+++ b/supervisor/session/rtu/dynamicv.lua
@@ -84,7 +84,7 @@ function dynamicv.new(session_id, unit_id, advert, out_queue)
},
state = {
last_update = 0,
- container_mode = CONTAINER_MODE.BOTH ---@type container_mode
+ container_mode = CONTAINER_MODE.BOTH ---@type container_mode
},
tanks = {
last_update = 0,
@@ -94,6 +94,7 @@ function dynamicv.new(session_id, unit_id, advert, out_queue)
}
}
+ ---@class dynamicv_session:unit_session
local public = self.session.get()
-- PRIVATE FUNCTIONS --
@@ -224,7 +225,7 @@ function dynamicv.new(session_id, unit_id, advert, out_queue)
end
elseif msg.qtype == mqueue.TYPE.DATA then
-- instruction with body
- local cmd = msg.message ---@type queue_data
+ local cmd = msg.message ---@type queue_data
if cmd.key == DTV_RTU_S_DATA.SET_CONT_MODE then
if cmd.val == types.CONTAINER_MODE.BOTH or
cmd.val == types.CONTAINER_MODE.FILL or
diff --git a/supervisor/session/rtu/envd.lua b/supervisor/session/rtu/envd.lua
index 046ef0a..269975a 100644
--- a/supervisor/session/rtu/envd.lua
+++ b/supervisor/session/rtu/envd.lua
@@ -52,6 +52,7 @@ function envd.new(session_id, unit_id, advert, out_queue)
}
}
+ ---@class envd_session:unit_session
local public = self.session.get()
-- PRIVATE FUNCTIONS --
diff --git a/supervisor/session/rtu/imatrix.lua b/supervisor/session/rtu/imatrix.lua
index 84bfc1e..aa7a984 100644
--- a/supervisor/session/rtu/imatrix.lua
+++ b/supervisor/session/rtu/imatrix.lua
@@ -83,6 +83,7 @@ function imatrix.new(session_id, unit_id, advert, out_queue)
}
}
+ ---@class imatrix_session:unit_session
local public = self.session.get()
-- PRIVATE FUNCTIONS --
diff --git a/supervisor/session/rtu/redstone.lua b/supervisor/session/rtu/redstone.lua
index b99c0d9..ce9d6c4 100644
--- a/supervisor/session/rtu/redstone.lua
+++ b/supervisor/session/rtu/redstone.lua
@@ -39,9 +39,13 @@ local PERIODICS = {
OUTPUT_SYNC = 200
}
----@class phy_entry
----@field phy IO_LVL
----@field req IO_LVL
+---@class dig_phy_entry
+---@field phy IO_LVL actual value
+---@field req IO_LVL commanded value
+
+---@class ana_phy_entry
+---@field phy number actual value
+---@field req number commanded value
-- create a new redstone rtu session runner
---@nodiscard
@@ -72,27 +76,29 @@ function redstone.new(session_id, unit_id, advert, out_queue)
},
---@class rs_io_list
io_list = {
- digital_in = {}, -- discrete inputs
- digital_out = {}, -- coils
- analog_in = {}, -- input registers
- analog_out = {} -- holding registers
+ digital_in = {}, ---@type IO_PORT[] discrete inputs
+ digital_out = {}, ---@type IO_PORT[] coils
+ analog_in = {}, ---@type IO_PORT[] input registers
+ analog_out = {} ---@type IO_PORT[] holding registers
},
phy_trans = { coils = -1, hold_regs = -1 },
-- last set/read ports (reflecting the current state of the RTU)
---@class rs_io_states
phy_io = {
- digital_in = {}, -- discrete inputs
- digital_out = {}, -- coils
- analog_in = {}, -- input registers
- analog_out = {} -- holding registers
+ digital_in = {}, ---@type dig_phy_entry[] discrete inputs
+ digital_out = {}, ---@type dig_phy_entry[] coils
+ analog_in = {}, ---@type ana_phy_entry[] input registers
+ analog_out = {} ---@type ana_phy_entry[] holding registers
},
---@class redstone_session_db
db = {
-- read/write functions for connected I/O
+ ---@type (rs_db_dig_io|rs_db_ana_io)[]
io = {}
}
}
+ ---@class redstone_session:unit_session
local public = self.session.get()
-- INITIALIZE --
diff --git a/supervisor/session/rtu/sna.lua b/supervisor/session/rtu/sna.lua
index a75e185..7e0fc34 100644
--- a/supervisor/session/rtu/sna.lua
+++ b/supervisor/session/rtu/sna.lua
@@ -74,6 +74,7 @@ function sna.new(session_id, unit_id, advert, out_queue)
}
}
+ ---@class sna_session:unit_session
local public = self.session.get()
-- PRIVATE FUNCTIONS --
diff --git a/supervisor/session/rtu/sps.lua b/supervisor/session/rtu/sps.lua
index a631e58..1dacd61 100644
--- a/supervisor/session/rtu/sps.lua
+++ b/supervisor/session/rtu/sps.lua
@@ -88,6 +88,7 @@ function sps.new(session_id, unit_id, advert, out_queue)
}
}
+ ---@class sps_session:unit_session
local public = self.session.get()
-- PRIVATE FUNCTIONS --
diff --git a/supervisor/session/rtu/turbinev.lua b/supervisor/session/rtu/turbinev.lua
index 4541e56..3581884 100644
--- a/supervisor/session/rtu/turbinev.lua
+++ b/supervisor/session/rtu/turbinev.lua
@@ -95,7 +95,7 @@ function turbinev.new(session_id, unit_id, advert, out_queue)
flow_rate = 0,
prod_rate = 0,
steam_input_rate = 0,
- dumping_mode = DUMPING_MODE.IDLE ---@type dumping_mode
+ dumping_mode = DUMPING_MODE.IDLE ---@type dumping_mode
},
tanks = {
last_update = 0,
@@ -109,6 +109,7 @@ function turbinev.new(session_id, unit_id, advert, out_queue)
}
}
+ ---@class turbinev_session:unit_session
local public = self.session.get()
-- PRIVATE FUNCTIONS --
@@ -254,7 +255,7 @@ function turbinev.new(session_id, unit_id, advert, out_queue)
end
elseif msg.qtype == mqueue.TYPE.DATA then
-- instruction with body
- local cmd = msg.message ---@type queue_data
+ local cmd = msg.message ---@type queue_data
if cmd.key == TBV_RTU_S_DATA.SET_DUMP_MODE then
if cmd.val == types.DUMPING_MODE.IDLE or
cmd.val == types.DUMPING_MODE.DUMPING_EXCESS or
diff --git a/supervisor/session/rtu/txnctrl.lua b/supervisor/session/rtu/txnctrl.lua
index 25ab3ed..cb8de47 100644
--- a/supervisor/session/rtu/txnctrl.lua
+++ b/supervisor/session/rtu/txnctrl.lua
@@ -6,7 +6,8 @@ local util = require("scada-common.util")
local txnctrl = {}
-local TIMEOUT = 2000 -- 2000ms max wait
+-- 2000ms max wait
+local TIMEOUT = 2000
-- create a new transaction controller
---@nodiscard
diff --git a/supervisor/session/rtu/unit_session.lua b/supervisor/session/rtu/unit_session.lua
index 4f516c8..632890b 100644
--- a/supervisor/session/rtu/unit_session.lua
+++ b/supervisor/session/rtu/unit_session.lua
@@ -29,7 +29,7 @@ unit_session.RTU_US_DATA = RTU_US_DATA
---@param advert rtu_advertisement RTU advertisement for this unit
---@param out_queue mqueue send queue
---@param log_tag string logging tag
----@param txn_tags table transaction log tags
+---@param txn_tags string[] transaction log tags
function unit_session.new(session_id, unit_id, advert, out_queue, log_tag, txn_tags)
local self = {
device_index = advert.index,
@@ -52,7 +52,7 @@ function unit_session.new(session_id, unit_id, advert, out_queue, log_tag, txn_t
-- send a MODBUS message, creating a transaction in the process
---@param txn_type integer transaction type
---@param f_code MODBUS_FCODE function code
- ---@param register_param table register range or register and values
+ ---@param register_param (number|string)[] register range or register and values
---@return integer txn_id transaction ID of this transaction
function protected.send_request(txn_type, f_code, register_param)
local m_pkt = comms.modbus_packet()
@@ -164,7 +164,6 @@ function unit_session.new(session_id, unit_id, advert, out_queue, log_tag, txn_t
function public.get_cmd_queue() return protected.in_q end
-- close this unit
- ---@nodiscard
function public.close() self.connected = false end
-- check if this unit is connected
---@nodiscard
diff --git a/supervisor/session/svsessions.lua b/supervisor/session/svsessions.lua
index 30ef729..6090eff 100644
--- a/supervisor/session/svsessions.lua
+++ b/supervisor/session/svsessions.lua
@@ -40,13 +40,26 @@ local SESSION_TYPE = {
svsessions.SESSION_TYPE = SESSION_TYPE
local self = {
- nic = nil, ---@type nic|nil
+ -- references to supervisor state and other data
+ nic = nil, ---@type nic|nil
fp_ok = false,
- config = nil, ---@type svr_config
- facility = nil, ---@type facility|nil
- sessions = { rtu = {}, plc = {}, crd = {}, pdg = {} },
+ config = nil, ---@type svr_config
+ facility = nil, ---@type facility|nil
+ -- lists of connected sessions
+ sessions = {
+ rtu = {}, ---@type rtu_session_struct
+ plc = {}, ---@type plc_session_struct
+ crd = {}, ---@type crd_session_struct
+ pdg = {} ---@type pdg_session_struct
+ },
+ -- next session IDs
next_ids = { rtu = 0, plc = 0, crd = 0, pdg = 0 },
- dev_dbg = { duplicate = {}, out_of_range = {}, connected = {} }
+ -- rtu device tracking and invalid assignment detection
+ dev_dbg = {
+ duplicate = {}, ---@type unit_session[]
+ out_of_range = {}, ---@type unit_session[]
+ connected = {} ---@type { induction: boolean, sps: boolean, tanks: boolean[], units: unit_connections[] }
+ }
}
---@alias sv_session_structs plc_session_struct|rtu_session_struct|crd_session_struct|pdg_session_struct
@@ -119,10 +132,10 @@ local function _sv_handle_outq(session)
end
-- iterate all the given sessions
----@param sessions table
+---@param sessions sv_session_structs[]
local function _iterate(sessions)
for i = 1, #sessions do
- local session = sessions[i] ---@type sv_session_structs
+ local session = sessions[i]
if session.open and session.instance.iterate() then
_sv_handle_outq(session)
@@ -150,20 +163,20 @@ local function _shutdown(session)
end
-- close connections
----@param sessions table
+---@param sessions sv_session_structs[]
local function _close(sessions)
for i = 1, #sessions do
- local session = sessions[i] ---@type sv_session_structs
+ local session = sessions[i]
if session.open then _shutdown(session) end
end
end
-- check if a watchdog timer event matches that of one of the provided sessions
----@param sessions table
+---@param sessions sv_session_structs[]
---@param timer_event number
local function _check_watchdogs(sessions, timer_event)
for i = 1, #sessions do
- local session = sessions[i] ---@type sv_session_structs
+ local session = sessions[i]
if session.open then
local triggered = session.instance.check_wd(timer_event)
if triggered then
@@ -175,8 +188,9 @@ local function _check_watchdogs(sessions, timer_event)
end
-- delete any closed sessions
----@param sessions table
+---@param sessions sv_session_structs[]
local function _free_closed(sessions)
+ ---@param session sv_session_structs
local f = function (session) return session.open end
---@param session sv_session_structs
@@ -189,7 +203,7 @@ end
-- find a session by computer ID
---@nodiscard
----@param list table
+---@param list sv_session_structs[]
---@param s_addr integer
---@return sv_session_structs|nil
local function _find_session(list, s_addr)
@@ -273,7 +287,7 @@ end
-- on attempted link of an RTU to a facility or unit object, verify its ID and report a problem if it can't be accepted
---@param unit unit_session RTU session
----@param list table table of RTU sessions
+---@param list unit_session[] table of RTU sessions
---@param max integer max of this type of RTU
---@return RTU_ID_FAIL fail_code, string fail_str
function svsessions.check_rtu_id(unit, list, max)
@@ -366,7 +380,7 @@ function svsessions.init(nic, fp_ok, config, facility)
for i = 1, config.UnitCount do
local r_cool = cool_conf.r_cool[i]
- local conns = { boilers = {}, turbines = {}, tanks = {} }
+ local conns = { boilers = {}, turbines = {}, tanks = {} } ---@type unit_connections
for b = 1, r_cool.BoilerCount do conns.boilers[b] = true end
for t = 1, r_cool.TurbineCount do conns.turbines[t] = true end
@@ -633,8 +647,8 @@ function svsessions.iterate_all()
-- iterate sessions
for _, list in pairs(self.sessions) do _iterate(list) end
- -- report RTU sessions to facility
- self.facility.report_rtus(self.sessions.rtu)
+ -- report RTU gateway sessions to facility
+ self.facility.report_rtu_gateways(self.sessions.rtu)
-- iterate facility
self.facility.update()
diff --git a/supervisor/startup.lua b/supervisor/startup.lua
index 4f6726c..08a1a89 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.3"
+local SUPERVISOR_VERSION = "v1.5.4"
local println = util.println
local println_ts = util.println_ts
@@ -157,6 +157,7 @@ local function main()
if type ~= nil and device ~= nil then
if type == "modem" then
+ ---@cast device Modem
-- we only care if this is our wireless modem
if nic.is_modem(device) then
nic.disconnect()
@@ -181,6 +182,7 @@ local function main()
if type ~= nil and device ~= nil then
if type == "modem" then
+ ---@cast device Modem
if device.isWireless() and not nic.is_connected() then
-- reconnected modem
nic.connect(device)
diff --git a/supervisor/unit.lua b/supervisor/unit.lua
index 3290af0..16f065a 100644
--- a/supervisor/unit.lua
+++ b/supervisor/unit.lua
@@ -81,13 +81,13 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
num_turbines = num_turbines,
types = { DT_KEYS = DT_KEYS, AISTATE = AISTATE },
-- rtus
- rtu_list = {},
- redstone = {},
- boilers = {},
- turbines = {},
- tanks = {},
- snas = {},
- envd = {},
+ rtu_list = {}, ---@type unit_session[][]
+ redstone = {}, ---@type redstone_session[]
+ boilers = {}, ---@type boilerv_session[]
+ turbines = {}, ---@type turbinev_session[]
+ tanks = {}, ---@type dynamicv_session[]
+ snas = {}, ---@type sna_session[]
+ envd = {}, ---@type envd_session[]
-- redstone control
io_ctl = nil, ---@type rs_controller
valves = {}, ---@type unit_valves
@@ -100,7 +100,7 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
auto_was_alarmed = false,
ramp_target_br100 = 0,
-- state tracking
- deltas = {},
+ deltas = {}, ---@type { last_t: number, last_v: number, dt: number }[]
last_heartbeat = 0,
last_radiation = 0,
damage_decreasing = false,
@@ -108,12 +108,12 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
damage_start = 0,
damage_last = 0,
damage_est_last = 0,
- waste_product = WASTE.PLUTONIUM, ---@type WASTE_PRODUCT
+ waste_product = WASTE.PLUTONIUM, ---@type WASTE_PRODUCT
status_text = { "UNKNOWN", "awaiting connection..." },
-- logic for alarms
had_reactor = false,
turbine_flow_stable = false,
- turbine_stability_data = {},
+ turbine_stability_data = {}, ---@type { time_state: integer, time_tanks: integer, rotation: number, input_rate: integer }[]
last_rate_change_ms = 0,
---@type rps_status
last_rps_trips = {
@@ -154,7 +154,7 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
waste = 0,
high_temp_lim = 1150
},
- ---@class alarm_monitors
+ ---@type { [string]: alarm_def }
alarms = {
-- reactor lost under the condition of meltdown imminent
ContainmentBreach = { state = AISTATE.INACTIVE, trip_time = 0, hold_time = 0, id = ALARM.ContainmentBreach, tier = PRIO.CRITICAL },
@@ -211,17 +211,17 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
SteamFeedMismatch = false,
MaxWaterReturnFeed = false,
-- boilers
- BoilerOnline = {},
- HeatingRateLow = {},
- WaterLevelLow = {},
+ BoilerOnline = {}, ---@type boolean[]
+ HeatingRateLow = {}, ---@type boolean[]
+ WaterLevelLow = {}, ---@type boolean[]
-- turbines
- TurbineOnline = {},
- SteamDumpOpen = {},
- TurbineOverSpeed = {},
- GeneratorTrip = {},
- TurbineTrip = {}
+ TurbineOnline = {}, ---@type boolean[]
+ SteamDumpOpen = {}, ---@type integer[]
+ TurbineOverSpeed = {}, ---@type boolean[]
+ GeneratorTrip = {}, ---@type boolean[]
+ TurbineTrip = {} ---@type boolean[]
},
- ---@class alarms
+ ---@type { [ALARM]: ALARM_STATE }
alarm_states = {
ALARM_STATE.INACTIVE,
ALARM_STATE.INACTIVE,
@@ -244,7 +244,7 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
blade_count = 0,
br100 = 0,
lim_br100 = 0,
- waste_mode = WASTE_MODE.AUTO ---@type WASTE_MODE
+ waste_mode = WASTE_MODE.AUTO ---@type WASTE_MODE
}
}
}
@@ -324,8 +324,8 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
end
for i = 1, #self.boilers do
- local boiler = self.boilers[i] ---@type unit_session
- local db = boiler.get_db() ---@type boilerv_session_db
+ local boiler = self.boilers[i]
+ local db = boiler.get_db()
local last_update_s = db.tanks.last_update / 1000.0
@@ -336,8 +336,8 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
end
for i = 1, #self.turbines do
- local turbine = self.turbines[i] ---@type unit_session
- local db = turbine.get_db() ---@type turbinev_session_db
+ local turbine = self.turbines[i]
+ local db = turbine.get_db()
local last_update_s = db.tanks.last_update / 1000.0
@@ -553,8 +553,8 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
-- check boilers formed/faulted
for i = 1, #self.boilers do
- local sess = self.boilers[i] ---@type unit_session
- local boiler = sess.get_db() ---@type boilerv_session_db
+ local sess = self.boilers[i]
+ local boiler = sess.get_db()
if sess.is_faulted() or not boiler.formed then
self.db.control.degraded = true
end
@@ -562,8 +562,8 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
-- check turbines formed/faulted
for i = 1, #self.turbines do
- local sess = self.turbines[i] ---@type unit_session
- local turbine = sess.get_db() ---@type turbinev_session_db
+ local sess = self.turbines[i]
+ local turbine = sess.get_db()
if sess.is_faulted() or not turbine.formed then
self.db.control.degraded = true
end
@@ -881,7 +881,7 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
if all or (filter == RTU_UNIT_TYPE.BOILER_VALVE) then
build.boilers = {}
for i = 1, #self.boilers do
- local boiler = self.boilers[i] ---@type unit_session
+ local boiler = self.boilers[i]
build.boilers[boiler.get_device_idx()] = { boiler.get_db().formed, boiler.get_db().build }
end
end
@@ -889,7 +889,7 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
if all or (filter == RTU_UNIT_TYPE.TURBINE_VALVE) then
build.turbines = {}
for i = 1, #self.turbines do
- local turbine = self.turbines[i] ---@type unit_session
+ local turbine = self.turbines[i]
build.turbines[turbine.get_device_idx()] = { turbine.get_db().formed, turbine.get_db().build }
end
end
@@ -897,7 +897,7 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
if all or (filter == RTU_UNIT_TYPE.DYNAMIC_VALVE) then
build.tanks = {}
for i = 1, #self.tanks do
- local tank = self.tanks[i] ---@type unit_session
+ local tank = self.tanks[i]
build.tanks[tank.get_device_idx()] = { tank.get_db().formed, tank.get_db().build }
end
end
@@ -927,6 +927,10 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
-- check which RTUs are connected
---@nodiscard
function public.check_rtu_conns()
+ ---@class unit_connections
+ ---@field boilers boolean[]
+ ---@field turbines boolean[]
+ ---@field tanks boolean[]
local conns = {}
conns.boilers = {}
@@ -955,31 +959,31 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
-- status of boilers (including tanks)
status.boilers = {}
for i = 1, #self.boilers do
- local boiler = self.boilers[i] ---@type unit_session
- local db = boiler.get_db() ---@type boilerv_session_db
+ local boiler = self.boilers[i]
+ local db = boiler.get_db()
status.boilers[boiler.get_device_idx()] = { boiler.is_faulted(), db.formed, db.state, db.tanks }
end
-- status of turbines (including tanks)
status.turbines = {}
for i = 1, #self.turbines do
- local turbine = self.turbines[i] ---@type unit_session
- local db = turbine.get_db() ---@type turbinev_session_db
+ local turbine = self.turbines[i]
+ local db = turbine.get_db()
status.turbines[turbine.get_device_idx()] = { turbine.is_faulted(), db.formed, db.state, db.tanks }
end
-- status of dynamic tanks
status.tanks = {}
for i = 1, #self.tanks do
- local tank = self.tanks[i] ---@type unit_session
- local db = tank.get_db() ---@type dynamicv_session_db
+ local tank = self.tanks[i]
+ local db = tank.get_db()
status.tanks[tank.get_device_idx()] = { tank.is_faulted(), db.formed, db.state, db.tanks }
end
-- SNA statistical information
local total_peak, total_avail, total_out = 0, 0, 0
for i = 1, #self.snas do
- local db = self.snas[i].get_db() ---@type sna_session_db
+ local db = self.snas[i].get_db()
total_peak = total_peak + db.state.peak_production
total_avail = total_avail + db.state.production_rate
total_out = total_out + math.min(db.tanks.input.amount / 10, db.state.production_rate)
@@ -989,8 +993,8 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
-- radiation monitors (environment detectors)
status.envds = {}
for i = 1, #self.envd do
- local envd = self.envd[i] ---@type unit_session
- local db = envd.get_db() ---@type envd_session_db
+ local envd = self.envd[i]
+ local db = envd.get_db()
status.envds[envd.get_device_idx()] = { envd.is_faulted(), db.radiation, db.radiation_raw }
end
@@ -1004,7 +1008,7 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
local total_avail_rate = 0
for i = 1, #self.snas do
- local db = self.snas[i].get_db() ---@type sna_session_db
+ local db = self.snas[i].get_db()
total_avail_rate = total_avail_rate + db.state.production_rate
end
diff --git a/supervisor/unitlogic.lua b/supervisor/unitlogic.lua
index b1e1fc8..f0e4c33 100644
--- a/supervisor/unitlogic.lua
+++ b/supervisor/unitlogic.lua
@@ -161,8 +161,8 @@ function logic.update_annunciator(self)
local max_rad, any_faulted = 0, false
for i = 1, #self.envd do
- local envd = self.envd[i] ---@type unit_session
- local db = envd.get_db() ---@type envd_session_db
+ local envd = self.envd[i]
+ local db = envd.get_db()
any_faulted = any_faulted or envd.is_faulted()
if db.radiation_raw > max_rad then max_rad = db.radiation_raw end
end
@@ -173,8 +173,7 @@ function logic.update_annunciator(self)
annunc.EmergencyCoolant = 1
for i = 1, #self.redstone do
- local db = self.redstone[i].get_db() ---@type redstone_session_db
- local io = db.io[IO.U_EMER_COOL] ---@type rs_db_dig_io|nil
+ local io = self.redstone[i].get_db().io[IO.U_EMER_COOL]
if io ~= nil then
annunc.EmergencyCoolant = util.trinary(io.read(), 3, 2)
break
@@ -197,8 +196,8 @@ function logic.update_annunciator(self)
if num_boilers > 0 then
-- go through boilers for stats and online
for i = 1, #self.boilers do
- local session = self.boilers[i] ---@type unit_session
- local boiler = session.get_db() ---@type boilerv_session_db
+ local session = self.boilers[i]
+ local boiler = session.get_db()
local idx = session.get_device_idx()
annunc.RCSFault = annunc.RCSFault or (not boiler.formed) or session.is_faulted()
@@ -225,9 +224,9 @@ function logic.update_annunciator(self)
-- check for inactive boilers while reactor is active
for i = 1, #self.boilers do
- local boiler = self.boilers[i] ---@type unit_session
+ local boiler = self.boilers[i]
local idx = boiler.get_device_idx()
- local db = boiler.get_db() ---@type boilerv_session_db
+ local db = boiler.get_db()
if r_db.mek_status.status then
annunc.HeatingRateLow[idx] = db.state.boil_rate == 0
@@ -250,9 +249,9 @@ function logic.update_annunciator(self)
if num_boilers > 0 then
for i = 1, #self.boilers do
- local boiler = self.boilers[i] ---@type unit_session
+ local boiler = self.boilers[i]
local idx = boiler.get_device_idx()
- local db = boiler.get_db() ---@type boilerv_session_db
+ local db = boiler.get_db()
local gaining_hc = _get_dt(DT_KEYS.BoilerHCool .. idx) > 10.0 or db.tanks.hcool_fill == 1
@@ -294,8 +293,8 @@ function logic.update_annunciator(self)
-- go through turbines for stats and online
for i = 1, #self.turbines do
- local session = self.turbines[i] ---@type unit_session
- local turbine = session.get_db() ---@type turbinev_session_db
+ local session = self.turbines[i]
+ local turbine = session.get_db()
local idx = session.get_device_idx()
annunc.RCSFault = annunc.RCSFault or (not turbine.formed) or session.is_faulted()
@@ -380,8 +379,8 @@ function logic.update_annunciator(self)
-- turbine safety checks
for i = 1, #self.turbines do
- local turbine = self.turbines[i] ---@type unit_session
- local db = turbine.get_db() ---@type turbinev_session_db
+ local turbine = self.turbines[i]
+ local db = turbine.get_db()
local idx = turbine.get_device_idx()
-- check if steam dumps are open
@@ -652,7 +651,7 @@ function logic.update_status_text(self)
-- check if an alarm is active (tripped or ack'd)
---@nodiscard
- ---@param alarm table alarm entry
+ ---@param alarm alarm_def alarm entry
---@return boolean active
local function is_active(alarm)
return alarm.state == AISTATE.TRIPPED or alarm.state == AISTATE.ACKED
@@ -818,7 +817,7 @@ function logic.handle_redstone(self)
-- check if an alarm is active (tripped or ack'd)
---@nodiscard
- ---@param alarm table alarm entry
+ ---@param alarm alarm_def alarm entry
---@return boolean active
local function is_active(alarm)
return alarm.state == AISTATE.TRIPPED or alarm.state == AISTATE.ACKED
@@ -904,8 +903,8 @@ function logic.handle_redstone(self)
if not cache.rps_trip then
-- set turbines to not dump steam
for i = 1, #self.turbines do
- local session = self.turbines[i] ---@type unit_session
- local turbine = session.get_db() ---@type turbinev_session_db
+ local session = self.turbines[i]
+ local turbine = session.get_db()
if turbine.state.dumping_mode ~= DUMPING_MODE.IDLE then
session.get_cmd_queue().push_data(TBV_RTU_S_DATA.SET_DUMP_MODE, DUMPING_MODE.IDLE)
@@ -921,8 +920,8 @@ function logic.handle_redstone(self)
elseif enable_emer_cool or self.emcool_opened then
-- set turbines to dump excess steam
for i = 1, #self.turbines do
- local session = self.turbines[i] ---@type unit_session
- local turbine = session.get_db() ---@type turbinev_session_db
+ local session = self.turbines[i]
+ local turbine = session.get_db()
if turbine.state.dumping_mode ~= DUMPING_MODE.DUMPING_EXCESS then
session.get_cmd_queue().push_data(TBV_RTU_S_DATA.SET_DUMP_MODE, DUMPING_MODE.DUMPING_EXCESS)
@@ -931,8 +930,8 @@ function logic.handle_redstone(self)
-- make sure dynamic tanks are allowing outflow
for i = 1, #self.tanks do
- local session = self.tanks[i] ---@type unit_session
- local tank = session.get_db() ---@type dynamicv_session_db
+ local session = self.tanks[i]
+ local tank = session.get_db()
if tank.state.container_mode == CONTAINER_MODE.FILL then
session.get_cmd_queue().push_data(DTV_RTU_S_DATA.SET_CONT_MODE, CONTAINER_MODE.BOTH)