diff --git a/coordinator/renderer.lua b/coordinator/renderer.lua
index ffb36bc..fec6629 100644
--- a/coordinator/renderer.lua
+++ b/coordinator/renderer.lua
@@ -138,9 +138,9 @@ function renderer.close_ui()
-- stop blinking indicators
flasher.clear()
- -- hide to stop animation callbacks
- if engine.ui.main_display ~= nil then engine.ui.main_display.hide() end
- for _, display in ipairs(engine.ui.unit_displays) do display.hide() end
+ -- delete element trees
+ if engine.ui.main_display ~= nil then engine.ui.main_display.delete() end
+ for _, display in ipairs(engine.ui.unit_displays) do display.delete() end
-- report ui as not ready
engine.ui_ready = false
diff --git a/coordinator/startup.lua b/coordinator/startup.lua
index 2944c14..2e08061 100644
--- a/coordinator/startup.lua
+++ b/coordinator/startup.lua
@@ -20,7 +20,7 @@ local sounder = require("coordinator.sounder")
local apisessions = require("coordinator.session.apisessions")
-local COORDINATOR_VERSION = "v0.14.0"
+local COORDINATOR_VERSION = "v0.15.0"
local println = util.println
local println_ts = util.println_ts
diff --git a/coordinator/ui/components/boiler.lua b/coordinator/ui/components/boiler.lua
index 9ed497c..114a0bb 100644
--- a/coordinator/ui/components/boiler.lua
+++ b/coordinator/ui/components/boiler.lua
@@ -27,9 +27,9 @@ local function new_view(root, x, y, ps)
local temp = DataIndicator{parent=boiler,x=5,y=3,lu_colors=lu_col,label="Temp:",unit="K",format="%10.2f",value=0,width=22,fg_bg=text_fg_bg}
local boil_r = DataIndicator{parent=boiler,x=5,y=4,lu_colors=lu_col,label="Boil:",unit="mB/t",format="%10.0f",value=0,commas=true,width=22,fg_bg=text_fg_bg}
- ps.subscribe("computed_status", status.update)
- ps.subscribe("temperature", temp.update)
- ps.subscribe("boil_rate", boil_r.update)
+ status.register(ps, "computed_status", status.update)
+ temp.register(ps, "temperature", temp.update)
+ boil_r.register(ps, "boil_rate", boil_r.update)
TextBox{parent=boiler,text="H",x=2,y=5,height=1,width=1,fg_bg=text_fg_bg}
TextBox{parent=boiler,text="W",x=3,y=5,height=1,width=1,fg_bg=text_fg_bg}
@@ -41,10 +41,10 @@ local function new_view(root, x, y, ps)
local steam = VerticalBar{parent=boiler,x=27,y=1,fg_bg=cpair(colors.white,colors.gray),height=4,width=1}
local ccool = VerticalBar{parent=boiler,x=28,y=1,fg_bg=cpair(colors.lightBlue,colors.gray),height=4,width=1}
- ps.subscribe("hcool_fill", hcool.update)
- ps.subscribe("water_fill", water.update)
- ps.subscribe("steam_fill", steam.update)
- ps.subscribe("ccool_fill", ccool.update)
+ hcool.register(ps, "hcool_fill", hcool.update)
+ water.register(ps, "water_fill", water.update)
+ steam.register(ps, "steam_fill", steam.update)
+ ccool.register(ps, "ccool_fill", ccool.update)
end
return new_view
diff --git a/coordinator/ui/components/imatrix.lua b/coordinator/ui/components/imatrix.lua
index c94ff9f..a234cbc 100644
--- a/coordinator/ui/components/imatrix.lua
+++ b/coordinator/ui/components/imatrix.lua
@@ -50,15 +50,15 @@ local function new_view(root, x, y, data, ps, id)
local avg_in = PowerIndicator{parent=rect,x=7,y=9,lu_colors=lu_col,label="Avg. In: ",format="%8.2f",rate=true,value=0,width=26,fg_bg=text_fg_bg}
local avg_out = PowerIndicator{parent=rect,x=7,y=10,lu_colors=lu_col,label="Avg. Out:",format="%8.2f",rate=true,value=0,width=26,fg_bg=text_fg_bg}
- ps.subscribe("computed_status", status.update)
- ps.subscribe("energy", function (val) energy.update(util.joules_to_fe(val)) end)
- ps.subscribe("max_energy", function (val) capacity.update(util.joules_to_fe(val)) end)
- ps.subscribe("last_input", function (val) input.update(util.joules_to_fe(val)) end)
- ps.subscribe("last_output", function (val) output.update(util.joules_to_fe(val)) end)
+ status.register(ps, "computed_status", status.update)
+ energy.register(ps, "energy", function (val) energy.update(util.joules_to_fe(val)) end)
+ capacity.register(ps, "max_energy", function (val) capacity.update(util.joules_to_fe(val)) end)
+ input.register(ps, "last_input", function (val) input.update(util.joules_to_fe(val)) end)
+ output.register(ps, "last_output", function (val) output.update(util.joules_to_fe(val)) end)
- ps.subscribe("avg_charge", avg_chg.update)
- ps.subscribe("avg_inflow", avg_in.update)
- ps.subscribe("avg_outflow", avg_out.update)
+ avg_chg.register(ps, "avg_charge", avg_chg.update)
+ avg_in.register(ps, "avg_inflow", avg_in.update)
+ avg_out.register(ps, "avg_outflow", avg_out.update)
local fill = DataIndicator{parent=rect,x=11,y=12,lu_colors=lu_col,label="Fill:",unit="%",format="%8.2f",value=0,width=18,fg_bg=text_fg_bg}
@@ -68,10 +68,10 @@ local function new_view(root, x, y, data, ps, id)
TextBox{parent=rect,text="Transfer Capacity",x=11,y=17,height=1,width=17,fg_bg=label_fg_bg}
local trans_cap = PowerIndicator{parent=rect,x=19,y=18,lu_colors=lu_col,label="",format="%5.2f",rate=true,value=0,width=12,fg_bg=text_fg_bg}
- ps.subscribe("cells", cells.update)
- ps.subscribe("providers", providers.update)
- ps.subscribe("energy_fill", function (val) fill.update(val * 100) end)
- ps.subscribe("transfer_cap", function (val) trans_cap.update(util.joules_to_fe(val)) end)
+ cells.register(ps, "cells", cells.update)
+ providers.register(ps, "providers", providers.update)
+ fill.register(ps, "energy_fill", function (val) fill.update(val * 100) end)
+ trans_cap.register(ps, "transfer_cap", function (val) trans_cap.update(util.joules_to_fe(val)) end)
local charge = VerticalBar{parent=rect,x=2,y=2,fg_bg=cpair(colors.green,colors.gray),height=17,width=4}
local in_cap = VerticalBar{parent=rect,x=7,y=12,fg_bg=cpair(colors.red,colors.gray),height=7,width=1}
@@ -88,9 +88,9 @@ local function new_view(root, x, y, data, ps, id)
end
end
- ps.subscribe("energy_fill", charge.update)
- ps.subscribe("last_input", function (val) in_cap.update(calc_saturation(val)) end)
- ps.subscribe("last_output", function (val) out_cap.update(calc_saturation(val)) end)
+ charge.register(ps, "energy_fill", charge.update)
+ in_cap.register(ps, "last_input", function (val) in_cap.update(calc_saturation(val)) end)
+ out_cap.register(ps, "last_output", function (val) out_cap.update(calc_saturation(val)) end)
end
return new_view
diff --git a/coordinator/ui/components/processctl.lua b/coordinator/ui/components/processctl.lua
index 8719968..a238a8c 100644
--- a/coordinator/ui/components/processctl.lua
+++ b/coordinator/ui/components/processctl.lua
@@ -55,9 +55,9 @@ local function new_view(root, x, y)
local ind_mat = IndicatorLight{parent=main,label="Induction Matrix",colors=cpair(colors.green,colors.gray)}
local rad_mon = TriIndicatorLight{parent=main,label="Radiation Monitor",c1=colors.gray,c2=colors.yellow,c3=colors.green}
- facility.ps.subscribe("all_sys_ok", all_ok.update)
- facility.induction_ps_tbl[1].subscribe("computed_status", function (status) ind_mat.update(status > 1) end)
- facility.ps.subscribe("rad_computed_status", rad_mon.update)
+ all_ok.register(facility.ps, "all_sys_ok", all_ok.update)
+ ind_mat.register(facility.induction_ps_tbl[1], "computed_status", function (status) ind_mat.update(status > 1) end)
+ rad_mon.register(facility.ps, "rad_computed_status", rad_mon.update)
main.line_break()
@@ -66,10 +66,10 @@ local function new_view(root, x, y)
local auto_ramp = IndicatorLight{parent=main,label="Process Ramping",colors=cpair(colors.white,colors.gray),flash=true,period=period.BLINK_250_MS}
local auto_sat = IndicatorLight{parent=main,label="Min/Max Burn Rate",colors=cpair(colors.yellow,colors.gray)}
- facility.ps.subscribe("auto_ready", auto_ready.update)
- facility.ps.subscribe("auto_active", auto_act.update)
- facility.ps.subscribe("auto_ramping", auto_ramp.update)
- facility.ps.subscribe("auto_saturated", auto_sat.update)
+ auto_ready.register(facility.ps, "auto_ready", auto_ready.update)
+ auto_act.register(facility.ps, "auto_active", auto_act.update)
+ auto_ramp.register(facility.ps, "auto_ramping", auto_ramp.update)
+ auto_sat.register(facility.ps, "auto_saturated", auto_sat.update)
main.line_break()
@@ -80,20 +80,20 @@ local function new_view(root, x, y)
local fac_rad_h = IndicatorLight{parent=main,label="Facility Radiation High",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS}
local gen_fault = IndicatorLight{parent=main,label="Gen. Control Fault",colors=cpair(colors.yellow,colors.gray),flash=true,period=period.BLINK_500_MS}
- facility.ps.subscribe("auto_scram", auto_scram.update)
- facility.ps.subscribe("as_matrix_dc", matrix_dc.update)
- facility.ps.subscribe("as_matrix_fill", matrix_fill.update)
- facility.ps.subscribe("as_crit_alarm", unit_crit.update)
- facility.ps.subscribe("as_radiation", fac_rad_h.update)
- facility.ps.subscribe("as_gen_fault", gen_fault.update)
+ auto_scram.register(facility.ps, "auto_scram", auto_scram.update)
+ matrix_dc.register(facility.ps, "as_matrix_dc", matrix_dc.update)
+ matrix_fill.register(facility.ps, "as_matrix_fill", matrix_fill.update)
+ unit_crit.register(facility.ps, "as_crit_alarm", unit_crit.update)
+ fac_rad_h.register(facility.ps, "as_radiation", fac_rad_h.update)
+ gen_fault.register(facility.ps, "as_gen_fault", gen_fault.update)
TextBox{parent=main,y=23,text="Radiation",height=1,width=13,fg_bg=style.label}
local radiation = RadIndicator{parent=main,label="",format="%9.3f",lu_colors=lu_cpair,width=13,fg_bg=bw_fg_bg}
- facility.ps.subscribe("radiation", radiation.update)
+ radiation.register(facility.ps, "radiation", radiation.update)
TextBox{parent=main,x=15,y=23,text="Linked RTUs",height=1,width=11,fg_bg=style.label}
local rtu_count = DataIndicator{parent=main,x=15,y=24,label="",format="%11d",value=0,lu_colors=lu_cpair,width=11,fg_bg=bw_fg_bg}
- facility.ps.subscribe("rtu_count", rtu_count.update)
+ rtu_count.register(facility.ps, "rtu_count", rtu_count.update)
---------------------
-- process control --
@@ -115,8 +115,8 @@ local function new_view(root, x, y)
TextBox{parent=burn_target,x=18,y=2,text="mB/t"}
local burn_sum = DataIndicator{parent=targets,x=9,y=4,label="",format="%18.1f",value=0,unit="mB/t",commas=true,lu_colors=cpair(colors.black,colors.black),width=23,fg_bg=cpair(colors.black,colors.brown)}
- facility.ps.subscribe("process_burn_target", b_target.set_value)
- facility.ps.subscribe("burn_sum", burn_sum.update)
+ b_target.register(facility.ps, "process_burn_target", b_target.set_value)
+ burn_sum.register(facility.ps, "burn_sum", burn_sum.update)
local chg_tag = Div{parent=targets,x=1,y=6,width=8,height=4,fg_bg=cpair(colors.black,colors.purple)}
TextBox{parent=chg_tag,x=2,y=2,text="Charge Target",width=7,height=2}
@@ -126,8 +126,8 @@ local function new_view(root, x, y)
TextBox{parent=chg_target,x=18,y=2,text="MFE"}
local cur_charge = DataIndicator{parent=targets,x=9,y=9,label="",format="%19d",value=0,unit="MFE",commas=true,lu_colors=cpair(colors.black,colors.black),width=23,fg_bg=cpair(colors.black,colors.brown)}
- facility.ps.subscribe("process_charge_target", c_target.set_value)
- facility.induction_ps_tbl[1].subscribe("energy", function (j) cur_charge.update(util.joules_to_fe(j) / 1000000) end)
+ c_target.register(facility.ps, "process_charge_target", c_target.set_value)
+ cur_charge.register(facility.induction_ps_tbl[1], "energy", function (j) cur_charge.update(util.joules_to_fe(j) / 1000000) end)
local gen_tag = Div{parent=targets,x=1,y=11,width=8,height=4,fg_bg=cpair(colors.black,colors.purple)}
TextBox{parent=gen_tag,x=2,y=2,text="Gen. Target",width=7,height=2}
@@ -137,8 +137,8 @@ local function new_view(root, x, y)
TextBox{parent=gen_target,x=18,y=2,text="kFE/t"}
local cur_gen = DataIndicator{parent=targets,x=9,y=14,label="",format="%17d",value=0,unit="kFE/t",commas=true,lu_colors=cpair(colors.black,colors.black),width=23,fg_bg=cpair(colors.black,colors.brown)}
- facility.ps.subscribe("process_gen_target", g_target.set_value)
- facility.induction_ps_tbl[1].subscribe("last_input", function (j) cur_gen.update(util.round(util.joules_to_fe(j) / 1000)) end)
+ g_target.register(facility.ps, "process_gen_target", g_target.set_value)
+ cur_gen.register(facility.induction_ps_tbl[1], "last_input", function (j) cur_gen.update(util.round(util.joules_to_fe(j) / 1000)) end)
-----------------
-- unit limits --
@@ -160,12 +160,12 @@ local function new_view(root, x, y)
rate_limits[i] = SpinboxNumeric{parent=lim_ctl,x=2,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=cpair(colors.gray,colors.white),fg_bg=bw_fg_bg}
TextBox{parent=lim_ctl,x=9,y=2,text="mB/t",width=4,height=1}
- unit.unit_ps.subscribe("max_burn", rate_limits[i].set_max)
- unit.unit_ps.subscribe("burn_limit", rate_limits[i].set_value)
+ rate_limits[i].register(unit.unit_ps, "max_burn", rate_limits[i].set_max)
+ rate_limits[i].register(unit.unit_ps, "burn_limit", rate_limits[i].set_value)
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(colors.black,colors.black),width=14,fg_bg=cpair(colors.black,colors.brown)}
- unit.unit_ps.subscribe("act_burn_rate", cur_burn.update)
+ cur_burn.register(unit.unit_ps, "act_burn_rate", cur_burn.update)
end
-------------------
@@ -186,8 +186,8 @@ local function new_view(root, x, y)
local ready = IndicatorLight{parent=lights,x=2,y=2,label="Ready",colors=cpair(colors.green,colors.gray)}
local degraded = IndicatorLight{parent=lights,x=2,y=3,label="Degraded",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS}
- unit.unit_ps.subscribe("U_AutoReady", ready.update)
- unit.unit_ps.subscribe("U_AutoDegraded", degraded.update)
+ ready.register(unit.unit_ps, "U_AutoReady", ready.update)
+ degraded.register(unit.unit_ps, "U_AutoDegraded", degraded.update)
end
-------------------------
@@ -197,14 +197,14 @@ local function new_view(root, x, y)
local ctl_opts = { "Monitored Max Burn", "Combined Burn Rate", "Charge Level", "Generation Rate" }
local mode = RadioButton{parent=proc,x=34,y=1,options=ctl_opts,callback=function()end,radio_colors=cpair(colors.purple,colors.black),radio_bg=colors.gray}
- facility.ps.subscribe("process_mode", mode.set_value)
+ mode.register(facility.ps, "process_mode", mode.set_value)
local u_stat = Rectangle{parent=proc,border=border(1,colors.gray,true),thin=true,width=31,height=4,x=1,y=16,fg_bg=bw_fg_bg}
local stat_line_1 = TextBox{parent=u_stat,x=1,y=1,text="UNKNOWN",width=31,height=1,alignment=TEXT_ALIGN.CENTER,fg_bg=bw_fg_bg}
local stat_line_2 = TextBox{parent=u_stat,x=1,y=2,text="awaiting data...",width=31,height=1,alignment=TEXT_ALIGN.CENTER,fg_bg=cpair(colors.gray, colors.white)}
- facility.ps.subscribe("status_line_1", stat_line_1.set_value)
- facility.ps.subscribe("status_line_2", stat_line_2.set_value)
+ stat_line_1.register(facility.ps, "status_line_1", stat_line_1.set_value)
+ stat_line_2.register(facility.ps, "status_line_2", stat_line_2.set_value)
local auto_controls = Div{parent=proc,x=1,y=20,width=31,height=5,fg_bg=cpair(colors.gray,colors.white)}
@@ -233,11 +233,14 @@ local function new_view(root, x, y)
tcd.dispatch(0.2, function () save.on_response(ack) end)
end
- facility.ps.subscribe("auto_ready", function (ready)
+ start.register(facility.ps, "auto_ready", function (ready)
if ready and (not facility.auto_active) then start.enable() else start.disable() end
end)
- facility.ps.subscribe("auto_active", function (active)
+ -- REGISTER_NOTE: for optimization/brevity, due to not deleting anything but the whole element tree when it comes
+ -- to the process control display and coordinator GUI as a whole, child elements will not directly be registered here
+ -- (preventing garbage collection until the parent 'proc' is deleted)
+ proc.register(facility.ps, "auto_active", function (active)
if active then
b_target.disable()
c_target.disable()
@@ -246,9 +249,7 @@ local function new_view(root, x, y)
mode.disable()
start.disable()
- for i = 1, #rate_limits do
- rate_limits[i].disable()
- end
+ for i = 1, #rate_limits do rate_limits[i].disable() end
else
b_target.enable()
c_target.enable()
@@ -257,9 +258,7 @@ local function new_view(root, x, y)
mode.enable()
if facility.auto_ready then start.enable() end
- for i = 1, #rate_limits do
- rate_limits[i].enable()
- end
+ for i = 1, #rate_limits do rate_limits[i].enable() end
end
end)
end
diff --git a/coordinator/ui/components/reactor.lua b/coordinator/ui/components/reactor.lua
index 578bbba..b4a2c1b 100644
--- a/coordinator/ui/components/reactor.lua
+++ b/coordinator/ui/components/reactor.lua
@@ -30,10 +30,10 @@ local function new_view(root, x, y, ps)
local burn_r = DataIndicator{parent=reactor,x=2,y=4,lu_colors=lu_col,label="Burn Rate:",unit="mB/t",format="%10.2f",value=0,width=26,fg_bg=text_fg_bg}
local heating_r = DataIndicator{parent=reactor,x=2,y=5,lu_colors=lu_col,label="Heating:",unit="mB/t",format="%12.0f",value=0,commas=true,width=26,fg_bg=text_fg_bg}
- ps.subscribe("computed_status", status.update)
- ps.subscribe("temp", core_temp.update)
- ps.subscribe("act_burn_rate", burn_r.update)
- ps.subscribe("heating_rate", heating_r.update)
+ status.register(ps, "computed_status", status.update)
+ core_temp.register(ps, "temp", core_temp.update)
+ burn_r.register(ps, "act_burn_rate", burn_r.update)
+ heating_r.register(ps, "heating_rate", heating_r.update)
local reactor_fills = Rectangle{parent=root,border=border(1, colors.gray, true),width=24,height=7,x=(x + 29),y=y}
@@ -47,7 +47,7 @@ local function new_view(root, x, y, ps)
local hcool = HorizontalBar{parent=reactor_fills,x=8,y=4,show_percent=true,bar_fg_bg=cpair(colors.white,colors.gray),height=1,width=14}
local waste = HorizontalBar{parent=reactor_fills,x=8,y=5,show_percent=true,bar_fg_bg=cpair(colors.brown,colors.gray),height=1,width=14}
- ps.subscribe("ccool_type", function (type)
+ ccool.register(ps, "ccool_type", function (type)
if type == types.FLUID.SODIUM then
ccool.recolor(cpair(colors.lightBlue, colors.gray))
else
@@ -55,7 +55,7 @@ local function new_view(root, x, y, ps)
end
end)
- ps.subscribe("hcool_type", function (type)
+ hcool.register(ps, "hcool_type", function (type)
if type == types.FLUID.SUPERHEATED_SODIUM then
hcool.recolor(cpair(colors.orange, colors.gray))
else
@@ -63,10 +63,10 @@ local function new_view(root, x, y, ps)
end
end)
- ps.subscribe("fuel_fill", fuel.update)
- ps.subscribe("ccool_fill", ccool.update)
- ps.subscribe("hcool_fill", hcool.update)
- ps.subscribe("waste_fill", waste.update)
+ fuel.register(ps, "fuel_fill", fuel.update)
+ ccool.register(ps, "ccool_fill", ccool.update)
+ hcool.register(ps, "hcool_fill", hcool.update)
+ waste.register(ps, "waste_fill", waste.update)
end
return new_view
diff --git a/coordinator/ui/components/turbine.lua b/coordinator/ui/components/turbine.lua
index 3bfd731..0e4cb21 100644
--- a/coordinator/ui/components/turbine.lua
+++ b/coordinator/ui/components/turbine.lua
@@ -30,9 +30,9 @@ local function new_view(root, x, y, ps)
local prod_rate = PowerIndicator{parent=turbine,x=5,y=3,lu_colors=lu_col,label="",format="%10.2f",value=0,rate=true,width=16,fg_bg=text_fg_bg}
local flow_rate = DataIndicator{parent=turbine,x=5,y=4,lu_colors=lu_col,label="",unit="mB/t",format="%10.0f",value=0,commas=true,width=16,fg_bg=text_fg_bg}
- ps.subscribe("computed_status", status.update)
- ps.subscribe("prod_rate", function (val) prod_rate.update(util.joules_to_fe(val)) end)
- ps.subscribe("flow_rate", flow_rate.update)
+ status.register(ps, "computed_status", status.update)
+ prod_rate.register(ps, "prod_rate", function (val) prod_rate.update(util.joules_to_fe(val)) end)
+ flow_rate.register(ps, "flow_rate", flow_rate.update)
local steam = VerticalBar{parent=turbine,x=2,y=1,fg_bg=cpair(colors.white,colors.gray),height=4,width=1}
local energy = VerticalBar{parent=turbine,x=3,y=1,fg_bg=cpair(colors.green,colors.gray),height=4,width=1}
@@ -40,8 +40,8 @@ local function new_view(root, x, y, ps)
TextBox{parent=turbine,text="S",x=2,y=5,height=1,width=1,fg_bg=text_fg_bg}
TextBox{parent=turbine,text="E",x=3,y=5,height=1,width=1,fg_bg=text_fg_bg}
- ps.subscribe("steam_fill", steam.update)
- ps.subscribe("energy_fill", energy.update)
+ steam.register(ps, "steam_fill", steam.update)
+ energy.register(ps, "energy_fill", energy.update)
end
return new_view
diff --git a/coordinator/ui/components/unit_detail.lua b/coordinator/ui/components/unit_detail.lua
index 7181430..30e2044 100644
--- a/coordinator/ui/components/unit_detail.lua
+++ b/coordinator/ui/components/unit_detail.lua
@@ -79,16 +79,16 @@ local function init(parent, id)
-----------------------------
local core_map = CoreMap{parent=main,x=2,y=3,reactor_l=18,reactor_w=18}
- u_ps.subscribe("temp", core_map.update)
- u_ps.subscribe("size", function (s) core_map.resize(s[1], s[2]) end)
+ core_map.register(u_ps, "temp", core_map.update)
+ core_map.register(u_ps, "size", function (s) core_map.resize(s[1], s[2]) end)
TextBox{parent=main,x=12,y=22,text="Heating Rate",height=1,width=12,fg_bg=style.label}
local heating_r = DataIndicator{parent=main,x=12,label="",format="%14.0f",value=0,unit="mB/t",commas=true,lu_colors=lu_cpair,width=19,fg_bg=bw_fg_bg}
- u_ps.subscribe("heating_rate", heating_r.update)
+ heating_r.register(u_ps, "heating_rate", heating_r.update)
TextBox{parent=main,x=12,y=25,text="Commanded Burn Rate",height=1,width=19,fg_bg=style.label}
local burn_r = DataIndicator{parent=main,x=12,label="",format="%14.2f",value=0,unit="mB/t",lu_colors=lu_cpair,width=19,fg_bg=bw_fg_bg}
- u_ps.subscribe("burn_rate", burn_r.update)
+ burn_r.register(u_ps, "burn_rate", burn_r.update)
TextBox{parent=main,text="F",x=2,y=22,width=1,height=1,fg_bg=style.label}
TextBox{parent=main,text="C",x=4,y=22,width=1,height=1,fg_bg=style.label}
@@ -102,12 +102,12 @@ local function init(parent, id)
local hcool = VerticalBar{parent=main,x=8,y=23,fg_bg=cpair(colors.white,colors.gray),height=4,width=1}
local waste = VerticalBar{parent=main,x=10,y=23,fg_bg=cpair(colors.brown,colors.gray),height=4,width=1}
- u_ps.subscribe("fuel_fill", fuel.update)
- u_ps.subscribe("ccool_fill", ccool.update)
- u_ps.subscribe("hcool_fill", hcool.update)
- u_ps.subscribe("waste_fill", waste.update)
+ fuel.register(u_ps, "fuel_fill", fuel.update)
+ ccool.register(u_ps, "ccool_fill", ccool.update)
+ hcool.register(u_ps, "hcool_fill", hcool.update)
+ waste.register(u_ps, "waste_fill", waste.update)
- u_ps.subscribe("ccool_type", function (type)
+ ccool.register(u_ps, "ccool_type", function (type)
if type == "mekanism:sodium" then
ccool.recolor(cpair(colors.lightBlue, colors.gray))
else
@@ -115,7 +115,7 @@ local function init(parent, id)
end
end)
- u_ps.subscribe("hcool_type", function (type)
+ hcool.register(u_ps, "hcool_type", function (type)
if type == "mekanism:superheated_sodium" then
hcool.recolor(cpair(colors.orange, colors.gray))
else
@@ -125,19 +125,19 @@ local function init(parent, id)
TextBox{parent=main,x=32,y=22,text="Core Temp",height=1,width=9,fg_bg=style.label}
local core_temp = DataIndicator{parent=main,x=32,label="",format="%11.2f",value=0,unit="K",lu_colors=lu_cpair,width=13,fg_bg=bw_fg_bg}
- u_ps.subscribe("temp", core_temp.update)
+ core_temp.register(u_ps, "temp", core_temp.update)
TextBox{parent=main,x=32,y=25,text="Burn Rate",height=1,width=9,fg_bg=style.label}
local act_burn_r = DataIndicator{parent=main,x=32,label="",format="%8.2f",value=0,unit="mB/t",lu_colors=lu_cpair,width=13,fg_bg=bw_fg_bg}
- u_ps.subscribe("act_burn_rate", act_burn_r.update)
+ act_burn_r.register(u_ps, "act_burn_rate", act_burn_r.update)
TextBox{parent=main,x=32,y=28,text="Damage",height=1,width=6,fg_bg=style.label}
local damage_p = DataIndicator{parent=main,x=32,label="",format="%11.0f",value=0,unit="%",lu_colors=lu_cpair,width=13,fg_bg=bw_fg_bg}
- u_ps.subscribe("damage", damage_p.update)
+ damage_p.register(u_ps, "damage", damage_p.update)
TextBox{parent=main,x=32,y=31,text="Radiation",height=1,width=21,fg_bg=style.label}
local radiation = RadIndicator{parent=main,x=32,label="",format="%9.3f",lu_colors=lu_cpair,width=13,fg_bg=bw_fg_bg}
- u_ps.subscribe("radiation", radiation.update)
+ radiation.register(u_ps, "radiation", radiation.update)
-------------------
-- system status --
@@ -147,8 +147,8 @@ local function init(parent, id)
local stat_line_1 = TextBox{parent=u_stat,x=1,y=1,text="UNKNOWN",width=33,height=1,alignment=TEXT_ALIGN.CENTER,fg_bg=bw_fg_bg}
local stat_line_2 = TextBox{parent=u_stat,x=1,y=2,text="awaiting data...",width=33,height=1,alignment=TEXT_ALIGN.CENTER,fg_bg=cpair(colors.gray, colors.white)}
- u_ps.subscribe("U_StatusLine1", stat_line_1.set_value)
- u_ps.subscribe("U_StatusLine2", stat_line_2.set_value)
+ stat_line_1.register(u_ps, "U_StatusLine1", stat_line_1.set_value)
+ stat_line_2.register(u_ps, "U_StatusLine2", stat_line_2.set_value)
-----------------
-- annunciator --
@@ -163,9 +163,9 @@ local function init(parent, id)
local plc_hbeat = IndicatorLight{parent=annunciator,label="PLC Heartbeat",colors=cpair(colors.white,colors.gray)}
local rad_mon = TriIndicatorLight{parent=annunciator,label="Radiation Monitor",c1=colors.gray,c2=colors.yellow,c3=colors.green}
- u_ps.subscribe("PLCOnline", plc_online.update)
- u_ps.subscribe("PLCHeartbeat", plc_hbeat.update)
- u_ps.subscribe("RadiationMonitor", rad_mon.update)
+ plc_online.register(u_ps, "PLCOnline", plc_online.update)
+ plc_hbeat.register(u_ps, "PLCHeartbeat", plc_hbeat.update)
+ rad_mon.register(u_ps, "RadiationMonitor", rad_mon.update)
annunciator.line_break()
@@ -173,8 +173,8 @@ local function init(parent, id)
local r_active = IndicatorLight{parent=annunciator,label="Active",colors=cpair(colors.green,colors.gray)}
local r_auto = IndicatorLight{parent=annunciator,label="Automatic Control",colors=cpair(colors.white,colors.gray)}
- u_ps.subscribe("status", r_active.update)
- u_ps.subscribe("AutoControl", r_auto.update)
+ r_active.register(u_ps, "status", r_active.update)
+ r_auto.register(u_ps, "AutoControl", r_auto.update)
-- main unit transient/warning annunciator panel
local r_scram = IndicatorLight{parent=annunciator,label="Reactor SCRAM",colors=cpair(colors.red,colors.gray)}
@@ -190,18 +190,18 @@ local function init(parent, id)
local r_wloc = IndicatorLight{parent=annunciator,label="Waste Line Occlusion",colors=cpair(colors.yellow,colors.gray)}
local r_hsrt = IndicatorLight{parent=annunciator,label="Startup Rate High",colors=cpair(colors.yellow,colors.gray)}
- u_ps.subscribe("ReactorSCRAM", r_scram.update)
- u_ps.subscribe("ManualReactorSCRAM", r_mscrm.update)
- u_ps.subscribe("AutoReactorSCRAM", r_ascrm.update)
- u_ps.subscribe("RadiationWarning", rad_wrn.update)
- u_ps.subscribe("RCPTrip", r_rtrip.update)
- u_ps.subscribe("RCSFlowLow", r_cflow.update)
- u_ps.subscribe("CoolantLevelLow", r_clow.update)
- u_ps.subscribe("ReactorTempHigh", r_temp.update)
- u_ps.subscribe("ReactorHighDeltaT", r_rhdt.update)
- u_ps.subscribe("FuelInputRateLow", r_firl.update)
- u_ps.subscribe("WasteLineOcclusion", r_wloc.update)
- u_ps.subscribe("HighStartupRate", r_hsrt.update)
+ r_scram.register(u_ps, "ReactorSCRAM", r_scram.update)
+ r_mscrm.register(u_ps, "ManualReactorSCRAM", r_mscrm.update)
+ r_ascrm.register(u_ps, "AutoReactorSCRAM", r_ascrm.update)
+ rad_wrn.register(u_ps, "RadiationWarning", rad_wrn.update)
+ r_rtrip.register(u_ps, "RCPTrip", r_rtrip.update)
+ r_cflow.register(u_ps, "RCSFlowLow", r_cflow.update)
+ r_clow.register(u_ps, "CoolantLevelLow", r_clow.update)
+ r_temp.register(u_ps, "ReactorTempHigh", r_temp.update)
+ r_rhdt.register(u_ps, "ReactorHighDeltaT", r_rhdt.update)
+ r_firl.register(u_ps, "FuelInputRateLow", r_firl.update)
+ r_wloc.register(u_ps, "WasteLineOcclusion", r_wloc.update)
+ r_hsrt.register(u_ps, "HighStartupRate", r_hsrt.update)
-- RPS annunciator panel
@@ -220,16 +220,16 @@ local function init(parent, id)
local rps_tmo = IndicatorLight{parent=rps_annunc,label="Connection Timeout",colors=cpair(colors.yellow,colors.gray),flash=true,period=period.BLINK_500_MS}
local rps_sfl = IndicatorLight{parent=rps_annunc,label="System Failure",colors=cpair(colors.orange,colors.gray),flash=true,period=period.BLINK_500_MS}
- u_ps.subscribe("rps_tripped", rps_trp.update)
- u_ps.subscribe("high_dmg", rps_dmg.update)
- u_ps.subscribe("ex_hcool", rps_exh.update)
- u_ps.subscribe("ex_waste", rps_exw.update)
- u_ps.subscribe("high_temp", rps_tmp.update)
- u_ps.subscribe("no_fuel", rps_nof.update)
- u_ps.subscribe("low_cool", rps_loc.update)
- u_ps.subscribe("fault", rps_flt.update)
- u_ps.subscribe("timeout", rps_tmo.update)
- u_ps.subscribe("sys_fail", rps_sfl.update)
+ rps_trp.register(u_ps, "rps_tripped", rps_trp.update)
+ rps_dmg.register(u_ps, "high_dmg", rps_dmg.update)
+ rps_exh.register(u_ps, "ex_hcool", rps_exh.update)
+ rps_exw.register(u_ps, "ex_waste", rps_exw.update)
+ rps_tmp.register(u_ps, "high_temp", rps_tmp.update)
+ rps_nof.register(u_ps, "no_fuel", rps_nof.update)
+ rps_loc.register(u_ps, "low_cool", rps_loc.update)
+ rps_flt.register(u_ps, "fault", rps_flt.update)
+ rps_tmo.register(u_ps, "timeout", rps_tmo.update)
+ rps_sfl.register(u_ps, "sys_fail", rps_sfl.update)
-- cooling annunciator panel
@@ -245,12 +245,12 @@ local function init(parent, id)
local c_sfm = IndicatorLight{parent=rcs_annunc,label="Steam Feed Mismatch",colors=cpair(colors.yellow,colors.gray)}
local c_mwrf = IndicatorLight{parent=rcs_annunc,label="Max Water Return Feed",colors=cpair(colors.yellow,colors.gray)}
- u_ps.subscribe("RCSFault", c_flt.update)
- u_ps.subscribe("EmergencyCoolant", c_emg.update)
- u_ps.subscribe("CoolantFeedMismatch", c_cfm.update)
- u_ps.subscribe("BoilRateMismatch", c_brm.update)
- u_ps.subscribe("SteamFeedMismatch", c_sfm.update)
- u_ps.subscribe("MaxWaterReturnFeed", c_mwrf.update)
+ c_flt.register(u_ps, "RCSFault", c_flt.update)
+ c_emg.register(u_ps, "EmergencyCoolant", c_emg.update)
+ c_cfm.register(u_ps, "CoolantFeedMismatch", c_cfm.update)
+ c_brm.register(u_ps, "BoilRateMismatch", c_brm.update)
+ c_sfm.register(u_ps, "SteamFeedMismatch", c_sfm.update)
+ c_mwrf.register(u_ps, "MaxWaterReturnFeed", c_mwrf.update)
local available_space = 16 - (unit.num_boilers * 2 + unit.num_turbines * 4)
@@ -267,11 +267,11 @@ local function init(parent, id)
if unit.num_boilers > 0 then
TextBox{parent=rcs_tags,x=1,text="B1",width=2,height=1,fg_bg=bw_fg_bg}
local b1_wll = IndicatorLight{parent=rcs_annunc,label="Water Level Low",colors=cpair(colors.red,colors.gray)}
- b_ps[1].subscribe("WasterLevelLow", b1_wll.update)
+ b1_wll.register(b_ps[1], "WasterLevelLow", b1_wll.update)
TextBox{parent=rcs_tags,text="B1",width=2,height=1,fg_bg=bw_fg_bg}
local b1_hr = IndicatorLight{parent=rcs_annunc,label="Heating Rate Low",colors=cpair(colors.yellow,colors.gray)}
- b_ps[1].subscribe("HeatingRateLow", b1_hr.update)
+ b1_hr.register(b_ps[1], "HeatingRateLow", b1_hr.update)
end
if unit.num_boilers > 1 then
-- note, can't (shouldn't for sure...) have 0 turbines
@@ -283,11 +283,11 @@ local function init(parent, id)
TextBox{parent=rcs_tags,text="B2",width=2,height=1,fg_bg=bw_fg_bg}
local b2_wll = IndicatorLight{parent=rcs_annunc,label="Water Level Low",colors=cpair(colors.red,colors.gray)}
- b_ps[2].subscribe("WasterLevelLow", b2_wll.update)
+ b2_wll.register(b_ps[2], "WasterLevelLow", b2_wll.update)
TextBox{parent=rcs_tags,text="B2",width=2,height=1,fg_bg=bw_fg_bg}
local b2_hr = IndicatorLight{parent=rcs_annunc,label="Heating Rate Low",colors=cpair(colors.yellow,colors.gray)}
- b_ps[2].subscribe("HeatingRateLow", b2_hr.update)
+ b2_hr.register(b_ps[2], "HeatingRateLow", b2_hr.update)
end
-- turbine annunciator panels
@@ -296,19 +296,19 @@ local function init(parent, id)
TextBox{parent=rcs_tags,text="T1",width=2,height=1,fg_bg=bw_fg_bg}
local t1_sdo = TriIndicatorLight{parent=rcs_annunc,label="Steam Relief Valve Open",c1=colors.gray,c2=colors.yellow,c3=colors.red}
- t_ps[1].subscribe("SteamDumpOpen", t1_sdo.update)
+ t1_sdo.register(t_ps[1], "SteamDumpOpen", t1_sdo.update)
TextBox{parent=rcs_tags,text="T1",width=2,height=1,fg_bg=bw_fg_bg}
local t1_tos = IndicatorLight{parent=rcs_annunc,label="Turbine Over Speed",colors=cpair(colors.red,colors.gray)}
- t_ps[1].subscribe("TurbineOverSpeed", t1_tos.update)
+ t1_tos.register(t_ps[1], "TurbineOverSpeed", t1_tos.update)
TextBox{parent=rcs_tags,text="T1",width=2,height=1,fg_bg=bw_fg_bg}
local t1_gtrp = IndicatorLight{parent=rcs_annunc,label="Generator Trip",colors=cpair(colors.yellow,colors.gray),flash=true,period=period.BLINK_250_MS}
- t_ps[1].subscribe("GeneratorTrip", t1_gtrp.update)
+ t1_gtrp.register(t_ps[1], "GeneratorTrip", t1_gtrp.update)
TextBox{parent=rcs_tags,text="T1",width=2,height=1,fg_bg=bw_fg_bg}
local t1_trp = IndicatorLight{parent=rcs_annunc,label="Turbine Trip",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS}
- t_ps[1].subscribe("TurbineTrip", t1_trp.update)
+ t1_trp.register(t_ps[1], "TurbineTrip", t1_trp.update)
if unit.num_turbines > 1 then
if (available_space > 2 and unit.num_turbines == 2) or available_space > 3 then
@@ -317,19 +317,19 @@ local function init(parent, id)
TextBox{parent=rcs_tags,text="T2",width=2,height=1,fg_bg=bw_fg_bg}
local t2_sdo = TriIndicatorLight{parent=rcs_annunc,label="Steam Relief Valve Open",c1=colors.gray,c2=colors.yellow,c3=colors.red}
- t_ps[2].subscribe("SteamDumpOpen", t2_sdo.update)
+ t2_sdo.register(t_ps[2], "SteamDumpOpen", t2_sdo.update)
TextBox{parent=rcs_tags,text="T2",width=2,height=1,fg_bg=bw_fg_bg}
local t2_tos = IndicatorLight{parent=rcs_annunc,label="Turbine Over Speed",colors=cpair(colors.red,colors.gray)}
- t_ps[2].subscribe("TurbineOverSpeed", t2_tos.update)
+ t2_tos.register(t_ps[2], "TurbineOverSpeed", t2_tos.update)
TextBox{parent=rcs_tags,text="T2",width=2,height=1,fg_bg=bw_fg_bg}
local t2_gtrp = IndicatorLight{parent=rcs_annunc,label="Generator Trip",colors=cpair(colors.yellow,colors.gray),flash=true,period=period.BLINK_250_MS}
- t_ps[2].subscribe("GeneratorTrip", t2_gtrp.update)
+ t2_gtrp.register(t_ps[2], "GeneratorTrip", t2_gtrp.update)
TextBox{parent=rcs_tags,text="T2",width=2,height=1,fg_bg=bw_fg_bg}
local t2_trp = IndicatorLight{parent=rcs_annunc,label="Turbine Trip",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS}
- t_ps[2].subscribe("TurbineTrip", t2_trp.update)
+ t2_trp.register(t_ps[2], "TurbineTrip", t2_trp.update)
end
if unit.num_turbines > 2 then
@@ -337,19 +337,19 @@ local function init(parent, id)
TextBox{parent=rcs_tags,text="T3",width=2,height=1,fg_bg=bw_fg_bg}
local t3_sdo = TriIndicatorLight{parent=rcs_annunc,label="Steam Relief Valve Open",c1=colors.gray,c2=colors.yellow,c3=colors.red}
- t_ps[3].subscribe("SteamDumpOpen", t3_sdo.update)
+ t3_sdo.register(t_ps[3], "SteamDumpOpen", t3_sdo.update)
TextBox{parent=rcs_tags,text="T3",width=2,height=1,fg_bg=bw_fg_bg}
local t3_tos = IndicatorLight{parent=rcs_annunc,label="Turbine Over Speed",colors=cpair(colors.red,colors.gray)}
- t_ps[3].subscribe("TurbineOverSpeed", t3_tos.update)
+ t3_tos.register(t_ps[3], "TurbineOverSpeed", t3_tos.update)
TextBox{parent=rcs_tags,text="T3",width=2,height=1,fg_bg=bw_fg_bg}
local t3_gtrp = IndicatorLight{parent=rcs_annunc,label="Generator Trip",colors=cpair(colors.yellow,colors.gray),flash=true,period=period.BLINK_250_MS}
- t_ps[3].subscribe("GeneratorTrip", t3_gtrp.update)
+ t3_gtrp.register(t_ps[3], "GeneratorTrip", t3_gtrp.update)
TextBox{parent=rcs_tags,text="T3",width=2,height=1,fg_bg=bw_fg_bg}
local t3_trp = IndicatorLight{parent=rcs_annunc,label="Turbine Trip",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS}
- t_ps[3].subscribe("TurbineTrip", t3_trp.update)
+ t3_trp.register(t_ps[3], "TurbineTrip", t3_trp.update)
end
----------------------
@@ -365,8 +365,8 @@ local function init(parent, id)
local set_burn = function () unit.set_burn(burn_rate.get_value()) end
local set_burn_btn = PushButton{parent=burn_control,x=14,y=2,text="SET",min_width=5,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),dis_fg_bg=dis_colors,callback=set_burn}
- u_ps.subscribe("burn_rate", burn_rate.set_value)
- u_ps.subscribe("max_burn", burn_rate.set_max)
+ burn_rate.register(u_ps, "burn_rate", burn_rate.set_value)
+ burn_rate.register(u_ps, "max_burn", burn_rate.set_max)
local start = HazardButton{parent=main,x=2,y=28,text="START",accent=colors.lightBlue,dis_colors=dis_colors,callback=unit.start,fg_bg=hzd_fg_bg}
local ack_a = HazardButton{parent=main,x=12,y=32,text="ACK \x13",accent=colors.orange,dis_colors=dis_colors,callback=unit.ack_alarms,fg_bg=hzd_fg_bg}
@@ -387,9 +387,12 @@ local function init(parent, id)
end
end
- u_ps.subscribe("status", start_button_en_check)
- u_ps.subscribe("rps_tripped", start_button_en_check)
- u_ps.subscribe("rps_tripped", function (active) if active then reset.enable() else reset.disable() end end)
+ start.register(u_ps, "status", start_button_en_check)
+ start.register(u_ps, "rps_tripped", start_button_en_check)
+ start.register(u_ps, "auto_group_id", start_button_en_check)
+ start.register(u_ps, "AutoControl", start_button_en_check)
+
+ reset.register(u_ps, "rps_tripped", function (active) if active then reset.enable() else reset.disable() end end)
TextBox{parent=main,text="WASTE PROCESSING",fg_bg=cpair(colors.black,colors.brown),alignment=TEXT_ALIGN.CENTER,width=33,height=1,x=46,y=48}
local waste_proc = Rectangle{parent=main,border=border(1,colors.brown,true),thin=true,width=33,height=3,x=46,y=49}
@@ -397,7 +400,7 @@ local function init(parent, id)
local waste_mode = MultiButton{parent=waste_div,x=1,y=1,options=waste_opts,callback=unit.set_waste,min_width=6}
- u_ps.subscribe("U_WasteMode", waste_mode.set_value)
+ waste_mode.register(u_ps, "U_WasteMode", waste_mode.set_value)
----------------------
-- alarm management --
@@ -420,20 +423,20 @@ local function init(parent, id)
local a_clt = AlarmLight{parent=alarm_panel,x=6,label="RCS Transient",c1=colors.gray,c2=colors.yellow,c3=colors.green,flash=true,period=period.BLINK_500_MS}
local a_tbt = AlarmLight{parent=alarm_panel,x=6,label="Turbine Trip",c1=colors.gray,c2=colors.red,c3=colors.green,flash=true,period=period.BLINK_250_MS}
- u_ps.subscribe("Alarm_1", a_brc.update)
- u_ps.subscribe("Alarm_2", a_rad.update)
- u_ps.subscribe("Alarm_4", a_dmg.update)
+ a_brc.register(u_ps, "Alarm_1", a_brc.update)
+ a_rad.register(u_ps, "Alarm_2", a_rad.update)
+ a_dmg.register(u_ps, "Alarm_4", a_dmg.update)
- u_ps.subscribe("Alarm_3", a_rcl.update)
- u_ps.subscribe("Alarm_5", a_rcd.update)
- u_ps.subscribe("Alarm_6", a_rot.update)
- u_ps.subscribe("Alarm_7", a_rht.update)
- u_ps.subscribe("Alarm_8", a_rwl.update)
- u_ps.subscribe("Alarm_9", a_rwh.update)
+ a_rcl.register(u_ps, "Alarm_3", a_rcl.update)
+ a_rcd.register(u_ps, "Alarm_5", a_rcd.update)
+ a_rot.register(u_ps, "Alarm_6", a_rot.update)
+ a_rht.register(u_ps, "Alarm_7", a_rht.update)
+ a_rwl.register(u_ps, "Alarm_8", a_rwl.update)
+ a_rwh.register(u_ps, "Alarm_9", a_rwh.update)
- u_ps.subscribe("Alarm_10", a_rps.update)
- u_ps.subscribe("Alarm_11", a_clt.update)
- u_ps.subscribe("Alarm_12", a_tbt.update)
+ a_rps.register(u_ps, "Alarm_10", a_rps.update)
+ a_clt.register(u_ps, "Alarm_11", a_clt.update)
+ a_tbt.register(u_ps, "Alarm_12", a_tbt.update)
-- ack's and resets
@@ -487,7 +490,7 @@ local function init(parent, id)
local group = RadioButton{parent=auto_div,options=ctl_opts,callback=function()end,radio_colors=cpair(colors.blue,colors.white),radio_bg=colors.gray}
- u_ps.subscribe("auto_group_id", function (gid) group.set_value(gid + 1) end)
+ group.register(u_ps, "auto_group_id", function (gid) group.set_value(gid + 1) end)
auto_div.line_break()
@@ -499,44 +502,35 @@ local function init(parent, id)
TextBox{parent=auto_div,text="Prio. Group",height=1,width=11,fg_bg=style.label}
local auto_grp = TextBox{parent=auto_div,text="Manual",height=1,width=11,fg_bg=bw_fg_bg}
- u_ps.subscribe("auto_group", auto_grp.set_value)
+ auto_grp.register(u_ps, "auto_group", auto_grp.set_value)
auto_div.line_break()
local a_rdy = IndicatorLight{parent=auto_div,label="Ready",x=2,colors=cpair(colors.green,colors.gray)}
local a_stb = IndicatorLight{parent=auto_div,label="Standby",x=2,colors=cpair(colors.white,colors.gray),flash=true,period=period.BLINK_1000_MS}
- u_ps.subscribe("U_AutoReady", a_rdy.update)
+ a_rdy.register(u_ps, "U_AutoReady", a_rdy.update)
-- update standby indicator
- u_ps.subscribe("status", function (active)
+ a_stb.register(u_ps, "status", function (active)
a_stb.update(unit.annunciator.AutoControl and (not active))
end)
-
- -- enable and disable controls based on group assignment
- u_ps.subscribe("auto_group_id", function (gid)
- start_button_en_check()
-
- if gid == 0 then
- burn_rate.enable()
- set_burn_btn.enable()
- else
- burn_rate.disable()
- set_burn_btn.disable()
- end
- end)
-
- -- enable and disable controls based on auto control state (start button is handled separately)
- u_ps.subscribe("AutoControl", function (auto_active)
- start_button_en_check()
-
+ a_stb.register(u_ps, "AutoControl", function (auto_active)
if auto_active then
a_stb.update(unit.reactor_data.mek_status.status == false)
else a_stb.update(false) end
end)
+ -- enable/disable controls based on group assignment (start button is separate)
+ burn_rate.register(u_ps, "auto_group_id", function (gid)
+ if gid == 0 then burn_rate.enable() else burn_rate.disable() end
+ end)
+ set_burn_btn.register(u_ps, "auto_group_id", function (gid)
+ if gid == 0 then set_burn_btn.enable() else set_burn_btn.disable() end
+ end)
+
-- can't change group if auto is engaged regardless of if this unit is part of auto control
- f_ps.subscribe("auto_active", function (auto_active)
+ set_grp_btn.register(f_ps, "auto_active", function (auto_active)
if auto_active then set_grp_btn.disable() else set_grp_btn.enable() end
end)
diff --git a/coordinator/ui/layout/main_view.lua b/coordinator/ui/layout/main_view.lua
index 5510382..a758b24 100644
--- a/coordinator/ui/layout/main_view.lua
+++ b/coordinator/ui/layout/main_view.lua
@@ -34,8 +34,8 @@ local function init(main)
-- max length example: "01:23:45 AM - Wednesday, September 28 2022"
local datetime = TextBox{parent=main,x=(header.width()-42),y=1,text="",alignment=TEXT_ALIGN.RIGHT,width=42,height=1,fg_bg=style.header}
- facility.ps.subscribe("sv_ping", ping.update)
- facility.ps.subscribe("date_time", datetime.set_value)
+ 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
diff --git a/graphics/element.lua b/graphics/element.lua
index edcbdcc..46b9ca1 100644
--- a/graphics/element.lua
+++ b/graphics/element.lua
@@ -52,6 +52,11 @@ local element = {}
---|textbox_args
---|tiling_args
+---@class element_subscription
+---@field ps psil ps used
+---@field key string data key
+---@field func function callback
+
-- a base graphics element, should not be created on its own
---@nodiscard
---@param args graphics_args arguments
@@ -66,6 +71,7 @@ function element.new(args)
bounds = { x1 = 1, y1 = 1, x2 = 1, y2 = 1 }, ---@class element_bounds
next_y = 1,
children = {},
+ subscriptions = {},
mt = {}
}
@@ -85,15 +91,6 @@ function element.new(args)
return "graphics.element{" .. self.elem_type .. "} @ " .. tostring(self)
end
- -- check if a coordinate is within the bounds of this element
- ---@param x integer
- ---@param y integer
- local function _in_bounds(x, y)
- local in_x = x >= self.bounds.x1 and x <= self.bounds.x2
- local in_y = y >= self.bounds.y1 and y <= self.bounds.y2
- return in_x and in_y
- end
-
---@class graphics_element
local public = {}
@@ -180,9 +177,29 @@ function element.new(args)
self.bounds.y2 = self.position.y + f.h - 1
end
+ -- check if a coordinate is within the bounds of this element
+ ---@param x integer
+ ---@param y integer
+ function protected.in_bounds(x, y)
+ local in_x = x >= self.bounds.x1 and x <= self.bounds.x2
+ local in_y = y >= self.bounds.y1 and y <= self.bounds.y2
+ return in_x and in_y
+ end
+
-- luacheck: push ignore
---@diagnostic disable: unused-local, unused-vararg
+ -- dynamically insert a child element
+ ---@param id string|integer element identifier
+ ---@param elem graphics_element element
+ function protected.insert(id, elem)
+ end
+
+ -- dynamically remove a child element
+ ---@param id string|integer element identifier
+ function protected.remove(id)
+ end
+
-- handle a mouse event
---@param event mouse_interaction mouse interaction event
function protected.handle_mouse(event)
@@ -281,7 +298,25 @@ function element.new(args)
---@nodiscard
function public.window() return protected.window end
- -- CHILD ELEMENTS --
+ -- delete this element (hide and unsubscribe from PSIL)
+ function public.delete()
+ -- hide + stop animations
+ public.hide()
+
+ -- unsubscribe from PSIL
+ for i = 1, #self.subscriptions do
+ local s = self.subscriptions[i] ---@type element_subscription
+ s.ps.unsubscribe(s.key, s.func)
+ end
+
+ -- delete all children
+ for k, v in pairs(self.children) do
+ v.delete()
+ self.children[k] = nil
+ end
+ end
+
+ -- ELEMENT TREE --
-- add a child element
---@nodiscard
@@ -311,12 +346,18 @@ function element.new(args)
-- get a child element
---@nodiscard
+ ---@param id element_id
---@return graphics_element
- function public.get_child(key) return self.children[key] end
+ function public.get_child(id) return self.children[id] end
- -- remove child
- ---@param key string|integer
- function public.remove(key) self.children[key] = nil end
+ -- remove a child element
+ ---@param id element_id
+ function public.remove(id)
+ if self.children[id] ~= nil then
+ self.children[id].delete()
+ self.children[id] = nil
+ end
+ end
-- attempt to get a child element by ID (does not include this element itself)
---@nodiscard
@@ -335,6 +376,25 @@ function element.new(args)
return nil
end
+ -- DYNAMIC CHILD ELEMENTS --
+
+ -- insert an element as a contained child
+ -- this is intended to be used dynamically, and depends on the target element type.
+ -- not all elements support dynamic children.
+ ---@param id string|integer element identifier
+ ---@param elem graphics_element element
+ function public.insert_element(id, elem)
+ protected.insert(id, elem)
+ end
+
+ -- remove an element from contained children
+ -- this is intended to be used dynamically, and depends on the target element type.
+ -- not all elements support dynamic children.
+ ---@param id string|integer element identifier
+ function public.remove_element(id)
+ protected.remove(id)
+ end
+
-- AUTO-PLACEMENT --
-- skip a line for automatically placed elements
@@ -428,19 +488,25 @@ function element.new(args)
protected.resize(...)
end
+ -- reposition the element window
+ -- offsets relative to parent frame are where (1, 1) would be on top of the parent's top left corner
+ ---@param x integer x position relative to parent frame
+ ---@param y integer y position relative to parent frame
+ function public.reposition(x, y)
+ protected.window.reposition(x, y)
+ end
+
-- FUNCTION CALLBACKS --
-- handle a monitor touch or mouse click
---@param event mouse_interaction mouse interaction event
function public.handle_mouse(event)
- local x_ini, y_ini, x_cur, y_cur = event.initial.x, event.initial.y, event.current.x, event.current.y
+ local x_ini, y_ini = event.initial.x, event.initial.y
- local ini_in = _in_bounds(x_ini, y_ini)
- local cur_in = _in_bounds(x_cur, y_cur)
+ local ini_in = protected.in_bounds(x_ini, y_ini)
if ini_in then
local event_T = core.events.mouse_transposed(event, self.position.x, self.position.y)
- if not cur_in then event_T.type = core.events.CLICK_TYPE.EXITED end
-- handle the mouse event then pass to children
protected.handle_mouse(event_T)
@@ -460,6 +526,16 @@ function element.new(args)
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
+ ---@param key string key to subscribe to
+ ---@param func function function to link
+ function public.register(ps, key, func)
+ table.insert(self.subscriptions, { ps = ps, key = key, func = func })
+ ps.subscribe(key, func)
+ end
+
-- VISIBILITY --
-- show the element
diff --git a/graphics/elements/controls/push_button.lua b/graphics/elements/controls/push_button.lua
index ed0fc2a..7f91ea5 100644
--- a/graphics/elements/controls/push_button.lua
+++ b/graphics/elements/controls/push_button.lua
@@ -84,9 +84,9 @@ local function push_button(args)
show_pressed()
elseif event.type == CLICK_TYPE.UP then
show_unpressed()
- args.callback()
- elseif event.type == CLICK_TYPE.EXITED then
- show_unpressed()
+ if e.in_bounds(event.current.x, event.current.y) then
+ args.callback()
+ end
end
end
end
diff --git a/graphics/elements/controls/sidebar.lua b/graphics/elements/controls/sidebar.lua
index 997b372..a20cb72 100644
--- a/graphics/elements/controls/sidebar.lua
+++ b/graphics/elements/controls/sidebar.lua
@@ -93,14 +93,14 @@ local function sidebar(args)
elseif event.type == CLICK_TYPE.DOWN then
draw(true, cur_idx)
elseif event.type == CLICK_TYPE.UP then
- if cur_idx == ini_idx then
+ if cur_idx == ini_idx and e.in_bounds(event.current.x, event.current.y) then
e.value = cur_idx
draw(false)
args.callback(e.value)
else draw(false) end
- elseif event.type == CLICK_TYPE.EXITED then
- draw(false)
end
+ elseif event.type == CLICK_TYPE.UP then
+ draw(false)
end
end
end
diff --git a/graphics/events.lua b/graphics/events.lua
index 7370481..3391a18 100644
--- a/graphics/events.lua
+++ b/graphics/events.lua
@@ -21,8 +21,7 @@ events.CLICK_TYPE = {
UP = 3, -- button up (completed a click)
DRAG = 4, -- mouse dragged
SCROLL_DOWN = 5, -- scroll down
- SCROLL_UP = 6, -- scroll up
- EXITED = 7 -- cursor exited bounds of element
+ SCROLL_UP = 6 -- scroll up
}
-- create a new 2D coordinate
diff --git a/install_manifest.json b/install_manifest.json
index 6327cf6..e26050a 100644
--- a/install_manifest.json
+++ b/install_manifest.json
@@ -1 +1 @@
-{"versions": {"installer": "v1.0", "bootloader": "0.2", "comms": "1.4.1", "reactor-plc": "v1.2.0", "rtu": "v1.1.0", "supervisor": "v0.15.8", "coordinator": "v0.14.0", "pocket": "alpha-v0.2.6"}, "files": {"system": ["initenv.lua", "startup.lua"], "common": ["scada-common/crypto.lua", "scada-common/ppm.lua", "scada-common/comms.lua", "scada-common/psil.lua", "scada-common/tcallbackdsp.lua", "scada-common/rsio.lua", "scada-common/constants.lua", "scada-common/mqueue.lua", "scada-common/crash.lua", "scada-common/log.lua", "scada-common/types.lua", "scada-common/util.lua"], "graphics": ["graphics/element.lua", "graphics/events.lua", "graphics/flasher.lua", "graphics/core.lua", "graphics/elements/textbox.lua", "graphics/elements/displaybox.lua", "graphics/elements/pipenet.lua", "graphics/elements/rectangle.lua", "graphics/elements/div.lua", "graphics/elements/multipane.lua", "graphics/elements/tiling.lua", "graphics/elements/colormap.lua", "graphics/elements/indicators/alight.lua", "graphics/elements/indicators/icon.lua", "graphics/elements/indicators/power.lua", "graphics/elements/indicators/rad.lua", "graphics/elements/indicators/state.lua", "graphics/elements/indicators/light.lua", "graphics/elements/indicators/vbar.lua", "graphics/elements/indicators/led.lua", "graphics/elements/indicators/coremap.lua", "graphics/elements/indicators/data.lua", "graphics/elements/indicators/ledpair.lua", "graphics/elements/indicators/hbar.lua", "graphics/elements/indicators/trilight.lua", "graphics/elements/indicators/ledrgb.lua", "graphics/elements/controls/switch_button.lua", "graphics/elements/controls/spinbox_numeric.lua", "graphics/elements/controls/hazard_button.lua", "graphics/elements/controls/push_button.lua", "graphics/elements/controls/radio_button.lua", "graphics/elements/controls/multi_button.lua", "graphics/elements/controls/tabbar.lua", "graphics/elements/controls/sidebar.lua", "graphics/elements/animations/waiting.lua"], "lockbox": ["lockbox/init.lua", "lockbox/LICENSE", "lockbox/kdf/pbkdf2.lua", "lockbox/util/bit.lua", "lockbox/util/array.lua", "lockbox/util/stream.lua", "lockbox/util/queue.lua", "lockbox/digest/sha2_224.lua", "lockbox/digest/sha1.lua", "lockbox/digest/sha2_256.lua", "lockbox/cipher/aes128.lua", "lockbox/cipher/aes256.lua", "lockbox/cipher/aes192.lua", "lockbox/cipher/mode/ofb.lua", "lockbox/cipher/mode/cbc.lua", "lockbox/cipher/mode/ctr.lua", "lockbox/cipher/mode/cfb.lua", "lockbox/mac/hmac.lua", "lockbox/padding/ansix923.lua", "lockbox/padding/pkcs7.lua", "lockbox/padding/zero.lua", "lockbox/padding/isoiec7816.lua"], "reactor-plc": ["reactor-plc/renderer.lua", "reactor-plc/threads.lua", "reactor-plc/databus.lua", "reactor-plc/plc.lua", "reactor-plc/config.lua", "reactor-plc/startup.lua", "reactor-plc/panel/front_panel.lua", "reactor-plc/panel/style.lua"], "rtu": ["rtu/renderer.lua", "rtu/threads.lua", "rtu/rtu.lua", "rtu/databus.lua", "rtu/modbus.lua", "rtu/config.lua", "rtu/startup.lua", "rtu/panel/front_panel.lua", "rtu/panel/style.lua", "rtu/dev/sps_rtu.lua", "rtu/dev/envd_rtu.lua", "rtu/dev/boilerv_rtu.lua", "rtu/dev/redstone_rtu.lua", "rtu/dev/sna_rtu.lua", "rtu/dev/imatrix_rtu.lua", "rtu/dev/turbinev_rtu.lua"], "supervisor": ["supervisor/supervisor.lua", "supervisor/unit.lua", "supervisor/config.lua", "supervisor/startup.lua", "supervisor/unitlogic.lua", "supervisor/facility.lua", "supervisor/session/coordinator.lua", "supervisor/session/svqtypes.lua", "supervisor/session/pocket.lua", "supervisor/session/svsessions.lua", "supervisor/session/rtu.lua", "supervisor/session/plc.lua", "supervisor/session/rsctl.lua", "supervisor/session/rtu/boilerv.lua", "supervisor/session/rtu/txnctrl.lua", "supervisor/session/rtu/unit_session.lua", "supervisor/session/rtu/turbinev.lua", "supervisor/session/rtu/envd.lua", "supervisor/session/rtu/imatrix.lua", "supervisor/session/rtu/sps.lua", "supervisor/session/rtu/qtypes.lua", "supervisor/session/rtu/sna.lua", "supervisor/session/rtu/redstone.lua"], "coordinator": ["coordinator/coordinator.lua", "coordinator/renderer.lua", "coordinator/iocontrol.lua", "coordinator/sounder.lua", "coordinator/config.lua", "coordinator/startup.lua", "coordinator/process.lua", "coordinator/ui/dialog.lua", "coordinator/ui/style.lua", "coordinator/ui/layout/main_view.lua", "coordinator/ui/layout/unit_view.lua", "coordinator/ui/components/reactor.lua", "coordinator/ui/components/processctl.lua", "coordinator/ui/components/unit_overview.lua", "coordinator/ui/components/boiler.lua", "coordinator/ui/components/unit_detail.lua", "coordinator/ui/components/imatrix.lua", "coordinator/ui/components/turbine.lua", "coordinator/session/api.lua", "coordinator/session/apisessions.lua"], "pocket": ["pocket/pocket.lua", "pocket/renderer.lua", "pocket/config.lua", "pocket/coreio.lua", "pocket/startup.lua", "pocket/ui/main.lua", "pocket/ui/style.lua", "pocket/ui/components/turbine_page.lua", "pocket/ui/components/reactor_page.lua", "pocket/ui/components/home_page.lua", "pocket/ui/components/unit_page.lua", "pocket/ui/components/boiler_page.lua", "pocket/ui/components/conn_waiting.lua"]}, "depends": {"reactor-plc": ["system", "common", "graphics"], "rtu": ["system", "common", "graphics"], "supervisor": ["system", "common"], "coordinator": ["system", "common", "graphics"], "pocket": ["system", "common", "graphics"]}, "sizes": {"manifest": 5530, "system": 1991, "common": 90635, "graphics": 126610, "lockbox": 100797, "reactor-plc": 95708, "rtu": 100333, "supervisor": 283104, "coordinator": 196014, "pocket": 36221}}
\ No newline at end of file
+{"versions": {"installer": "v1.0", "bootloader": "0.2", "comms": "1.4.1", "reactor-plc": "v1.3.0", "rtu": "v1.2.0", "supervisor": "v0.15.8", "coordinator": "v0.15.0", "pocket": "alpha-v0.3.0"}, "files": {"system": ["initenv.lua", "startup.lua"], "common": ["scada-common/crypto.lua", "scada-common/ppm.lua", "scada-common/comms.lua", "scada-common/psil.lua", "scada-common/tcallbackdsp.lua", "scada-common/rsio.lua", "scada-common/constants.lua", "scada-common/mqueue.lua", "scada-common/crash.lua", "scada-common/log.lua", "scada-common/types.lua", "scada-common/util.lua"], "graphics": ["graphics/element.lua", "graphics/events.lua", "graphics/flasher.lua", "graphics/core.lua", "graphics/elements/textbox.lua", "graphics/elements/displaybox.lua", "graphics/elements/pipenet.lua", "graphics/elements/rectangle.lua", "graphics/elements/div.lua", "graphics/elements/multipane.lua", "graphics/elements/tiling.lua", "graphics/elements/colormap.lua", "graphics/elements/indicators/alight.lua", "graphics/elements/indicators/icon.lua", "graphics/elements/indicators/power.lua", "graphics/elements/indicators/rad.lua", "graphics/elements/indicators/state.lua", "graphics/elements/indicators/light.lua", "graphics/elements/indicators/vbar.lua", "graphics/elements/indicators/led.lua", "graphics/elements/indicators/coremap.lua", "graphics/elements/indicators/data.lua", "graphics/elements/indicators/ledpair.lua", "graphics/elements/indicators/hbar.lua", "graphics/elements/indicators/trilight.lua", "graphics/elements/indicators/ledrgb.lua", "graphics/elements/controls/switch_button.lua", "graphics/elements/controls/spinbox_numeric.lua", "graphics/elements/controls/hazard_button.lua", "graphics/elements/controls/push_button.lua", "graphics/elements/controls/radio_button.lua", "graphics/elements/controls/multi_button.lua", "graphics/elements/controls/tabbar.lua", "graphics/elements/controls/sidebar.lua", "graphics/elements/animations/waiting.lua"], "lockbox": ["lockbox/init.lua", "lockbox/LICENSE", "lockbox/kdf/pbkdf2.lua", "lockbox/util/bit.lua", "lockbox/util/array.lua", "lockbox/util/stream.lua", "lockbox/util/queue.lua", "lockbox/digest/sha2_224.lua", "lockbox/digest/sha1.lua", "lockbox/digest/sha2_256.lua", "lockbox/cipher/aes128.lua", "lockbox/cipher/aes256.lua", "lockbox/cipher/aes192.lua", "lockbox/cipher/mode/ofb.lua", "lockbox/cipher/mode/cbc.lua", "lockbox/cipher/mode/ctr.lua", "lockbox/cipher/mode/cfb.lua", "lockbox/mac/hmac.lua", "lockbox/padding/ansix923.lua", "lockbox/padding/pkcs7.lua", "lockbox/padding/zero.lua", "lockbox/padding/isoiec7816.lua"], "reactor-plc": ["reactor-plc/renderer.lua", "reactor-plc/threads.lua", "reactor-plc/databus.lua", "reactor-plc/plc.lua", "reactor-plc/config.lua", "reactor-plc/startup.lua", "reactor-plc/panel/front_panel.lua", "reactor-plc/panel/style.lua"], "rtu": ["rtu/renderer.lua", "rtu/threads.lua", "rtu/rtu.lua", "rtu/databus.lua", "rtu/modbus.lua", "rtu/config.lua", "rtu/startup.lua", "rtu/panel/front_panel.lua", "rtu/panel/style.lua", "rtu/dev/sps_rtu.lua", "rtu/dev/envd_rtu.lua", "rtu/dev/boilerv_rtu.lua", "rtu/dev/redstone_rtu.lua", "rtu/dev/sna_rtu.lua", "rtu/dev/imatrix_rtu.lua", "rtu/dev/turbinev_rtu.lua"], "supervisor": ["supervisor/supervisor.lua", "supervisor/unit.lua", "supervisor/config.lua", "supervisor/startup.lua", "supervisor/unitlogic.lua", "supervisor/facility.lua", "supervisor/session/coordinator.lua", "supervisor/session/svqtypes.lua", "supervisor/session/pocket.lua", "supervisor/session/svsessions.lua", "supervisor/session/rtu.lua", "supervisor/session/plc.lua", "supervisor/session/rsctl.lua", "supervisor/session/rtu/boilerv.lua", "supervisor/session/rtu/txnctrl.lua", "supervisor/session/rtu/unit_session.lua", "supervisor/session/rtu/turbinev.lua", "supervisor/session/rtu/envd.lua", "supervisor/session/rtu/imatrix.lua", "supervisor/session/rtu/sps.lua", "supervisor/session/rtu/qtypes.lua", "supervisor/session/rtu/sna.lua", "supervisor/session/rtu/redstone.lua"], "coordinator": ["coordinator/coordinator.lua", "coordinator/renderer.lua", "coordinator/iocontrol.lua", "coordinator/sounder.lua", "coordinator/config.lua", "coordinator/startup.lua", "coordinator/process.lua", "coordinator/ui/dialog.lua", "coordinator/ui/style.lua", "coordinator/ui/layout/main_view.lua", "coordinator/ui/layout/unit_view.lua", "coordinator/ui/components/reactor.lua", "coordinator/ui/components/processctl.lua", "coordinator/ui/components/unit_overview.lua", "coordinator/ui/components/boiler.lua", "coordinator/ui/components/unit_detail.lua", "coordinator/ui/components/imatrix.lua", "coordinator/ui/components/turbine.lua", "coordinator/session/api.lua", "coordinator/session/apisessions.lua"], "pocket": ["pocket/pocket.lua", "pocket/renderer.lua", "pocket/config.lua", "pocket/coreio.lua", "pocket/startup.lua", "pocket/ui/main.lua", "pocket/ui/style.lua", "pocket/ui/components/turbine_page.lua", "pocket/ui/components/reactor_page.lua", "pocket/ui/components/home_page.lua", "pocket/ui/components/unit_page.lua", "pocket/ui/components/boiler_page.lua", "pocket/ui/components/conn_waiting.lua"]}, "depends": {"reactor-plc": ["system", "common", "graphics"], "rtu": ["system", "common", "graphics"], "supervisor": ["system", "common"], "coordinator": ["system", "common", "graphics"], "pocket": ["system", "common", "graphics"]}, "sizes": {"manifest": 5530, "system": 1991, "common": 91102, "graphics": 129080, "lockbox": 100797, "reactor-plc": 95927, "rtu": 101013, "supervisor": 283104, "coordinator": 197539, "pocket": 36231}}
\ No newline at end of file
diff --git a/pocket/startup.lua b/pocket/startup.lua
index 9ed088c..086cd68 100644
--- a/pocket/startup.lua
+++ b/pocket/startup.lua
@@ -17,7 +17,7 @@ local coreio = require("pocket.coreio")
local pocket = require("pocket.pocket")
local renderer = require("pocket.renderer")
-local POCKET_VERSION = "alpha-v0.2.6"
+local POCKET_VERSION = "alpha-v0.3.0"
local println = util.println
local println_ts = util.println_ts
diff --git a/pocket/ui/main.lua b/pocket/ui/main.lua
index 1b7be88..c143b0b 100644
--- a/pocket/ui/main.lua
+++ b/pocket/ui/main.lua
@@ -45,7 +45,7 @@ local function init(main)
local root_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes=root_panes}
- coreio.core_ps().subscribe("link_state", function (state)
+ root_pane.register(coreio.core_ps(), "link_state", function (state)
if state == coreio.LINK_STATE.UNLINKED or state == coreio.LINK_STATE.API_LINK_ONLY then
root_pane.set_value(1)
elseif state == coreio.LINK_STATE.SV_LINK_ONLY then
diff --git a/reactor-plc/databus.lua b/reactor-plc/databus.lua
index beee265..ba7a68e 100644
--- a/reactor-plc/databus.lua
+++ b/reactor-plc/databus.lua
@@ -8,14 +8,16 @@ local util = require("scada-common.util")
local databus = {}
+-- databus PSIL
+databus.ps = psil.create()
+
local dbus_iface = {
- ps = psil.create(),
rps_scram = function () log.debug("DBUS: unset rps_scram() called") end,
rps_reset = function () log.debug("DBUS: unset rps_reset() called") end
}
-- call to toggle heartbeat signal
-function databus.heartbeat() dbus_iface.ps.toggle("heartbeat") end
+function databus.heartbeat() databus.ps.toggle("heartbeat") end
-- link RPS command functions
---@param scram function reactor SCRAM function
@@ -35,42 +37,42 @@ function databus.rps_reset() dbus_iface.rps_reset() end
---@param plc_v string PLC version
---@param comms_v string comms version
function databus.tx_versions(plc_v, comms_v)
- dbus_iface.ps.publish("version", plc_v)
- dbus_iface.ps.publish("comms_version", comms_v)
+ databus.ps.publish("version", plc_v)
+ databus.ps.publish("comms_version", comms_v)
end
-- transmit unit ID across the bus
---@param id integer unit ID
function databus.tx_id(id)
- dbus_iface.ps.publish("unit_id", id)
+ databus.ps.publish("unit_id", id)
end
-- transmit hardware status across the bus
---@param plc_state plc_state
function databus.tx_hw_status(plc_state)
- dbus_iface.ps.publish("reactor_dev_state", util.trinary(plc_state.no_reactor, 1, util.trinary(plc_state.reactor_formed, 3, 2)))
- dbus_iface.ps.publish("has_modem", not plc_state.no_modem)
- dbus_iface.ps.publish("degraded", plc_state.degraded)
- dbus_iface.ps.publish("init_ok", plc_state.init_ok)
+ databus.ps.publish("reactor_dev_state", util.trinary(plc_state.no_reactor, 1, util.trinary(plc_state.reactor_formed, 3, 2)))
+ databus.ps.publish("has_modem", not plc_state.no_modem)
+ databus.ps.publish("degraded", plc_state.degraded)
+ databus.ps.publish("init_ok", plc_state.init_ok)
end
-- transmit thread (routine) statuses
---@param thread string thread name
---@param ok boolean thread state
function databus.tx_rt_status(thread, ok)
- dbus_iface.ps.publish(util.c("routine__", thread), ok)
+ databus.ps.publish(util.c("routine__", thread), ok)
end
-- transmit supervisor link state across the bus
---@param state integer
function databus.tx_link_state(state)
- dbus_iface.ps.publish("link_state", state)
+ databus.ps.publish("link_state", state)
end
-- transmit reactor enable state across the bus
---@param active boolean reactor active
function databus.tx_reactor_state(active)
- dbus_iface.ps.publish("reactor_active", active)
+ databus.ps.publish("reactor_active", active)
end
-- transmit RPS data across the bus
@@ -78,26 +80,26 @@ end
---@param status table RPS status
---@param emer_cool_active boolean RPS activated the emergency coolant
function databus.tx_rps(tripped, status, emer_cool_active)
- dbus_iface.ps.publish("rps_scram", tripped)
- dbus_iface.ps.publish("rps_damage", status[1])
- dbus_iface.ps.publish("rps_high_temp", status[2])
- dbus_iface.ps.publish("rps_low_ccool", status[3])
- dbus_iface.ps.publish("rps_high_waste", status[4])
- dbus_iface.ps.publish("rps_high_hcool", status[5])
- dbus_iface.ps.publish("rps_no_fuel", status[6])
- dbus_iface.ps.publish("rps_fault", status[7])
- dbus_iface.ps.publish("rps_timeout", status[8])
- dbus_iface.ps.publish("rps_manual", status[9])
- dbus_iface.ps.publish("rps_automatic", status[10])
- dbus_iface.ps.publish("rps_sysfail", status[11])
- dbus_iface.ps.publish("emer_cool", emer_cool_active)
+ databus.ps.publish("rps_scram", tripped)
+ databus.ps.publish("rps_damage", status[1])
+ databus.ps.publish("rps_high_temp", status[2])
+ databus.ps.publish("rps_low_ccool", status[3])
+ databus.ps.publish("rps_high_waste", status[4])
+ databus.ps.publish("rps_high_hcool", status[5])
+ databus.ps.publish("rps_no_fuel", status[6])
+ databus.ps.publish("rps_fault", status[7])
+ databus.ps.publish("rps_timeout", status[8])
+ databus.ps.publish("rps_manual", status[9])
+ databus.ps.publish("rps_automatic", status[10])
+ databus.ps.publish("rps_sysfail", status[11])
+ databus.ps.publish("emer_cool", emer_cool_active)
end
-- link a function to receive data from the bus
---@param field string field name
---@param func function function to link
function databus.rx_field(field, func)
- dbus_iface.ps.subscribe(field, func)
+ databus.ps.subscribe(field, func)
end
return databus
diff --git a/reactor-plc/panel/front_panel.lua b/reactor-plc/panel/front_panel.lua
index c000a3d..8e28a75 100644
--- a/reactor-plc/panel/front_panel.lua
+++ b/reactor-plc/panel/front_panel.lua
@@ -31,7 +31,7 @@ local border = core.border
---@param panel graphics_element main displaybox
local function init(panel)
local header = TextBox{parent=panel,y=1,text="REACTOR PLC - UNIT ?",alignment=TEXT_ALIGN.CENTER,height=1,fg_bg=style.header}
- databus.rx_field("unit_id", function (id) header.set_value(util.c("REACTOR PLC - UNIT ", id)) end)
+ header.register(databus.ps, "unit_id", function (id) header.set_value(util.c("REACTOR PLC - UNIT ", id)) end)
--
-- system indicators
@@ -43,8 +43,8 @@ local function init(panel)
local heartbeat = LED{parent=system,label="HEARTBEAT",colors=cpair(colors.green,colors.green_off)}
system.line_break()
- databus.rx_field("init_ok", init_ok.update)
- databus.rx_field("heartbeat", heartbeat.update)
+ init_ok.register(databus.ps, "init_ok", init_ok.update)
+ heartbeat.register(databus.ps, "heartbeat", heartbeat.update)
local reactor = LEDPair{parent=system,label="REACTOR",off=colors.red,c1=colors.yellow,c2=colors.green}
local modem = LED{parent=system,label="MODEM",colors=cpair(colors.green,colors.green_off)}
@@ -52,9 +52,9 @@ local function init(panel)
network.update(5)
system.line_break()
- databus.rx_field("reactor_dev_state", reactor.update)
- databus.rx_field("has_modem", modem.update)
- databus.rx_field("link_state", network.update)
+ reactor.register(databus.ps, "reactor_dev_state", reactor.update)
+ modem.register(databus.ps, "has_modem", modem.update)
+ network.register(databus.ps, "link_state", network.update)
local rt_main = LED{parent=system,label="RT MAIN",colors=cpair(colors.green,colors.green_off)}
local rt_rps = LED{parent=system,label="RT RPS",colors=cpair(colors.green,colors.green_off)}
@@ -63,11 +63,11 @@ local function init(panel)
local rt_sctl = LED{parent=system,label="RT SPCTL",colors=cpair(colors.green,colors.green_off)}
system.line_break()
- databus.rx_field("routine__main", rt_main.update)
- databus.rx_field("routine__rps", rt_rps.update)
- databus.rx_field("routine__comms_tx", rt_cmtx.update)
- databus.rx_field("routine__comms_rx", rt_cmrx.update)
- databus.rx_field("routine__spctl", rt_sctl.update)
+ rt_main.register(databus.ps, "routine__main", rt_main.update)
+ rt_rps.register(databus.ps, "routine__rps", rt_rps.update)
+ rt_cmtx.register(databus.ps, "routine__comms_tx", rt_cmtx.update)
+ rt_cmrx.register(databus.ps, "routine__comms_rx", rt_cmrx.update)
+ rt_sctl.register(databus.ps, "routine__spctl", rt_sctl.update)
--
-- status & controls
@@ -80,7 +80,7 @@ local function init(panel)
-- only show emergency coolant LED if emergency coolant is configured for this device
if type(config.EMERGENCY_COOL) == "table" then
local emer_cool = LED{parent=status,x=2,width=14,label="EMER COOLANT",colors=cpair(colors.yellow,colors.yellow_off)}
- databus.rx_field("emer_cool", emer_cool.update)
+ emer_cool.register(databus.ps, "emer_cool", emer_cool.update)
end
local status_trip_rct = Rectangle{parent=status,width=20,height=3,x=1,border=border(1,colors.lightGray,true),even_inner=true,fg_bg=cpair(colors.black,colors.ivory)}
@@ -92,8 +92,8 @@ local function init(panel)
PushButton{parent=controls,x=1,y=1,min_width=7,text="SCRAM",callback=databus.rps_scram,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.black,colors.red_off)}
PushButton{parent=controls,x=9,y=1,min_width=7,text="RESET",callback=databus.rps_reset,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.black,colors.yellow_off)}
- databus.rx_field("reactor_active", active.update)
- databus.rx_field("rps_scram", scram.update)
+ active.register(databus.ps, "reactor_active", active.update)
+ scram.register(databus.ps, "rps_scram", scram.update)
--
-- about footer
@@ -103,8 +103,8 @@ local function init(panel)
local fw_v = TextBox{parent=about,x=2,y=1,text="FW: v00.00.00",alignment=TEXT_ALIGN.LEFT,height=1}
local comms_v = TextBox{parent=about,x=17,y=1,text="NT: v00.00.00",alignment=TEXT_ALIGN.LEFT,height=1}
- databus.rx_field("version", function (version) fw_v.set_value(util.c("FW: ", version)) end)
- databus.rx_field("comms_version", function (version) comms_v.set_value(util.c("NT: v", version)) end)
+ fw_v.register(databus.ps, "version", function (version) fw_v.set_value(util.c("FW: ", version)) end)
+ comms_v.register(databus.ps, "comms_version", function (version) comms_v.set_value(util.c("NT: v", version)) end)
--
-- rps list
@@ -126,17 +126,17 @@ local function init(panel)
local rps_ccl = LED{parent=rps,label="LO CCOOLANT",colors=cpair(colors.red,colors.red_off)}
local rps_hcl = LED{parent=rps,label="HI HCOOLANT",colors=cpair(colors.red,colors.red_off)}
- databus.rx_field("rps_manual", rps_man.update)
- databus.rx_field("rps_automatic", rps_auto.update)
- databus.rx_field("rps_timeout", rps_tmo.update)
- databus.rx_field("rps_fault", rps_flt.update)
- databus.rx_field("rps_sysfail", rps_fail.update)
- databus.rx_field("rps_damage", rps_dmg.update)
- databus.rx_field("rps_high_temp", rps_tmp.update)
- databus.rx_field("rps_no_fuel", rps_nof.update)
- databus.rx_field("rps_high_waste", rps_wst.update)
- databus.rx_field("rps_low_ccool", rps_ccl.update)
- databus.rx_field("rps_high_hcool", rps_hcl.update)
+ rps_man.register(databus.ps, "rps_manual", rps_man.update)
+ rps_auto.register(databus.ps, "rps_automatic", rps_auto.update)
+ rps_tmo.register(databus.ps, "rps_timeout", rps_tmo.update)
+ rps_flt.register(databus.ps, "rps_fault", rps_flt.update)
+ rps_fail.register(databus.ps, "rps_sysfail", rps_fail.update)
+ rps_dmg.register(databus.ps, "rps_damage", rps_dmg.update)
+ rps_tmp.register(databus.ps, "rps_high_temp", rps_tmp.update)
+ rps_nof.register(databus.ps, "rps_no_fuel", rps_nof.update)
+ rps_wst.register(databus.ps, "rps_high_waste", rps_wst.update)
+ rps_ccl.register(databus.ps, "rps_low_ccool", rps_ccl.update)
+ rps_hcl.register(databus.ps, "rps_high_hcool", rps_hcl.update)
end
return init
diff --git a/reactor-plc/renderer.lua b/reactor-plc/renderer.lua
index 9830751..038918b 100644
--- a/reactor-plc/renderer.lua
+++ b/reactor-plc/renderer.lua
@@ -44,10 +44,8 @@ function renderer.close_ui()
-- stop blinking indicators
flasher.clear()
- -- hide to stop animation callbacks
- ui.display.hide()
-
- -- clear root UI elements
+ -- delete element tree
+ ui.display.delete()
ui.display = nil
-- restore colors
diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua
index 183fbf3..540b1fd 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.2.0"
+local R_PLC_VERSION = "v1.3.0"
local println = util.println
local println_ts = util.println_ts
diff --git a/rtu/databus.lua b/rtu/databus.lua
index 8ef720e..3014367 100644
--- a/rtu/databus.lua
+++ b/rtu/databus.lua
@@ -7,9 +7,8 @@ local util = require("scada-common.util")
local databus = {}
-local dbus_iface = {
- ps = psil.create()
-}
+-- databus PSIL
+databus.ps = psil.create()
---@enum RTU_UNIT_HW_STATE
local RTU_UNIT_HW_STATE = {
@@ -22,54 +21,54 @@ local RTU_UNIT_HW_STATE = {
databus.RTU_UNIT_HW_STATE = RTU_UNIT_HW_STATE
-- call to toggle heartbeat signal
-function databus.heartbeat() dbus_iface.ps.toggle("heartbeat") end
+function databus.heartbeat() databus.ps.toggle("heartbeat") end
-- transmit firmware versions across the bus
---@param rtu_v string RTU version
---@param comms_v string comms version
function databus.tx_versions(rtu_v, comms_v)
- dbus_iface.ps.publish("version", rtu_v)
- dbus_iface.ps.publish("comms_version", comms_v)
+ databus.ps.publish("version", rtu_v)
+ databus.ps.publish("comms_version", comms_v)
end
-- transmit hardware status for modem connection state
---@param has_modem boolean
function databus.tx_hw_modem(has_modem)
- dbus_iface.ps.publish("has_modem", has_modem)
+ databus.ps.publish("has_modem", has_modem)
end
-- transmit unit hardware type across the bus
---@param uid integer unit ID
---@param type RTU_UNIT_TYPE
function databus.tx_unit_hw_type(uid, type)
- dbus_iface.ps.publish("unit_type_" .. uid, type)
+ databus.ps.publish("unit_type_" .. uid, type)
end
-- transmit unit hardware status across the bus
---@param uid integer unit ID
---@param status RTU_UNIT_HW_STATE
function databus.tx_unit_hw_status(uid, status)
- dbus_iface.ps.publish("unit_hw_" .. uid, status)
+ databus.ps.publish("unit_hw_" .. uid, status)
end
-- transmit thread (routine) statuses
---@param thread string thread name
---@param ok boolean thread state
function databus.tx_rt_status(thread, ok)
- dbus_iface.ps.publish(util.c("routine__", thread), ok)
+ databus.ps.publish(util.c("routine__", thread), ok)
end
-- transmit supervisor link state across the bus
---@param state integer
function databus.tx_link_state(state)
- dbus_iface.ps.publish("link_state", state)
+ databus.ps.publish("link_state", state)
end
-- link a function to receive data from the bus
---@param field string field name
---@param func function function to link
function databus.rx_field(field, func)
- dbus_iface.ps.subscribe(field, func)
+ databus.ps.subscribe(field, func)
end
return databus
diff --git a/rtu/panel/front_panel.lua b/rtu/panel/front_panel.lua
index 8dcaa1f..4c4aa78 100644
--- a/rtu/panel/front_panel.lua
+++ b/rtu/panel/front_panel.lua
@@ -49,22 +49,22 @@ local function init(panel, units)
on.update(true)
system.line_break()
- databus.rx_field("heartbeat", heartbeat.update)
+ heartbeat.register(databus.ps, "heartbeat", heartbeat.update)
local modem = LED{parent=system,label="MODEM",colors=cpair(colors.green,colors.green_off)}
local network = RGBLED{parent=system,label="NETWORK",colors={colors.green,colors.red,colors.orange,colors.yellow,colors.gray}}
network.update(5)
system.line_break()
- databus.rx_field("has_modem", modem.update)
- databus.rx_field("link_state", network.update)
+ modem.register(databus.ps, "has_modem", modem.update)
+ network.register(databus.ps, "link_state", network.update)
local rt_main = LED{parent=system,label="RT MAIN",colors=cpair(colors.green,colors.green_off)}
local rt_comm = LED{parent=system,label="RT COMMS",colors=cpair(colors.green,colors.green_off)}
system.line_break()
- databus.rx_field("routine__main", rt_main.update)
- databus.rx_field("routine__comms", rt_comm.update)
+ rt_main.register(databus.ps, "routine__main", rt_main.update)
+ rt_comm.register(databus.ps, "routine__comms", rt_comm.update)
--
-- about label
@@ -74,8 +74,8 @@ local function init(panel, units)
local fw_v = TextBox{parent=about,x=1,y=1,text="FW: v00.00.00",alignment=TEXT_ALIGN.LEFT,height=1}
local comms_v = TextBox{parent=about,x=1,y=2,text="NT: v00.00.00",alignment=TEXT_ALIGN.LEFT,height=1}
- databus.rx_field("version", function (version) fw_v.set_value(util.c("FW: ", version)) end)
- databus.rx_field("comms_version", function (version) comms_v.set_value(util.c("NT: v", version)) end)
+ fw_v.register(databus.ps, "version", function (version) fw_v.set_value(util.c("FW: ", version)) end)
+ comms_v.register(databus.ps, "comms_version", function (version) comms_v.set_value(util.c("NT: v", version)) end)
--
-- unit status list
@@ -90,7 +90,7 @@ local function init(panel, units)
for i = 1, list_length do
TextBox{parent=threads,x=1,y=i,text=util.sprintf("%02d",i),height=1}
local rt_unit = LED{parent=threads,x=4,y=i,label="RT",colors=cpair(colors.green,colors.green_off)}
- databus.rx_field("routine__unit_" .. i, rt_unit.update)
+ rt_unit.register(databus.ps, "routine__unit_" .. i, rt_unit.update)
end
local unit_hw_statuses = Div{parent=panel,height=18,x=25,y=3}
@@ -102,13 +102,13 @@ local function init(panel, units)
-- hardware status
local unit_hw = RGBLED{parent=unit_hw_statuses,y=i,label="",colors={colors.red,colors.orange,colors.yellow,colors.green}}
- databus.rx_field("unit_hw_" .. i, unit_hw.update)
+ unit_hw.register(databus.ps, "unit_hw_" .. i, unit_hw.update)
-- unit name identifier (type + index)
local name = util.c(UNIT_TYPE_LABELS[unit.type + 1], " ", unit.index)
local name_box = TextBox{parent=unit_hw_statuses,y=i,x=3,text=name,height=1}
- databus.rx_field("unit_type_" .. i, function (t)
+ name_box.register(databus.ps, "unit_type_" .. i, function (t)
name_box.set_value(util.c(UNIT_TYPE_LABELS[t + 1], " ", unit.index))
end)
diff --git a/rtu/renderer.lua b/rtu/renderer.lua
index 490959c..17949ce 100644
--- a/rtu/renderer.lua
+++ b/rtu/renderer.lua
@@ -45,10 +45,8 @@ function renderer.close_ui()
-- stop blinking indicators
flasher.clear()
- -- hide to stop animation callbacks
- ui.display.hide()
-
- -- clear root UI elements
+ -- delete element tree
+ ui.display.delete()
ui.display = nil
-- restore colors
diff --git a/rtu/startup.lua b/rtu/startup.lua
index 0693f9f..a284b4b 100644
--- a/rtu/startup.lua
+++ b/rtu/startup.lua
@@ -28,7 +28,7 @@ local sna_rtu = require("rtu.dev.sna_rtu")
local sps_rtu = require("rtu.dev.sps_rtu")
local turbinev_rtu = require("rtu.dev.turbinev_rtu")
-local RTU_VERSION = "v1.1.0"
+local RTU_VERSION = "v1.2.0"
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE
diff --git a/scada-common/psil.lua b/scada-common/psil.lua
index 664d10d..13dcaa5 100644
--- a/scada-common/psil.lua
+++ b/scada-common/psil.lua
@@ -2,6 +2,8 @@
-- Publisher-Subscriber Interconnect Layer
--
+local util = require("scada-common.util")
+
local psil = {}
-- instantiate a new PSI layer
@@ -36,6 +38,15 @@ function psil.create()
table.insert(self.ic[key].subscribers, { notify = func })
end
+ -- unsubscribe a function from a given key
+ ---@param key string data key
+ ---@param func function function to unsubscribe
+ function public.unsubscribe(key, func)
+ if self.ic[key] ~= nil then
+ util.filter_table(self.ic[key].subscribers, function (s) return s.notify ~= func end)
+ end
+ end
+
-- publish data to a given key, passing it to all subscribers if it has changed
---@param key string data key
---@param value any data value
@@ -64,6 +75,9 @@ function psil.create()
end
end
+ -- clear the contents of the interconnect
+ function public.purge() self.ic = nil end
+
return public
end