diff --git a/coordinator/coordinator.lua b/coordinator/coordinator.lua index 655ce58..13ec9a4 100644 --- a/coordinator/coordinator.lua +++ b/coordinator/coordinator.lua @@ -409,6 +409,8 @@ 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.length == 1 and packet.data[1] == false then + log.debug("supervisor connection denied") else log.debug("supervisor conn establish packet length mismatch") end @@ -431,7 +433,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, sv_wa local cmd = packet.data[1] local unit = packet.data[2] local ack = packet.data[3] - + if cmd == CRDN_COMMANDS.SCRAM then elseif cmd == CRDN_COMMANDS.START then elseif cmd == CRDN_COMMANDS.RESET_RPS then diff --git a/coordinator/startup.lua b/coordinator/startup.lua index 915cb26..fac7ab8 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.5.5" +local COORDINATOR_VERSION = "alpha-v0.5.6" local print = util.print local println = util.println diff --git a/graphics/elements/controls/hazard_button.lua b/graphics/elements/controls/hazard_button.lua index c0395b9..5fca7fe 100644 --- a/graphics/elements/controls/hazard_button.lua +++ b/graphics/elements/controls/hazard_button.lua @@ -38,7 +38,7 @@ local function hazard_button(args) ---@param accent color accent color local function draw_border(accent) -- top - e.window.setTextColor(args.accent) + 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") @@ -46,17 +46,17 @@ local function hazard_button(args) -- center left e.window.setCursorPos(1, 2) e.window.setTextColor(args.fg_bg.bkg) - e.window.setBackgroundColor(args.accent) + e.window.setBackgroundColor(accent) e.window.write("\x99") -- center right e.window.setTextColor(args.fg_bg.bkg) - e.window.setBackgroundColor(args.accent) + e.window.setBackgroundColor(accent) e.window.setCursorPos(9, 2) e.window.write("\x99") -- bottom - e.window.setTextColor(args.accent) + 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") @@ -90,6 +90,10 @@ local function hazard_button(args) if val then e.handle_touch(core.events.touch("", 1, 1)) end end + -- initial draw of border + ---@todo disabling will change border + draw_border(args.accent) + return e.get() end diff --git a/supervisor/session/svsessions.lua b/supervisor/session/svsessions.lua index d2ccad0..de54493 100644 --- a/supervisor/session/svsessions.lua +++ b/supervisor/session/svsessions.lua @@ -60,12 +60,9 @@ local function _sv_handle_outq(session) elseif msg.qtype == mqueue.TYPE.COMMAND then -- handle instruction/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 + if (cmd == SV_Q_CMDS.BUILD_CHANGED) and (svsessions.get_coord_session() ~= nil) then + -- notify coordinator that a build has changed + svsessions.get_coord_session().in_queue.push_command(CRD_S_CMDS.RESEND_BUILDS) end elseif msg.qtype == mqueue.TYPE.DATA then -- instruction/notification with body @@ -243,6 +240,8 @@ function svsessions.find_device_session(remote_port) end -- find a coordinator session by the remote port +-- +-- only one coordinator is allowed, but this is kept to be consistent with all other session tables ---@param remote_port integer ---@return nil function svsessions.find_coord_session(remote_port) @@ -251,6 +250,12 @@ function svsessions.find_coord_session(remote_port) return _find_session(self.coord_sessions, remote_port) end +-- get the a coordinator session if exists +---@return coord_session_struct|nil +function svsessions.get_coord_session() + return self.coord_sessions[1] +end + -- get a session by reactor ID ---@param reactor integer ---@return plc_session_struct|nil session @@ -342,27 +347,32 @@ end ---@param version string ---@return integer|false session_id function svsessions.establish_coord_session(local_port, remote_port, version) - ---@class coord_session_struct - local coord_s = { - s_type = "crd", - open = true, - version = version, - l_port = local_port, - r_port = remote_port, - in_queue = mqueue.new(), - out_queue = mqueue.new(), - instance = nil ---@type coord_session - } + if svsessions.get_coord_session() == nil then + ---@class coord_session_struct + local coord_s = { + s_type = "crd", + open = true, + version = version, + l_port = local_port, + r_port = remote_port, + in_queue = mqueue.new(), + out_queue = mqueue.new(), + instance = nil ---@type coord_session + } - coord_s.instance = coordinator.new_session(self.next_coord_id, coord_s.in_queue, coord_s.out_queue, self.facility_units) - table.insert(self.coord_sessions, coord_s) + coord_s.instance = coordinator.new_session(self.next_coord_id, coord_s.in_queue, coord_s.out_queue, self.facility_units) + table.insert(self.coord_sessions, coord_s) - log.debug("established new coordinator session to " .. remote_port .. " with ID " .. self.next_coord_id) + log.debug("established new coordinator session to " .. remote_port .. " with ID " .. self.next_coord_id) - self.next_coord_id = self.next_coord_id + 1 + self.next_coord_id = self.next_coord_id + 1 - -- success - return coord_s.instance.get_id() + -- success + return coord_s.instance.get_id() + else + -- we already have a coordinator linked + return false + end end -- attempt to identify which session's watchdog timer fired diff --git a/supervisor/startup.lua b/supervisor/startup.lua index b7acdfb..1e3148b 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.6.4" +local SUPERVISOR_VERSION = "beta-v0.6.5" local print = util.print local println = util.println diff --git a/supervisor/supervisor.lua b/supervisor/supervisor.lua index 4cf0eef..ec85623 100644 --- a/supervisor/supervisor.lua +++ b/supervisor/supervisor.lua @@ -80,15 +80,19 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen -- send coordinator connection establish response ---@param seq_id integer ---@param dest integer - local function _send_crdn_establish(seq_id, dest) + ---@param allow boolean + local function _send_crdn_establish(seq_id, dest, allow) local s_pkt = comms.scada_packet() local c_pkt = comms.crdn_packet() - local config = { self.num_reactors } + local config = { false } - for i = 1, #cooling_conf do - table.insert(config, cooling_conf[i].BOILERS) - table.insert(config, cooling_conf[i].TURBINES) + if allow then + config = { self.num_reactors } + for i = 1, #cooling_conf do + table.insert(config, cooling_conf[i].BOILERS) + table.insert(config, cooling_conf[i].TURBINES) + end end c_pkt.make(SCADA_CRDN_TYPES.ESTABLISH, config) @@ -235,11 +239,14 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen elseif packet.type == SCADA_MGMT_TYPES.RTU_ADVERT then if packet.length >= 1 then -- this is an RTU advertisement for a new session - println(util.c("connected to RTU (", packet.data[1], ") [:", r_port, "]")) + local rtu_version = packet.data[1] + -- note: this function mutates packet.data svsessions.establish_rtu_session(l_port, r_port, packet.data) + println(util.c("connected to RTU (", rtu_version, ") [:", r_port, "]")) log.debug("RTU_ADVERT: linked " .. r_port) + _send_remote_linked(packet.scada_frame.seq_num() + 1, r_port) else log.debug("RTU_ADVERT: advertisement packet empty") @@ -263,7 +270,7 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen session.in_queue.push_packet(packet) else -- any other packet should be session related, discard it - log.debug(util.c(r_port, "->", l_port, ": discarding SCADA_MGMT packet without a known session")) + log.debug(r_port .. "->" .. l_port .. ": discarding SCADA_MGMT packet without a known session") end elseif protocol == PROTOCOLS.SCADA_CRDN then -- coordinator packet @@ -273,18 +280,22 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen elseif packet.type == SCADA_CRDN_TYPES.ESTABLISH then if packet.length == 1 then -- this is an attempt to establish a new session - println(util.c("connected to coordinator (", packet.data[1], ") [:", r_port, "]")) + local s_id = svsessions.establish_coord_session(l_port, r_port, packet.data[1]) - svsessions.establish_coord_session(l_port, r_port, packet.data[1]) + if s_id ~= false then + println(util.c("connected to coordinator (", packet.data[1], ") [:", r_port, "]")) + log.debug("CRDN_ESTABLISH: connected to " .. r_port) + else + log.debug("CRDN_ESTABLISH: denied new coordinator due to already being connected to another coordinator") + end - log.debug("CRDN_ESTABLISH: connected to " .. r_port) - _send_crdn_establish(packet.scada_frame.seq_num() + 1, r_port) + _send_crdn_establish(packet.scada_frame.seq_num() + 1, r_port, (s_id ~= false)) else log.debug("CRDN_ESTABLISH: establish packet length mismatch") end else -- any other packet should be session related, discard it - log.debug(util.c(r_port, "->", l_port, ": discarding SCADA_CRDN packet without a known session")) + log.debug(r_port .. "->" .. l_port .. ": discarding SCADA_CRDN packet without a known session") end else log.debug("illegal packet type " .. protocol .. " on coordinator listening channel")