diff --git a/coordinator/coordinator.lua b/coordinator/coordinator.lua index 5972bfc..0b62ed2 100644 --- a/coordinator/coordinator.lua +++ b/coordinator/coordinator.lua @@ -397,8 +397,19 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, sv_wa else log.debug("supervisor conn establish packet length mismatch") end - elseif packet.type == SCADA_CRDN_TYPES.QUERY_UNIT then - elseif packet.type == SCADA_CRDN_TYPES.QUERY_FACILITY then + elseif packet.type == SCADA_CRDN_TYPES.STRUCT_BUILDS then + -- record builds + if database.populate_builds(packet.data) then + -- acknowledge receipt of builds + _send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.STRUCT_BUILDS, {}) + else + log.error("supervisor build packet invalid") + end + elseif packet.type == SCADA_CRDN_TYPES.UNIT_STATUSES then + -- update statuses + if not database.update_statuses(packet.data) then + log.error("supervisor unit status packet invalid") + end elseif packet.type == SCADA_CRDN_TYPES.COMMAND_UNIT then elseif packet.type == SCADA_CRDN_TYPES.ALARM then else diff --git a/coordinator/database.lua b/coordinator/database.lua index 3cee4ac..1edda7b 100644 --- a/coordinator/database.lua +++ b/coordinator/database.lua @@ -1,4 +1,5 @@ local psil = require("scada-common.psil") +local log = require("scada-common.log") local database = {} @@ -7,6 +8,10 @@ database.WASTE = { Pu = 0, Po = 1, AntiMatter = 2 } ---@class coord_db local db = {} +-- @todo +function database.purge_subscribers() +end + -- initialize the coordinator database ---@param conf facility_conf configuration function database.init(conf) @@ -51,6 +56,105 @@ function database.init(conf) end end +-- populate structure builds +---@param builds table +---@return boolean valid +function database.populate_builds(builds) + if #builds ~= #db.units then + log.error("number of provided unit builds does not match expected number of units") + return false + else + for i = 1, #builds do + local unit = db.units[i] ---@type coord_db_entry + local build = builds[i] + + -- reactor build + unit.reactor_data.mek_struct = build.reactor + for key, val in pairs(unit.reactor_data.mek_struct) do + unit.reactor_ps.publish(key, val) + end + + -- boiler builds + for id, boiler in pairs(build.boilers) do + unit.boiler_data_tbl[id] = { + formed = boiler[2], ---@type boolean|nil + build = boiler[1] ---@type table + } + + unit.boiler_ps_tbl[id].publish("formed", boiler[2]) + + local key_prefix = "unit_" .. i .. "_boiler_" .. id .. "_" + + for key, val in pairs(unit.boiler_data_tbl[id].build) do + unit.boiler_ps_tbl[id].publish(key_prefix .. key, val) + end + end + + -- turbine builds + for id, turbine in pairs(build.turbines) do + unit.turbine_data_tbl[id] = { + formed = turbine[2], ---@type boolean|nil + build = turbine[1] ---@type table + } + + unit.turbine_ps_tbl[id].publish("formed", turbine[2]) + + local key_prefix = "unit_" .. i .. "_turbine_" .. id .. "_" + + for key, val in pairs(unit.turbine_data_tbl[id].build) do + unit.turbine_ps_tbl[id].publish(key_prefix .. key, val) + end + end + end + end + + return true +end + +-- update unit statuses +---@param statuses table +---@return boolean valid +function database.update_statuses(statuses) + if #statuses ~= #db.units then + log.error("number of provided unit statuses does not match expected number of units") + return false + else + for i = 1, #statuses do + local unit = db.units[i] ---@type coord_db_entry + local status = statuses[i] + + -- reactor status + + local reactor_status = status[1] + local mek_status = reactor_status[1] + local rps_status = reactor_status[2] + local gen_status = reactor_status[3] + + unit.reactor_data.last_status_update = gen_status[1] + unit.reactor_data.control_state = gen_status[2] + unit.reactor_data.overridden = gen_status[3] + unit.reactor_data.degraded = gen_status[4] + unit.reactor_data.rps_tripped = gen_status[5] + unit.reactor_data.rps_trip_cause = gen_status[6] + + unit.reactor_data.rps_status = rps_status ---@type rps_status + unit.reactor_data.mek_status = mek_status ---@type mek_status + + for key, val in pairs(unit.reactor_data) do + if key ~= "mek_struct" then + unit.reactor_ps.publish(key, val) + end + end + + -- boiler statuses + + -- turbine statuses + end + end + + return true +end + -- get the database function database.get() return db end diff --git a/coordinator/renderer.lua b/coordinator/renderer.lua index 2e49026..9683f0d 100644 --- a/coordinator/renderer.lua +++ b/coordinator/renderer.lua @@ -1,4 +1,6 @@ -local log = require("scada-common.log") +local log = require("scada-common.log") + +local database = require("coordinator.database") local main_view = require("coordinator.ui.layout.main_view") local unit_view = require("coordinator.ui.layout.unit_view") @@ -9,7 +11,8 @@ local renderer = {} -- render engine local engine = { monitors = nil, - dmesg_window = nil + dmesg_window = nil, + ui_ready = false } -- UI layouts @@ -82,11 +85,20 @@ function renderer.start_ui() for id, monitor in pairs(engine.monitors.unit_displays) do table.insert(ui.unit_layouts, unit_view(monitor, id)) end + + -- report ui as ready + engine.ui_ready = true end -- close out the UI ---@param recolor? boolean true to restore to color palette from style function renderer.close_ui(recolor) + -- delete all subscribers + database.purge_subscribers() + + -- report ui as not ready + engine.ui_ready = false + -- clear root UI elements ui.main_layout = nil ui.unit_layouts = {} @@ -99,6 +111,10 @@ function renderer.close_ui(recolor) engine.dmesg_window.redraw() end +-- is the UI ready? +---@return boolean ready +function renderer.ui_ready() return engine.ui_ready end + -- handle a touch event ---@param event monitor_touch function renderer.handle_touch(event) diff --git a/coordinator/startup.lua b/coordinator/startup.lua index 9b23416..7b72f25 100644 --- a/coordinator/startup.lua +++ b/coordinator/startup.lua @@ -16,7 +16,7 @@ local config = require("coordinator.config") local coordinator = require("coordinator.coordinator") local renderer = require("coordinator.renderer") -local COORDINATOR_VERSION = "alpha-v0.3.14" +local COORDINATOR_VERSION = "alpha-v0.4.0" local print = util.print local println = util.println diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index b9e0c56..a310f52 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.lua @@ -443,12 +443,12 @@ function plc.new_session(id, for_reactor, in_queue, out_queue) -- get the general status information function public.get_general_status() return { - last_status_update = self.sDB.last_status_update, - control_state = self.sDB.control_state, - overridden = self.sDB.overridden, - degraded = self.sDB.degraded, - rps_tripped = self.sDB.rps_tripped, - rps_trip_cause = self.sDB.rps_trip_cause + self.sDB.last_status_update, + self.sDB.control_state, + self.sDB.overridden, + self.sDB.degraded, + self.sDB.rps_tripped, + self.sDB.rps_trip_cause } end diff --git a/supervisor/session/unit.lua b/supervisor/session/unit.lua index 051cb15..5008d6a 100644 --- a/supervisor/session/unit.lua +++ b/supervisor/session/unit.lua @@ -404,13 +404,13 @@ function unit.new(for_reactor, num_boilers, num_turbines) build.boilers = {} for i = 1, #self.boilers do local boiler = self.boilers[i] ---@type unit_session - build.boilers[boiler.get_device_idx()] = { boiler.get_db().formed, boiler.get_db().build } + build.boilers[boiler.get_device_idx()] = { boiler.get_db().build, boiler.get_db().formed } end build.turbines = {} for i = 1, #self.turbines do local turbine = self.turbines[i] ---@type unit_session - build.turbines[turbine.get_device_idx()] = { turbine.get_db().formed, turbine.get_db().build } + build.turbines[turbine.get_device_idx()] = { turbine.get_db().build, turbine.get_db().formed } end return build @@ -422,9 +422,7 @@ function unit.new(for_reactor, num_boilers, num_turbines) if self.plc_s ~= nil then local reactor = self.plc_s - status.mek = reactor.get_status() - status.rps = reactor.get_rps() - status.general = reactor.get_general_status() + status = { reactor.get_status(), reactor.get_rps(), reactor.get_general_status() } end return status @@ -448,6 +446,8 @@ function unit.new(for_reactor, num_boilers, num_turbines) status.turbines[turbine.get_device_idx()] = { turbine.get_db().state, turbine.get_db().tanks } end + ---@todo other RTU statuses + return status end diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 52922ff..fdeedc1 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -13,7 +13,7 @@ local svsessions = require("supervisor.session.svsessions") local config = require("supervisor.config") local supervisor = require("supervisor.supervisor") -local SUPERVISOR_VERSION = "beta-v0.5.6" +local SUPERVISOR_VERSION = "beta-v0.5.7" local print = util.print local println = util.println