diff --git a/coordinator/iocontrol.lua b/coordinator/iocontrol.lua index b947f8c..f34cfab 100644 --- a/coordinator/iocontrol.lua +++ b/coordinator/iocontrol.lua @@ -86,41 +86,52 @@ function iocontrol.record_builds(builds) log.error("number of provided unit builds does not match expected number of units") return false else + -- note: if not all units and RTUs are connected, some will be nil for i = 1, #builds do local unit = io.units[i] ---@type ioctl_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) + if type(build.reactor) == "table" then + 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 + + if unit.reactor_data.mek_struct.length ~= 0 and unit.reactor_data.mek_struct.width ~= 0 then + unit.reactor_ps.publish("size", { unit.reactor_data.mek_struct.length, unit.reactor_data.mek_struct.width }) + end 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 - } + if type(build.boilers) == "table" then + 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]) + unit.boiler_ps_tbl[id].publish("formed", boiler[2]) - for key, val in pairs(unit.boiler_data_tbl[id].build) do - unit.boiler_ps_tbl[id].publish(key, val) + for key, val in pairs(unit.boiler_data_tbl[id].build) do + unit.boiler_ps_tbl[id].publish(key, val) + end 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 - } + if type(build.turbines) == "table" then + 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]) + unit.turbine_ps_tbl[id].publish("formed", turbine[2]) - for key, val in pairs(unit.turbine_data_tbl[id].build) do - unit.turbine_ps_tbl[id].publish(key, val) + for key, val in pairs(unit.turbine_data_tbl[id].build) do + unit.turbine_ps_tbl[id].publish(key, val) + end end end end diff --git a/coordinator/startup.lua b/coordinator/startup.lua index 47c1dc8..396a116 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.4.15" +local COORDINATOR_VERSION = "alpha-v0.5.0" local print = util.print local println = util.println diff --git a/coordinator/ui/components/unit_detail.lua b/coordinator/ui/components/unit_detail.lua index 2ef2dbe..2244fd3 100644 --- a/coordinator/ui/components/unit_detail.lua +++ b/coordinator/ui/components/unit_detail.lua @@ -47,9 +47,9 @@ local function init(parent, id) -- main stats and core map -- - ---@todo need to be checking actual reactor dimensions somehow local core_map = CoreMap{parent=main,x=2,y=3,reactor_l=18,reactor_w=18} r_ps.subscribe("temp", core_map.update) + r_ps.subscribe("size", function (s) core_map.resize(s[1], s[2]) end) local stat_fg_bg = cpair(colors.black,colors.white) diff --git a/graphics/elements/controls/scram_button.lua b/graphics/elements/controls/scram_button.lua index fc12d67..1abe8a1 100644 --- a/graphics/elements/controls/scram_button.lua +++ b/graphics/elements/controls/scram_button.lua @@ -5,6 +5,8 @@ local tcd = require("scada-common.tcallbackdsp") local core = require("graphics.core") local element = require("graphics.element") +local accent = colors.yellow + ---@class scram_button_args ---@field callback function function to call on touch ---@field parent graphics_element @@ -33,7 +35,7 @@ local function scram_button(args) -- draw border -- top - e.window.setTextColor(colors.yellow) + e.window.setTextColor(accent) e.window.setBackgroundColor(args.fg_bg.bkg) e.window.setCursorPos(1, 1) e.window.write("\x99\x89\x89\x89\x89\x89\x89\x89\x99") @@ -41,17 +43,17 @@ local function scram_button(args) -- center left e.window.setCursorPos(1, 2) e.window.setTextColor(args.fg_bg.bkg) - e.window.setBackgroundColor(colors.yellow) + e.window.setBackgroundColor(accent) e.window.write("\x99") -- center right e.window.setTextColor(args.fg_bg.bkg) - e.window.setBackgroundColor(colors.yellow) + e.window.setBackgroundColor(accent) e.window.setCursorPos(9, 2) e.window.write("\x99") -- bottom - e.window.setTextColor(colors.yellow) + e.window.setTextColor(accent) e.window.setBackgroundColor(args.fg_bg.bkg) e.window.setCursorPos(1, 3) e.window.write("\x99\x98\x98\x98\x98\x98\x98\x98\x99") diff --git a/graphics/elements/controls/start_button.lua b/graphics/elements/controls/start_button.lua index 59c8580..e512c31 100644 --- a/graphics/elements/controls/start_button.lua +++ b/graphics/elements/controls/start_button.lua @@ -5,6 +5,8 @@ local tcd = require("scada-common.tcallbackdsp") local core = require("graphics.core") local element = require("graphics.element") +local accent = colors.lightBlue + ---@class start_button_args ---@field callback function function to call on touch ---@field parent graphics_element @@ -33,7 +35,7 @@ local function start_button(args) -- draw border -- top - e.window.setTextColor(colors.orange) + e.window.setTextColor(accent) e.window.setBackgroundColor(args.fg_bg.bkg) e.window.setCursorPos(1, 1) e.window.write("\x99\x89\x89\x89\x89\x89\x89\x89\x99") @@ -41,17 +43,17 @@ local function start_button(args) -- center left e.window.setCursorPos(1, 2) e.window.setTextColor(args.fg_bg.bkg) - e.window.setBackgroundColor(colors.orange) + e.window.setBackgroundColor(accent) e.window.write("\x99") -- center right e.window.setTextColor(args.fg_bg.bkg) - e.window.setBackgroundColor(colors.orange) + e.window.setBackgroundColor(accent) e.window.setCursorPos(9, 2) e.window.write("\x99") -- bottom - e.window.setTextColor(colors.orange) + e.window.setTextColor(accent) e.window.setBackgroundColor(args.fg_bg.bkg) e.window.setCursorPos(1, 3) e.window.write("\x99\x98\x98\x98\x98\x98\x98\x98\x99") diff --git a/graphics/elements/indicators/coremap.lua b/graphics/elements/indicators/coremap.lua index 09a467c..0ca72e1 100644 --- a/graphics/elements/indicators/coremap.lua +++ b/graphics/elements/indicators/coremap.lua @@ -115,6 +115,9 @@ local function core_map(args) if inner_width % 2 == 0 then alternator = not alternator end end + + -- reset alternator + alternator = true end -- on state change diff --git a/rtu/config.lua b/rtu/config.lua index c97fda1..55968e1 100644 --- a/rtu/config.lua +++ b/rtu/config.lua @@ -27,26 +27,26 @@ config.RTU_DEVICES = { } -- RTU redstone interface definitions config.RTU_REDSTONE = { - { - for_reactor = 1, - io = { - { - channel = rsio.IO.WASTE_PO, - side = "top", - bundled_color = colors.blue - }, - { - channel = rsio.IO.WASTE_PU, - side = "top", - bundled_color = colors.cyan - }, - { - channel = rsio.IO.WASTE_AM, - side = "top", - bundled_color = colors.purple - } - } - } + -- { + -- for_reactor = 1, + -- io = { + -- { + -- channel = rsio.IO.WASTE_PO, + -- side = "top", + -- bundled_color = colors.blue + -- }, + -- { + -- channel = rsio.IO.WASTE_PU, + -- side = "top", + -- bundled_color = colors.cyan + -- }, + -- { + -- channel = rsio.IO.WASTE_AM, + -- side = "top", + -- bundled_color = colors.purple + -- } + -- } + -- } } return config diff --git a/supervisor/session/coordinator.lua b/supervisor/session/coordinator.lua index 80fb9d5..4860942 100644 --- a/supervisor/session/coordinator.lua +++ b/supervisor/session/coordinator.lua @@ -19,6 +19,16 @@ local println_ts = util.println_ts local INITIAL_WAIT = 1500 local RETRY_PERIOD = 1000 +local CRD_S_CMDS = { + RESEND_BUILDS = 1 +} + +local CRD_S_DATA = { +} + +coordinator.CRD_S_CMDS = CRD_S_CMDS +coordinator.CRD_S_DATA = CRD_S_DATA + local PERIODICS = { KEEP_ALIVE = 2000, STATUS = 500 @@ -51,11 +61,11 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units) }, -- when to next retry one of these messages retry_times = { - builds_packet = (util.time() + 500) + builds_packet = 0 }, -- message acknowledgements acks = { - builds = true + builds = false } } @@ -227,6 +237,13 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units) _handle_packet(message.message) elseif message.qtype == mqueue.TYPE.COMMAND then -- handle instruction + local cmd = message.message + if cmd == CRD_S_CMDS.RESEND_BUILDS then + -- re-send builds + self.acks.builds = false + self.retry_times.builds_packet = util.time() + RETRY_PERIOD + _send_builds() + end elseif message.qtype == mqueue.TYPE.DATA then -- instruction with body end diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index d80b4b1..9f01ec8 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.lua @@ -1,7 +1,9 @@ -local comms = require("scada-common.comms") -local log = require("scada-common.log") -local mqueue = require("scada-common.mqueue") -local util = require("scada-common.util") +local comms = require("scada-common.comms") +local log = require("scada-common.log") +local mqueue = require("scada-common.mqueue") +local util = require("scada-common.util") + +local svqtypes = require("supervisor.session.svqtypes") local plc = {} @@ -19,9 +21,9 @@ local INITIAL_WAIT = 1500 local RETRY_PERIOD = 1000 local PLC_S_CMDS = { - SCRAM = 0, - ENABLE = 1, - RPS_RESET = 2 + SCRAM = 1, + ENABLE = 2, + RPS_RESET = 3 } local PLC_S_DATA = { @@ -193,7 +195,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue) if self.received_struct then self.sDB.mek_status.fuel_need = self.sDB.mek_struct.fuel_cap - self.sDB.mek_status.fuel_fill self.sDB.mek_status.waste_need = self.sDB.mek_struct.waste_cap - self.sDB.mek_status.waste_fill - self.sDB.mek_status.cool_need = self.sDB.mek_struct.ccool_cap - self.sDB.mek_status.ccool_fill + self.sDB.mek_status.cool_need = self.sDB.mek_struct.ccool_cap - self.sDB.mek_status.ccool_fill self.sDB.mek_status.hcool_need = self.sDB.mek_struct.hcool_cap - self.sDB.mek_status.hcool_fill end end @@ -318,6 +320,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue) if status then -- copied in structure data OK self.received_struct = true + self.out_q.push_command(svqtypes.SV_Q_CMDS.BUILD_CHANGED) else -- error copying structure data log.error(log_header .. "failed to parse struct packet data") diff --git a/supervisor/session/rtu.lua b/supervisor/session/rtu.lua index 312c9a3..e844a9f 100644 --- a/supervisor/session/rtu.lua +++ b/supervisor/session/rtu.lua @@ -4,6 +4,8 @@ local mqueue = require("scada-common.mqueue") local rsio = require("scada-common.rsio") local util = require("scada-common.util") +local svqtypes = require("supervisor.session.svqtypes") + -- supervisor rtu sessions (svrs) local svrs_boilerv = require("supervisor.session.rtu.boilerv") local svrs_envd = require("supervisor.session.rtu.envd") @@ -192,6 +194,9 @@ function rtu.new_session(id, in_queue, out_queue, advertisement, facility_units) break end end + + -- report build changed + self.out_q.push_command(svqtypes.SV_Q_CMDS.BUILD_CHANGED) end -- mark this RTU session as closed, stop watchdog diff --git a/supervisor/session/rtu/imatrix.lua b/supervisor/session/rtu/imatrix.lua index e6a9513..d56be02 100644 --- a/supervisor/session/rtu/imatrix.lua +++ b/supervisor/session/rtu/imatrix.lua @@ -60,8 +60,8 @@ function imatrix.new(session_id, unit_id, advert, out_queue) length = 0, width = 0, height = 0, - min_pos = 0, - max_pos = 0, + min_pos = { x = 0, y = 0, z = 0 }, ---@type coordinate + max_pos = { x = 0, y = 0, z = 0 }, ---@type coordinate max_energy = 0, transfer_cap = 0, cells = 0, diff --git a/supervisor/session/rtu/sps.lua b/supervisor/session/rtu/sps.lua index 18ad727..e7a2a58 100644 --- a/supervisor/session/rtu/sps.lua +++ b/supervisor/session/rtu/sps.lua @@ -60,8 +60,8 @@ function sps.new(session_id, unit_id, advert, out_queue) length = 0, width = 0, height = 0, - min_pos = 0, - max_pos = 0, + min_pos = { x = 0, y = 0, z = 0 }, ---@type coordinate + max_pos = { x = 0, y = 0, z = 0 }, ---@type coordinate coils = 0, input_cap = 0, output_cap = 0, diff --git a/supervisor/session/svqtypes.lua b/supervisor/session/svqtypes.lua new file mode 100644 index 0000000..9814608 --- /dev/null +++ b/supervisor/session/svqtypes.lua @@ -0,0 +1,13 @@ +local svqtypes = {} + +local SV_Q_CMDS = { + BUILD_CHANGED = 0 +} + +local SV_Q_DATA = { +} + +svqtypes.SV_Q_CMDS = SV_Q_CMDS +svqtypes.SV_Q_DATA = SV_Q_DATA + +return svqtypes diff --git a/supervisor/session/svsessions.lua b/supervisor/session/svsessions.lua index 764e5bd..3ad05f4 100644 --- a/supervisor/session/svsessions.lua +++ b/supervisor/session/svsessions.lua @@ -2,6 +2,7 @@ local log = require("scada-common.log") local mqueue = require("scada-common.mqueue") local util = require("scada-common.util") +local svqtypes = require("supervisor.session.svqtypes") local unit = require("supervisor.session.unit") local coordinator = require("supervisor.session.coordinator") @@ -10,6 +11,9 @@ local rtu = require("supervisor.session.rtu") -- Supervisor Sessions Handler +local SV_Q_CMDS = svqtypes.SV_Q_CMDS +local CRD_S_CMDS = coordinator.CRD_S_CMDS + local svsessions = {} local SESSION_TYPE = { @@ -38,20 +42,30 @@ local self = { ---@param sessions table local function _iterate(sessions) for i = 1, #sessions do - local session = sessions[i] ---@type plc_session_struct|rtu_session_struct - if session.open then - local ok = session.instance.iterate() - if ok then - -- send packets in out queue - while session.out_queue.ready() do - local msg = session.out_queue.pop() - if msg ~= nil and msg.qtype == mqueue.TYPE.PACKET then + local session = sessions[i] ---@type plc_session_struct|rtu_session_struct|coord_session_struct + if session.open and session.instance.iterate() then + -- process output queues + while session.out_queue.ready() do + local msg = session.out_queue.pop() + if msg ~= nil then + if msg.qtype == mqueue.TYPE.PACKET then + -- packet to be sent self.modem.transmit(session.r_port, session.l_port, msg.message.raw_sendable()) + elseif msg.qtype == mqueue.TYPE.COMMAND then + -- notification + local cmd = msg.message + if cmd == SV_Q_CMDS.BUILD_CHANGED then + -- notify coordinator(s) that a build has changed + for j = 1, #self.coord_sessions do + local s = self.coord_sessions[j] ---@type coord_session_struct + s.in_queue.push_command(CRD_S_CMDS.RESEND_BUILDS) + end + end end end - else - session.open = false end + else + session.open = false end end end @@ -104,7 +118,10 @@ end ---@param sessions table local function _free_closed(sessions) local f = function (session) return session.open end - local on_delete = function (session) log.debug("free'ing closed session " .. session.instance.get_id() .. " on remote port " .. session.r_port) end + + local on_delete = function (session) + log.debug("free'ing closed session " .. session.instance.get_id() .. " on remote port " .. session.r_port) + end util.filter_table(sessions, f, on_delete) end diff --git a/supervisor/startup.lua b/supervisor/startup.lua index b4878b1..1756a2a 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.15" +local SUPERVISOR_VERSION = "beta-v0.6.0" local print = util.print local println = util.println