From 6517f78c1c741f19988b90ea153032afe8adfedd Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 10 Dec 2022 15:44:11 -0500 Subject: [PATCH] #129 induction matrix view --- coordinator/coordinator.lua | 14 +++-- coordinator/startup.lua | 2 +- coordinator/ui/components/boiler.lua | 5 +- coordinator/ui/components/imatrix.lua | 86 ++++++++++++++++++++++++++ coordinator/ui/components/reactor.lua | 7 ++- coordinator/ui/components/turbine.lua | 3 +- coordinator/ui/layout/main_view.lua | 9 ++- coordinator/ui/style.lua | 2 +- graphics/elements/indicators/power.lua | 13 +++- scada-common/comms.lua | 2 +- supervisor/session/coordinator.lua | 2 +- supervisor/startup.lua | 2 +- 12 files changed, 127 insertions(+), 20 deletions(-) create mode 100644 coordinator/ui/components/imatrix.lua diff --git a/coordinator/coordinator.lua b/coordinator/coordinator.lua index a6597c4..25ffa02 100644 --- a/coordinator/coordinator.lua +++ b/coordinator/coordinator.lua @@ -389,12 +389,16 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, sv_wa if protocol == PROTOCOLS.SCADA_CRDN then if self.sv_linked then if packet.type == SCADA_CRDN_TYPES.FAC_BUILDS then - -- record facility builds - if iocontrol.record_facility_builds(packet.data) then - -- acknowledge receipt of builds - _send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.FAC_BUILDS, {}) + if packet.length == 1 then + -- record facility builds + if iocontrol.record_facility_builds(packet.data[1]) then + -- acknowledge receipt of builds + _send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.FAC_BUILDS, {}) + else + log.error("received invalid FAC_BUILDS packet") + end else - log.error("received invalid FAC_BUILDS packet") + log.debug("FAC_BUILDS packet length mismatch") end elseif packet.type == SCADA_CRDN_TYPES.FAC_STATUS then -- update facility status diff --git a/coordinator/startup.lua b/coordinator/startup.lua index a95b861..5416a73 100644 --- a/coordinator/startup.lua +++ b/coordinator/startup.lua @@ -19,7 +19,7 @@ local iocontrol = require("coordinator.iocontrol") local renderer = require("coordinator.renderer") local sounder = require("coordinator.sounder") -local COORDINATOR_VERSION = "beta-v0.8.0" +local COORDINATOR_VERSION = "beta-v0.8.1" local print = util.print local println = util.println diff --git a/coordinator/ui/components/boiler.lua b/coordinator/ui/components/boiler.lua index c7a1b97..ee463a9 100644 --- a/coordinator/ui/components/boiler.lua +++ b/coordinator/ui/components/boiler.lua @@ -2,10 +2,11 @@ local core = require("graphics.core") local style = require("coordinator.ui.style") -local DataIndicator = require("graphics.elements.indicators.data") -local StateIndicator = require("graphics.elements.indicators.state") local Rectangle = require("graphics.elements.rectangle") local TextBox = require("graphics.elements.textbox") + +local DataIndicator = require("graphics.elements.indicators.data") +local StateIndicator = require("graphics.elements.indicators.state") local VerticalBar = require("graphics.elements.indicators.vbar") local cpair = core.graphics.cpair diff --git a/coordinator/ui/components/imatrix.lua b/coordinator/ui/components/imatrix.lua new file mode 100644 index 0000000..abd81b0 --- /dev/null +++ b/coordinator/ui/components/imatrix.lua @@ -0,0 +1,86 @@ +local core = require("graphics.core") +local util = require("scada-common.util") + +local style = require("coordinator.ui.style") + +local Div = require("graphics.elements.div") +local Rectangle = require("graphics.elements.rectangle") +local TextBox = require("graphics.elements.textbox") + +local DataIndicator = require("graphics.elements.indicators.data") +local PowerIndicator = require("graphics.elements.indicators.power") +local StateIndicator = require("graphics.elements.indicators.state") +local VerticalBar = require("graphics.elements.indicators.vbar") + +local cpair = core.graphics.cpair +local border = core.graphics.border + +local TEXT_ALIGN = core.graphics.TEXT_ALIGN + +-- new induction matrix view +---@param root graphics_element parent +---@param x integer top left x +---@param y integer top left y +---@param data imatrix_session_db matrix data +---@param ps psil ps interface +local function new_view(root, x, y, data, ps, id) + local title = "INDUCTION MATRIX" + if type(id) == "number" then title = title .. id end + + local matrix = Div{parent=root,fg_bg=style.root,width=33,height=21,x=x,y=y} + + TextBox{parent=matrix,text=" ",width=33,height=1,x=1,y=1,fg_bg=cpair(colors.lightGray,colors.gray)} + TextBox{parent=matrix,text=title,alignment=TEXT_ALIGN.CENTER,width=33,height=1,x=1,y=2,fg_bg=cpair(colors.lightGray,colors.gray)} + + local rect = Rectangle{parent=matrix,border=border(1, colors.gray, true),width=33,height=18,x=1,y=3} + + local text_fg_bg = cpair(colors.black, colors.lightGray) + local label_fg_bg = cpair(colors.gray, colors.lightGray) + local lu_col = cpair(colors.gray, colors.gray) + + local status = StateIndicator{parent=rect,x=11,y=1,states=style.imatrix.states,value=1,min_width=12} + local energy = PowerIndicator{parent=rect,x=7,y=3,lu_colors=lu_col,label="Energy: ",format="%8.2f",value=0,width=26,fg_bg=text_fg_bg} + local capacity = PowerIndicator{parent=rect,x=7,y=4,lu_colors=lu_col,label="Capacity:",format="%8.2f",value=0,width=26,fg_bg=text_fg_bg} + local input = PowerIndicator{parent=rect,x=7,y=5,lu_colors=lu_col,label="Input: ",format="%8.2f",rate=true,value=0,width=26,fg_bg=text_fg_bg} + local output = PowerIndicator{parent=rect,x=7,y=6,lu_colors=lu_col,label="Output: ",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) + + local fill = DataIndicator{parent=rect,x=11,y=8,lu_colors=lu_col,label="Fill:",unit="%",format="%8.2f",value=0,width=18,fg_bg=text_fg_bg} + + local cells = DataIndicator{parent=rect,x=11,y=10,lu_colors=lu_col,label="Cells: ",format="%7d",value=0,width=18,fg_bg=text_fg_bg} + local providers = DataIndicator{parent=rect,x=11,y=11,lu_colors=lu_col,label="Providers:",format="%7d",value=0,width=18,fg_bg=text_fg_bg} + + TextBox{parent=rect,text="Transfer Capacity",x=11,y=13,height=1,width=17,fg_bg=label_fg_bg} + local trans_cap = PowerIndicator{parent=rect,x=19,y=14,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) + + local charge = VerticalBar{parent=rect,x=2,y=2,fg_bg=cpair(colors.green,colors.gray),height=13,width=4} + local in_cap = VerticalBar{parent=rect,x=7,y=8,fg_bg=cpair(colors.red,colors.gray),height=7,width=1} + local out_cap = VerticalBar{parent=rect,x=9,y=8,fg_bg=cpair(colors.blue,colors.gray),height=7,width=1} + + TextBox{parent=rect,text="FILL",x=2,y=16,height=1,width=4,fg_bg=text_fg_bg} + TextBox{parent=rect,text="I/O",x=7,y=16,height=1,width=3,fg_bg=text_fg_bg} + + local function calc_saturation(val) + if (type(data.build) == "table") and (type(data.build.transfer_cap) == "number") and (data.build.transfer_cap > 0) then + return val / data.build.transfer_cap + else + return 0 + 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) +end + +return new_view diff --git a/coordinator/ui/components/reactor.lua b/coordinator/ui/components/reactor.lua index 8efe9ce..1c8978b 100644 --- a/coordinator/ui/components/reactor.lua +++ b/coordinator/ui/components/reactor.lua @@ -4,12 +4,13 @@ local core = require("graphics.core") local style = require("coordinator.ui.style") -local HorizontalBar = require("graphics.elements.indicators.hbar") -local DataIndicator = require("graphics.elements.indicators.data") -local StateIndicator = require("graphics.elements.indicators.state") local Rectangle = require("graphics.elements.rectangle") local TextBox = require("graphics.elements.textbox") +local DataIndicator = require("graphics.elements.indicators.data") +local HorizontalBar = require("graphics.elements.indicators.hbar") +local StateIndicator = require("graphics.elements.indicators.state") + local TEXT_ALIGN = core.graphics.TEXT_ALIGN local cpair = core.graphics.cpair diff --git a/coordinator/ui/components/turbine.lua b/coordinator/ui/components/turbine.lua index 4070eb0..5577bf3 100644 --- a/coordinator/ui/components/turbine.lua +++ b/coordinator/ui/components/turbine.lua @@ -3,10 +3,11 @@ local util = require("scada-common.util") local style = require("coordinator.ui.style") +local Rectangle = require("graphics.elements.rectangle") + local DataIndicator = require("graphics.elements.indicators.data") local PowerIndicator = require("graphics.elements.indicators.power") local StateIndicator = require("graphics.elements.indicators.state") -local Rectangle = require("graphics.elements.rectangle") local VerticalBar = require("graphics.elements.indicators.vbar") local cpair = core.graphics.cpair diff --git a/coordinator/ui/layout/main_view.lua b/coordinator/ui/layout/main_view.lua index 16c114d..7c0f05c 100644 --- a/coordinator/ui/layout/main_view.lua +++ b/coordinator/ui/layout/main_view.lua @@ -9,6 +9,7 @@ local util = require("scada-common.util") local style = require("coordinator.ui.style") local unit_overview = require("coordinator.ui.components.unit_overview") +local imatrix = require("coordinator.ui.components.imatrix") local core = require("graphics.core") @@ -72,12 +73,14 @@ local function init(monitor) TextBox{parent=main,y=cnc_y_start,text=util.strrep("\x8c", header.width()),alignment=TEXT_ALIGN.CENTER,height=1,fg_bg=cpair(colors.lightGray,colors.gray)} + cnc_y_start = cnc_y_start + 2 + -- testing ---@fixme remove test code ColorMap{parent=main,x=2,y=(main.height()-1)} - PushButton{parent=main,x=2,y=(cnc_y_start+2),text="TEST 1",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_1} + PushButton{parent=main,x=2,y=cnc_y_start,text="TEST 1",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_1} PushButton{parent=main,x=2,text="TEST 2",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_2} PushButton{parent=main,x=2,text="TEST 3",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_3} PushButton{parent=main,x=2,text="TEST 4",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_4} @@ -88,7 +91,7 @@ local function init(monitor) PushButton{parent=main,x=2,text="STOP",min_width=8,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.stop} PushButton{parent=main,x=2,text="PSCALE",min_width=8,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_power_scale} - SwitchButton{parent=main,x=12,y=(cnc_y_start+2),text="CONTAINMENT BREACH",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_breach} + SwitchButton{parent=main,x=12,y=cnc_y_start,text="CONTAINMENT BREACH",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_breach} SwitchButton{parent=main,x=12,text="CONTAINMENT RADIATION",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_rad} SwitchButton{parent=main,x=12,text="REACTOR LOST",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_lost} SwitchButton{parent=main,x=12,text="CRITICAL DAMAGE",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_crit} @@ -101,6 +104,8 @@ local function init(monitor) SwitchButton{parent=main,x=12,text="RCS TRANSIENT",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_rcs} SwitchButton{parent=main,x=12,text="TURBINE TRIP",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_turbinet} + local imatrix_1 = imatrix(main, 131, cnc_y_start, facility.induction_data_tbl[1], facility.induction_ps_tbl[1]) + return main end diff --git a/coordinator/ui/style.lua b/coordinator/ui/style.lua index 6fb8f88..24ade2e 100644 --- a/coordinator/ui/style.lua +++ b/coordinator/ui/style.lua @@ -138,7 +138,7 @@ style.imatrix = { text = "RTU FAULT" }, { - color = cpair(colors.white, colors.green), + color = cpair(colors.black, colors.green), text = "ONLINE" }, { diff --git a/graphics/elements/indicators/power.lua b/graphics/elements/indicators/power.lua index 6c7282b..e76f690 100644 --- a/graphics/elements/indicators/power.lua +++ b/graphics/elements/indicators/power.lua @@ -7,6 +7,7 @@ local element = require("graphics.element") ---@class power_indicator_args ---@field label string indicator label ---@field format string power format override (lua string format) +---@field rate boolean? whether to append /t to the end (power per tick) ---@field lu_colors? cpair label foreground color (a), unit foreground color (b) ---@field value any default value ---@field parent graphics_element @@ -57,8 +58,16 @@ local function power(args) if args.lu_colors ~= nil then e.window.setTextColor(args.lu_colors.color_b) end - -- add space so we don't end up with FEE (after having kFE for example) - if unit == "FE" then unit = "FE " end + + -- append per tick if rate is set + -- add space to FE so we don't end up with FEE (after having kFE for example) + if args.rate == true then + unit = unit .. "/t" + if unit == "FE/t" then unit = "FE/t " end + else + if unit == "FE" then unit = "FE " end + end + e.window.write(" " .. unit) end diff --git a/scada-common/comms.lua b/scada-common/comms.lua index 025a5c9..bb876dd 100644 --- a/scada-common/comms.lua +++ b/scada-common/comms.lua @@ -491,7 +491,7 @@ function comms.crdn_packet() self.type == SCADA_CRDN_TYPES.FAC_CMD or self.type == SCADA_CRDN_TYPES.UNIT_BUILDS or self.type == SCADA_CRDN_TYPES.UNIT_STATUSES or - self.type == SCADA_CRDN_TYPES.UNIT_STATUSES + self.type == SCADA_CRDN_TYPES.UNIT_CMD end -- make a coordinator packet diff --git a/supervisor/session/coordinator.lua b/supervisor/session/coordinator.lua index 2ce66df..1a5e93f 100644 --- a/supervisor/session/coordinator.lua +++ b/supervisor/session/coordinator.lua @@ -113,7 +113,7 @@ function coordinator.new_session(id, in_queue, out_queue, facility, units) -- send facility builds local function _send_fac_builds() self.acks.fac_builds = false - _send(SCADA_CRDN_TYPES.FAC_BUILDS, facility.get_build()) + _send(SCADA_CRDN_TYPES.FAC_BUILDS, { facility.get_build() }) end -- send unit builds diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 4467a3b..79fa007 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -14,7 +14,7 @@ local svsessions = require("supervisor.session.svsessions") local config = require("supervisor.config") local supervisor = require("supervisor.supervisor") -local SUPERVISOR_VERSION = "beta-v0.9.0" +local SUPERVISOR_VERSION = "beta-v0.9.1" local print = util.print local println = util.println