diff --git a/coordinator/iocontrol.lua b/coordinator/iocontrol.lua index 9944fe7..b41f185 100644 --- a/coordinator/iocontrol.lua +++ b/coordinator/iocontrol.lua @@ -801,7 +801,7 @@ function iocontrol.update_unit_statuses(statuses) local burn_rate = 0.0 - if type(status) ~= "table" or #status ~= 5 then + if type(status) ~= "table" or #status ~= 6 then log.debug(log_header .. "invalid status entry in unit statuses (not a table or invalid length)") valid = false else @@ -1122,6 +1122,30 @@ function iocontrol.update_unit_statuses(statuses) valid = false end + -- valve states + local valve_states = status[6] + + if type(valve_states) == "table" then + if #valve_states == 5 then + unit.unit_ps.publish("V_pu_conn", valve_states[1] > 0) + unit.unit_ps.publish("V_pu_state", valve_states[1] == 2) + unit.unit_ps.publish("V_po_conn", valve_states[2] > 0) + unit.unit_ps.publish("V_po_state", valve_states[2] == 2) + unit.unit_ps.publish("V_pl_conn", valve_states[3] > 0) + unit.unit_ps.publish("V_pl_state", valve_states[3] == 2) + unit.unit_ps.publish("V_am_conn", valve_states[4] > 0) + unit.unit_ps.publish("V_am_state", valve_states[4] == 2) + unit.unit_ps.publish("V_emc_conn", valve_states[5] > 0) + unit.unit_ps.publish("V_emc_state", valve_states[5] == 2) + else + log.debug(log_header .. "valve states length mismatch") + valid = false + end + else + log.debug(log_header .. "valve states not a table") + valid = false + end + -- determine waste production for this unit, add to statistics local is_pu = unit.waste_product == types.WASTE_PRODUCT.PLUTONIUM diff --git a/coordinator/ui/components/unit_flow.lua b/coordinator/ui/components/unit_flow.lua index 6a81e22..5ca17b7 100644 --- a/coordinator/ui/components/unit_flow.lua +++ b/coordinator/ui/components/unit_flow.lua @@ -45,6 +45,7 @@ local function make(parent, x, y, wide, unit) local v_start = 1 + ((unit.unit_id - 1) * 4) local prv_start = 1 + ((unit.unit_id - 1) * 3) + local v_fields = { "pu", "po", "pl", "am" } local v_names = { sprintf("PV%02d-PU", v_start), sprintf("PV%02d-PO", v_start + 1), @@ -169,7 +170,9 @@ local function make(parent, x, y, wide, unit) local function _valve(vx, vy, n) TextBox{parent=waste,x=vx,y=vy,text="\x10\x11",fg_bg=text_c,width=2,height=1} local conn = IndicatorLight{parent=waste,x=vx-3,y=vy+1,label=v_names[n],colors=ind_grn} - local state = IndicatorLight{parent=waste,x=vx-3,y=vy+2,label="STATE",colors=ind_wht} + local open = IndicatorLight{parent=waste,x=vx-3,y=vy+2,label="OPEN",colors=ind_wht} + conn.register(unit.unit_ps, util.c("V_", v_fields[n], "_conn"), conn.update) + open.register(unit.unit_ps, util.c("V_", v_fields[n], "_state"), open.update) end local function _machine(mx, my, name) diff --git a/coordinator/ui/layout/flow_view.lua b/coordinator/ui/layout/flow_view.lua index ef527cf..18b898b 100644 --- a/coordinator/ui/layout/flow_view.lua +++ b/coordinator/ui/layout/flow_view.lua @@ -254,7 +254,10 @@ local function init(main) TextBox{parent=main,x=12,y=vy,text="\x10\x11",fg_bg=cpair(colors.black,colors.lightGray),width=2,height=1} local conn = IndicatorLight{parent=main,x=9,y=vy+1,label=util.sprintf("PV%02d-EMC", i + 13),colors=cpair(colors.green,colors.gray)} - local state = IndicatorLight{parent=main,x=9,y=vy+2,label="STATE",colors=cpair(colors.white,colors.white)} + local open = IndicatorLight{parent=main,x=9,y=vy+2,label="OPEN",colors=cpair(colors.white,colors.gray)} + + conn.register(units[i].unit_ps, "V_emc_conn", conn.update) + open.register(units[i].unit_ps, "V_emc_state", open.update) end end diff --git a/supervisor/session/coordinator.lua b/supervisor/session/coordinator.lua index c2d20cd..015b599 100644 --- a/supervisor/session/coordinator.lua +++ b/supervisor/session/coordinator.lua @@ -172,7 +172,8 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil unit.get_rtu_statuses(), unit.get_annunciator(), unit.get_alarms(), - unit.get_state() + unit.get_state(), + unit.get_valves() } end diff --git a/supervisor/session/rsctl.lua b/supervisor/session/rsctl.lua index fb17efe..1bdef5a 100644 --- a/supervisor/session/rsctl.lua +++ b/supervisor/session/rsctl.lua @@ -11,6 +11,18 @@ function rsctl.new(redstone_rtus) ---@class rs_controller local public = {} + -- check if a redstone port has available connections + ---@param port IO_PORT + ---@return boolean + function public.is_connected(port) + for i = 1, #redstone_rtus do + local db = redstone_rtus[i].get_db() ---@type redstone_session_db + if db.io[port] ~= nil then return true end + end + + return false + end + -- write to a digital redstone port (applies to all RTUs) ---@param port IO_PORT ---@param value boolean diff --git a/supervisor/unit.lua b/supervisor/unit.lua index ae646f9..cae748d 100644 --- a/supervisor/unit.lua +++ b/supervisor/unit.lua @@ -333,14 +333,28 @@ function unit.new(reactor_id, num_boilers, num_turbines) --#region redstone I/O - local __rs_w = self.io_ctl.digital_write + -- create a generic valve interface + ---@nodiscard + ---@param port IO_PORT + local function _make_valve_iface(port) + ---@class unit_valve_iface + local iface = { + open = function () self.io_ctl.digital_write(port, true) end, + close = function () self.io_ctl.digital_write(port, false) end, + -- check valve state + ---@nodiscard + ---@return 0|1|2 0 for not connected, 1 for inactive, 2 for active + check = function () return util.trinary(self.io_ctl.is_connected(port), util.trinary(self.io_ctl.digital_read(port), 2, 1), 0) end + } + return iface + end -- valves - local waste_pu = { open = function () __rs_w(IO.WASTE_PU, true) end, close = function () __rs_w(IO.WASTE_PU, false) end } - local waste_sna = { open = function () __rs_w(IO.WASTE_PO, true) end, close = function () __rs_w(IO.WASTE_PO, false) end } - local waste_po = { open = function () __rs_w(IO.WASTE_POPL, true) end, close = function () __rs_w(IO.WASTE_POPL, false) end } - local waste_sps = { open = function () __rs_w(IO.WASTE_AM, true) end, close = function () __rs_w(IO.WASTE_AM, false) end } - local emer_cool = { open = function () __rs_w(IO.U_EMER_COOL, true) end, close = function () __rs_w(IO.U_EMER_COOL, false) end } + local waste_pu = _make_valve_iface(IO.WASTE_PU) + local waste_sna = _make_valve_iface(IO.WASTE_PO) + local waste_po = _make_valve_iface(IO.WASTE_POPL) + local waste_sps = _make_valve_iface(IO.WASTE_AM) + local emer_cool = _make_valve_iface(IO.U_EMER_COOL) ---@class unit_valves self.valves = { @@ -869,6 +883,19 @@ function unit.new(reactor_id, num_boilers, num_turbines) } end + -- get valve states + ---@nodiscard + function public.get_valves() + local v = self.valves + return { + v.waste_pu.check(), + v.waste_sna.check(), + v.waste_po.check(), + v.waste_sps.check(), + v.emer_cool.check() + } + end + -- get the reactor ID ---@nodiscard function public.get_id() return self.r_id end