From baba2e1411181f4c781d0fc2660962318ce89bea Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Mon, 20 Jan 2025 15:38:53 -0500 Subject: [PATCH] #557 facility app data and fixes --- coordinator/session/pocket.lua | 28 ++++- pocket/iocontrol.lua | 1 + pocket/iorx.lua | 168 +++++++++++++++++++++++++++- pocket/pocket.lua | 9 ++ pocket/ui/apps/facility.lua | 27 +++-- pocket/ui/apps/waste.lua | 2 +- pocket/ui/pages/facility_matrix.lua | 30 ++--- pocket/ui/pages/facility_sps.lua | 17 +-- 8 files changed, 229 insertions(+), 53 deletions(-) diff --git a/coordinator/session/pocket.lua b/coordinator/session/pocket.lua index 4bd78ed..6a901ac 100644 --- a/coordinator/session/pocket.lua +++ b/coordinator/session/pocket.lua @@ -266,24 +266,46 @@ 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_FAC_DTL then - local fac = db.facility + local units = {} local tank_statuses = {} + for i = 1, #db.units do + local u = db.units[i] + + units[i] = { u.connected, u.annunciator, u.reactor_data, u.tank_data_tbl } + + for t = 1, #u.tank_ps_tbl do table.insert(tank_statuses, u.tank_ps_tbl[t].get("computed_status")) end + end + + local fac = db.facility + for i = 1, #fac.tank_ps_tbl do table.insert(tank_statuses, fac.tank_ps_tbl[i].get("computed_status")) end + local mtx_sps = fac.induction_ps_tbl[1] + local matrix_data = { + mtx_sps.get("eta_string"), + mtx_sps.get("avg_charge"), + mtx_sps.get("avg_inflow"), + mtx_sps.get("avg_outflow"), + mtx_sps.get("is_charging"), + mtx_sps.get("is_discharging"), + mtx_sps.get("at_max_io") + } + local data = { fac.all_sys_ok, fac.rtu_count, - { fac.auto_current_waste_product, fac.auto_pu_fallback_active }, fac.auto_scram, fac.ascram_status, tank_statuses, fac.tank_data_tbl, fac.induction_ps_tbl[1].get("computed_status") or types.IMATRIX_STATE.OFFLINE, fac.induction_data_tbl[1], + matrix_data, fac.sps_ps_tbl[1].get("computed_status") or types.SPS_STATE.OFFLINE, - fac.sps_data_tbl[1] + fac.sps_data_tbl[1], + units } _send(CRDN_TYPE.API_GET_FAC_DTL, data) diff --git a/pocket/iocontrol.lua b/pocket/iocontrol.lua index 75c3b5d..5378329 100644 --- a/pocket/iocontrol.lua +++ b/pocket/iocontrol.lua @@ -94,6 +94,7 @@ function iocontrol.init_core(pkt_comms, nav, cfg) -- API access ---@class pocket_ioctl_api io.api = { + get_fac = function () comms.api__get_facility() end, get_unit = function (unit) comms.api__get_unit(unit) end, get_ctrl = function () comms.api__get_control() end, get_proc = function () comms.api__get_process() end, diff --git a/pocket/iorx.lua b/pocket/iorx.lua index 528c2f4..76fcd9b 100644 --- a/pocket/iorx.lua +++ b/pocket/iorx.lua @@ -12,6 +12,8 @@ local ALARM_STATE = types.ALARM_STATE local BLR_STATE = types.BOILER_STATE local TRB_STATE = types.TURBINE_STATE local TNK_STATE = types.TANK_STATE +local MTX_STATE = types.IMATRIX_STATE +local SPS_STATE = types.SPS_STATE local io ---@type pocket_ioctl local iorx = {} ---@class iorx @@ -55,6 +57,11 @@ local function _record_multiblock_status(faulted, data, ps) ps.publish("formed", data.formed) ps.publish("faulted", faulted) + ---@todo revisit this + if data.build then + for key, val in pairs(data.build) do ps.publish(key, val) end + end + for key, val in pairs(data.state) do ps.publish(key, val) end for key, val in pairs(data.tanks) do ps.publish(key, val) end end @@ -647,12 +654,169 @@ function iorx.record_waste_data(data) fac.ps.publish("po_am_rate", fac.waste_stats[5]) fac.ps.publish("spent_waste_rate", fac.waste_stats[6]) - fac.ps.publish("sps_computed_status", f_data[8]) + fac.sps_ps_tbl[1].publish("SPSStateStatus", f_data[8]) fac.ps.publish("sps_process_rate", f_data[9]) end -function iorx.record_fac_detail_data(data) +-- update facility app with facility and unit data from API_GET_FAC_DTL +---@param data table +function iorx.record_fac_detail_data(data) + local fac = io.facility + + local tank_statuses = data[5] + local next_t_stat = 1 + + -- annunciator + + fac.all_sys_ok = data[1] + fac.rtu_count = data[2] + fac.auto_scram = data[3] + fac.ascram_status = data[4] + + fac.ps.publish("all_sys_ok", fac.all_sys_ok) + fac.ps.publish("rtu_count", fac.rtu_count) + fac.ps.publish("auto_scram", fac.auto_scram) + fac.ps.publish("as_matrix_fault", fac.ascram_status.matrix_fault) + fac.ps.publish("as_matrix_fill", fac.ascram_status.matrix_fill) + fac.ps.publish("as_crit_alarm", fac.ascram_status.crit_alarm) + fac.ps.publish("as_radiation", fac.ascram_status.radiation) + fac.ps.publish("as_gen_fault", fac.ascram_status.gen_fault) + + -- unit data + + local units = data[12] + + for i = 1, io.facility.num_units do + local unit = io.units[i] + local u_rx = units[i] + + unit.connected = u_rx[1] + unit.annunciator = u_rx[2] + unit.reactor_data = u_rx[3] + + local control_status = 1 + if unit.connected then + if unit.reactor_data.rps_tripped then control_status = 2 end + if unit.reactor_data.mek_status.status then + control_status = util.trinary(unit.annunciator.AutoControl, 4, 3) + end + end + + unit.unit_ps.publish("U_ControlStatus", control_status) + + unit.tank_data_tbl = u_rx[4] + + for id = 1, #unit.tank_data_tbl do + local tank = unit.tank_data_tbl[id] + local ps = unit.tank_ps_tbl[id] + local c_stat = tank_statuses[next_t_stat] + + local tank_status = 1 + + if c_stat ~= TNK_STATE.OFFLINE then + if c_stat == TNK_STATE.FAULT then + tank_status = 3 + elseif tank.formed then + tank_status = 4 + else + tank_status = 2 + end + end + + ps.publish("DynamicTankStatus", tank_status) + ps.publish("DynamicTankStateStatus", c_stat) + + next_t_stat = next_t_stat + 1 + end + end + + -- facility dynamic tank data + + fac.tank_data_tbl = data[6] + + for id = 1, #fac.tank_data_tbl do + local tank = fac.tank_data_tbl[id] + local ps = fac.tank_ps_tbl[id] + local c_stat = tank_statuses[next_t_stat] + + local tank_status = 1 + + if c_stat ~= TNK_STATE.OFFLINE then + if c_stat == TNK_STATE.FAULT then + tank_status = 3 + elseif tank.formed then + tank_status = 4 + else + tank_status = 2 + end + + _record_multiblock_status(c_stat == TNK_STATE.FAULT, tank, ps) + end + + ps.publish("DynamicTankStatus", tank_status) + ps.publish("DynamicTankStateStatus", c_stat) + + next_t_stat = next_t_stat + 1 + end + + -- induction matrix data + + fac.induction_data_tbl[1] = data[8] + + local matrix = fac.induction_data_tbl[1] + local m_ps = fac.induction_ps_tbl[1] + local m_stat = data[7] + + local mtx_status = 1 + + if m_stat ~= MTX_STATE.OFFLINE then + if m_stat == MTX_STATE.FAULT then + mtx_status = 3 + elseif matrix.formed then + mtx_status = 4 + else + mtx_status = 2 + end + + _record_multiblock_status(m_stat == MTX_STATE.FAULT, matrix, m_ps) + end + + m_ps.publish("InductionMatrixStatus", mtx_status) + m_ps.publish("InductionMatrixStateStatus", m_stat) + + m_ps.publish("eta_string", data[9][1]) + m_ps.publish("avg_charge", data[9][2]) + m_ps.publish("avg_inflow", data[9][3]) + m_ps.publish("avg_outflow", data[9][4]) + m_ps.publish("is_charging", data[9][5]) + m_ps.publish("is_discharging", data[9][6]) + m_ps.publish("at_max_io", data[9][7]) + + -- sps data + + fac.sps_data_tbl[1] = data[11] + + local sps = fac.sps_data_tbl[1] + local s_ps = fac.sps_ps_tbl[1] + local s_stat = data[10] + + local sps_status = 1 + + if s_stat ~= SPS_STATE.OFFLINE then + if s_stat == SPS_STATE.FAULT then + sps_status = 3 + elseif sps.formed then + sps_status = 4 + else + sps_status = 2 + end + + _record_multiblock_status(s_stat == SPS_STATE.FAULT, sps, s_ps) + end + + s_ps.publish("SPSStatus", sps_status) + s_ps.publish("SPSStateStatus", s_stat) end return function (io_obj) diff --git a/pocket/pocket.lua b/pocket/pocket.lua index d022ec1..511190c 100644 --- a/pocket/pocket.lua +++ b/pocket/pocket.lua @@ -554,6 +554,11 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav) if self.sv.linked then _send_sv(MGMT_TYPE.DIAG_ALARM_SET, { id, state }) end end + -- coordinator get facility app data + function public.api__get_facility() + if self.api.linked then _send_api(CRDN_TYPE.API_GET_FAC_DTL, {}) end + end + -- coordinator get unit data function public.api__get_unit(unit) if self.api.linked then _send_api(CRDN_TYPE.API_GET_UNIT, { unit }) end @@ -730,6 +735,10 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav) if _check_length(packet, 11) then iocontrol.rx.record_facility_data(packet.data) end + elseif packet.type == CRDN_TYPE.API_GET_FAC_DTL then + if _check_length(packet, 12) then + iocontrol.rx.record_fac_detail_data(packet.data) + end elseif packet.type == CRDN_TYPE.API_GET_UNIT then if _check_length(packet, 12) and type(packet.data[1]) == "number" and iocontrol.get_db().units[packet.data[1]] then iocontrol.rx.record_unit_data(packet.data) diff --git a/pocket/ui/apps/facility.lua b/pocket/ui/apps/facility.lua index 0b38c07..df86348 100644 --- a/pocket/ui/apps/facility.lua +++ b/pocket/ui/apps/facility.lua @@ -31,7 +31,6 @@ local cpair = core.cpair local APP_ID = pocket.APP_ID -local text_fg = style.text_fg local label_fg_bg = style.label local lu_col = style.label_unit_pair @@ -40,7 +39,6 @@ local mode_states = style.icon_states.mode_states local red_ind_s = style.icon_states.red_ind_s local yel_ind_s = style.icon_states.yel_ind_s local grn_ind_s = style.icon_states.grn_ind_s -local wht_ind_s = style.icon_states.wht_ind_s -- new unit page view ---@param root Container parent @@ -61,9 +59,6 @@ local function new_view(root) app.set_sidebar({ { label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = db.nav.go_home } }) - local btn_fg_bg = cpair(colors.orange, colors.black) - local btn_active = cpair(colors.white, colors.black) - local tank_page_navs = {} local page_div = nil ---@type Div|nil @@ -80,7 +75,7 @@ local function new_view(root) local last_update = 0 local function update() if util.time_ms() - last_update >= 500 then - -- db.api.get_fac() + db.api.get_fac() last_update = util.time_ms() end end @@ -96,19 +91,27 @@ local function new_view(root) TextBox{parent=f_div,y=1,text="Facility",alignment=ALIGN.CENTER} - TextBox{parent=f_div,y=3,text="Induction Matrix",alignment=ALIGN.CENTER} + local mtx_state = IconIndicator{parent=f_div,y=3,label="Matrix Status",states=basic_states} + local sps_state = IconIndicator{parent=f_div,label="SPS Status",states=basic_states} + mtx_state.register(fac.induction_ps_tbl[1], "InductionMatrixStatus", mtx_state.update) + sps_state.register(fac.sps_ps_tbl[1], "SPSStatus", sps_state.update) - local eta = TextBox{parent=f_div,x=1,y=5,text="ETA Unknown",alignment=ALIGN.CENTER,fg_bg=cpair(colors.white,colors.gray)} + TextBox{parent=f_div,y=6,text="RTU Gateways",fg_bg=label_fg_bg} + local rtu_count = DataIndicator{parent=f_div,x=19,y=6,label="",format="%3d",value=0,lu_colors=lu_col,width=3} + rtu_count.register(f_ps, "rtu_count", rtu_count.update) + + TextBox{parent=f_div,y=8,text="Induction Matrix",alignment=ALIGN.CENTER} + + local eta = TextBox{parent=f_div,x=1,y=10,text="ETA Unknown",alignment=ALIGN.CENTER,fg_bg=cpair(colors.white,colors.gray)} eta.register(fac.induction_ps_tbl[1], "eta_string", eta.set_value) - TextBox{parent=f_div,y=7,text="Unit Statuses",alignment=ALIGN.CENTER} + TextBox{parent=f_div,y=12,text="Unit Statuses",alignment=ALIGN.CENTER} f_div.line_break() for i = 1, fac.num_units do local ctrl = IconIndicator{parent=f_div,label="U"..i.." Control State",states=mode_states} ctrl.register(db.units[i].unit_ps, "U_ControlStatus", ctrl.update) - f_div.line_break(); end --#endregion @@ -129,8 +132,8 @@ local function new_view(root) local sps = IconIndicator{parent=a_div,label="SPS Connected",states=grn_ind_s} all_ok.register(f_ps, "all_sys_ok", all_ok.update) - -- ind_mat.register(fac.induction_ps_tbl[1], "computed_status", function (status) ind_mat.update(status > 1) end) - -- sps.register(fac.sps_ps_tbl[1], "computed_status", function (status) sps.update(status > 1) end) + ind_mat.register(fac.induction_ps_tbl[1], "InductionMatrixStateStatus", function (status) ind_mat.update(status > 1) end) + sps.register(fac.sps_ps_tbl[1], "SPSStateStatus", function (status) sps.update(status > 1) end) a_div.line_break() diff --git a/pocket/ui/apps/waste.lua b/pocket/ui/apps/waste.lua index 0be7dde..8037d82 100644 --- a/pocket/ui/apps/waste.lua +++ b/pocket/ui/apps/waste.lua @@ -247,7 +247,7 @@ local function new_view(root) local sps_status = StateIndicator{parent=s_div,x=5,y=3,states=style.sps.states,value=1,min_width=12} - sps_status.register(f_ps, "sps_computed_status", sps_status.update) + sps_status.register(db.facility.sps_ps_tbl[1], "SPSStateStatus", sps_status.update) TextBox{parent=s_div,y=5,text="Input Rate",width=10,fg_bg=label_fg_bg} local sps_in = DataIndicator{parent=s_div,label="",format="%16.2f",value=0,unit="mB/t",lu_colors=lu_col,width=21,fg_bg=text_fg} diff --git a/pocket/ui/pages/facility_matrix.lua b/pocket/ui/pages/facility_matrix.lua index a66f2a9..77640b1 100644 --- a/pocket/ui/pages/facility_matrix.lua +++ b/pocket/ui/pages/facility_matrix.lua @@ -1,6 +1,3 @@ -local types = require("scada-common.types") -local util = require("scada-common.util") - local iocontrol = require("pocket.iocontrol") local style = require("pocket.ui.style") @@ -25,17 +22,8 @@ local label = style.label local lu_col = style.label_unit_pair local text_fg = style.text_fg -local basic_states = style.icon_states.basic_states -local mode_states = style.icon_states.mode_states -local red_ind_s = style.icon_states.red_ind_s -local yel_ind_s = style.icon_states.yel_ind_s -local grn_ind_s = style.icon_states.grn_ind_s -local wht_ind_s = style.icon_states.wht_ind_s - -local mode_ind_s = { - { color = cpair(colors.black, colors.lightGray), symbol = "-" }, - { color = cpair(colors.black, colors.white), symbol = "+" } -} +local yel_ind_s = style.icon_states.yel_ind_s +local wht_ind_s = style.icon_states.wht_ind_s -- create an induction matrix view for the facility app ---@param app pocket_app @@ -75,12 +63,12 @@ return function (app, panes, matrix_pane, ps, update) in_bar.register(ps, "last_input", function (val) in_bar.update(calc_saturation(val)) end) out_bar.register(ps, "last_output", function (val) out_bar.update(calc_saturation(val)) end) - local energy = PowerIndicator{parent=mtx_div,x=1,y=11,lu_colors=lu_col,label="Chg: ",unit=db.energy_label,format="%8.2f",value=0,width=21,fg_bg=text_fg} - local avg_chg = PowerIndicator{parent=mtx_div,x=1,lu_colors=lu_col,label="\xb7Avg: ",unit=db.energy_label,format="%8.2f",value=0,width=21,fg_bg=text_fg} - local input = PowerIndicator{parent=mtx_div,x=1,lu_colors=lu_col,label="In: ",unit=db.energy_label,format="%8.2f",rate=true,value=0,width=21,fg_bg=text_fg} - local avg_in = PowerIndicator{parent=mtx_div,x=1,lu_colors=lu_col,label="\xb7Avg: ",unit=db.energy_label,format="%8.2f",rate=true,value=0,width=21,fg_bg=text_fg} - local output = PowerIndicator{parent=mtx_div,x=1,lu_colors=lu_col,label="Out: ",unit=db.energy_label,format="%8.2f",rate=true,value=0,width=21,fg_bg=text_fg} - local avg_out = PowerIndicator{parent=mtx_div,x=1,lu_colors=lu_col,label="\xb7Avg: ",unit=db.energy_label,format="%8.2f",rate=true,value=0,width=21,fg_bg=text_fg} + local energy = PowerIndicator{parent=mtx_div,y=11,lu_colors=lu_col,label="Chg: ",unit=db.energy_label,format="%8.2f",value=0,width=21,fg_bg=text_fg} + local avg_chg = PowerIndicator{parent=mtx_div,lu_colors=lu_col,label="\xb7Avg: ",unit=db.energy_label,format="%8.2f",value=0,width=21,fg_bg=text_fg} + local input = PowerIndicator{parent=mtx_div,lu_colors=lu_col,label="In: ",unit=db.energy_label,format="%8.2f",rate=true,value=0,width=21,fg_bg=text_fg} + local avg_in = PowerIndicator{parent=mtx_div,lu_colors=lu_col,label="\xb7Avg: ",unit=db.energy_label,format="%8.2f",rate=true,value=0,width=21,fg_bg=text_fg} + local output = PowerIndicator{parent=mtx_div,lu_colors=lu_col,label="Out: ",unit=db.energy_label,format="%8.2f",rate=true,value=0,width=21,fg_bg=text_fg} + local avg_out = PowerIndicator{parent=mtx_div,lu_colors=lu_col,label="\xb7Avg: ",unit=db.energy_label,format="%8.2f",rate=true,value=0,width=21,fg_bg=text_fg} energy.register(ps, "energy", function (val) energy.update(db.energy_convert(val)) end) avg_chg.register(ps, "avg_charge", avg_chg.update) @@ -122,7 +110,7 @@ return function (app, panes, matrix_pane, ps, update) out_util.register(ps, "last_output", function (x) out_util.update(calc_saturation(x) * 100) end) TextBox{parent=mtx_ext_div,text="Capacity ("..db.energy_label..")",x=1,y=13,fg_bg=label} - local capacity = DataIndicator{parent=mtx_ext_div,y=14,lu_colors=lu_col,label="",unit="",format="%21d",value=1000000000000,width=21,fg_bg=text_fg} + local capacity = DataIndicator{parent=mtx_ext_div,y=14,lu_colors=lu_col,label="",unit="",format="%21d",value=0,width=21,fg_bg=text_fg} TextBox{parent=mtx_ext_div,text="Max In/Out ("..db.energy_label.."/t)",x=1,y=15,fg_bg=label} local trans_cap = DataIndicator{parent=mtx_ext_div,y=16,lu_colors=lu_col,label="",unit="",format="%21d",rate=true,value=0,width=21,fg_bg=text_fg} diff --git a/pocket/ui/pages/facility_sps.lua b/pocket/ui/pages/facility_sps.lua index 3e3e25d..1de23ca 100644 --- a/pocket/ui/pages/facility_sps.lua +++ b/pocket/ui/pages/facility_sps.lua @@ -11,7 +11,6 @@ local PushButton = require("graphics.elements.controls.PushButton") local DataIndicator = require("graphics.elements.indicators.DataIndicator") local HorizontalBar = require("graphics.elements.indicators.HorizontalBar") -local PowerIndicator = require("graphics.elements.indicators.PowerIndicator") local StateIndicator = require("graphics.elements.indicators.StateIndicator") local ALIGN = core.ALIGN @@ -38,22 +37,19 @@ return function (app, panes, sps_pane, ps, update) TextBox{parent=sps_div,y=1,text="Facility SPS",alignment=ALIGN.CENTER} local status = StateIndicator{parent=sps_div,x=5,y=3,states=style.sps.states,value=1,min_width=12} - status.register(ps, "sps_computed_status", status.update) + status.register(ps, "SPSStateStatus", status.update) TextBox{parent=sps_div,text="Po",y=5,fg_bg=label} local po_bar = HorizontalBar{parent=sps_div,x=4,y=5,fg_bg=cpair(colors.cyan,colors.gray),height=1} TextBox{parent=sps_div,text="AM",y=7,fg_bg=label} local am_bar = HorizontalBar{parent=sps_div,x=4,y=7,fg_bg=cpair(colors.purple,colors.gray),height=1} - TextBox{parent=sps_div,text="En",y=9,fg_bg=label} - local energy_bar = HorizontalBar{parent=sps_div,x=4,y=9,fg_bg=cpair(colors.green,colors.gray),height=1} po_bar.register(ps, "input_fill", po_bar.update) am_bar.register(ps, "output_fill", am_bar.update) - energy_bar.register(ps, "energy_fill", energy_bar.update) - TextBox{parent=sps_div,y=11,text="Input Rate",width=10,fg_bg=label} + TextBox{parent=sps_div,y=9,text="Input Rate",width=10,fg_bg=label} local input_rate = DataIndicator{parent=sps_div,label="",format="%16.2f",value=0,unit="mB/t",lu_colors=lu_col,width=21,fg_bg=text_fg} - TextBox{parent=sps_div,y=14,text="Production Rate",width=15,fg_bg=label} + TextBox{parent=sps_div,y=12,text="Production Rate",width=15,fg_bg=label} local proc_rate = DataIndicator{parent=sps_div,label="",format="%16d",value=0,unit="\xb5B/t",lu_colors=lu_col,width=21,fg_bg=text_fg} proc_rate.register(ps, "process_rate", function (r) proc_rate.update(r * 1000) end) @@ -84,12 +80,5 @@ return function (app, panes, sps_pane, ps, update) output_p.register(ps, "output_fill", function (x) output_p.update(x * 100) end) output_amnt.register(ps, "output", function (x) output_amnt.update(x.amount) end) - TextBox{parent=sps_ext_div,text="Energy Fill",x=1,y=9,width=11,fg_bg=label} - local energy_p = DataIndicator{parent=sps_ext_div,x=14,y=9,lu_colors=lu_col,label="",unit="%",format="%6.2f",value=0,width=8,fg_bg=text_fg} - local energy_amnt = PowerIndicator{parent=sps_ext_div,x=1,y=10,lu_colors=lu_col,label="",unit=db.energy_label,format="%17.4f",value=0,width=21,fg_bg=text_fg} - - energy_p.register(ps, "energy_fill", function (x) energy_p.update(x * 100) end) - energy_amnt.register(ps, "energy", function (val) energy_amnt.update(db.energy_convert(val)) end) - return sps_page.nav_to end