From d38e5ca5ec5a93ccd70952efccdb393093714f76 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sun, 28 Aug 2022 12:57:36 -0400 Subject: [PATCH] #86 send builds and statuses periodically --- scada-common/comms.lua | 8 ++-- supervisor/session/coordinator.lua | 76 ++++++++++++++++++++++++++++-- supervisor/session/unit.lua | 11 +++-- supervisor/startup.lua | 2 +- 4 files changed, 83 insertions(+), 14 deletions(-) diff --git a/scada-common/comms.lua b/scada-common/comms.lua index 3d18d7f..f0d18c1 100644 --- a/scada-common/comms.lua +++ b/scada-common/comms.lua @@ -51,8 +51,8 @@ local SCADA_MGMT_TYPES = { ---@alias SCADA_CRDN_TYPES integer local SCADA_CRDN_TYPES = { ESTABLISH = 0, -- initial greeting - QUERY_UNIT = 1, -- query the state of a unit - QUERY_FACILITY = 2, -- query general facility status + STRUCT_BUILDS = 1, -- mekanism structure builds + UNIT_STATUSES = 2, -- state of reactor units COMMAND_UNIT = 3, -- command a reactor unit ALARM = 4 -- alarm signaling } @@ -453,8 +453,8 @@ function comms.crdn_packet() -- check that type is known local function _crdn_type_valid() return self.type == SCADA_CRDN_TYPES.ESTABLISH or - self.type == SCADA_CRDN_TYPES.QUERY_UNIT or - self.type == SCADA_CRDN_TYPES.QUERY_FACILITY or + self.type == SCADA_CRDN_TYPES.STRUCT_BUILDS or + self.type == SCADA_CRDN_TYPES.UNIT_STATUSES or self.type == SCADA_CRDN_TYPES.COMMAND_UNIT or self.type == SCADA_CRDN_TYPES.ALARM end diff --git a/supervisor/session/coordinator.lua b/supervisor/session/coordinator.lua index 95507d2..c875e05 100644 --- a/supervisor/session/coordinator.lua +++ b/supervisor/session/coordinator.lua @@ -14,8 +14,13 @@ local println = util.println local print_ts = util.print_ts local println_ts = util.println_ts +-- retry time constants in ms +local INITIAL_WAIT = 1500 +local RETRY_PERIOD = 1000 + local PERIODICS = { - KEEP_ALIVE = 2000 + KEEP_ALIVE = 2000, + STATUS = 500 } -- coordinator supervisor session @@ -40,7 +45,16 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units) -- periodic messages periodics = { last_update = 0, - keep_alive = 0 + keep_alive = 0, + status_packet = 0 + }, + -- when to next retry one of these messages + retry_times = { + builds_packet = (util.time() + 500) + }, + -- message acknowledgements + acks = { + builds = true } } @@ -78,6 +92,34 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units) self.seq_num = self.seq_num + 1 end + -- send unit builds + local function _send_builds() + self.acks.builds = false + + local builds = {} + + for i = 1, #self.units do + local unit = self.units[i] ---@type reactor_unit + builds[unit.get_id()] = unit.get_build() + end + + _send(SCADA_CRDN_TYPES.STRUCT_BUILDS, builds) + end + + -- send unit statuses + local function _send_status() + self.acks.builds = false + + local status = {} + + for i = 1, #self.units do + local unit = self.units[i] ---@type reactor_unit + status[unit.get_id()] = { unit.get_reactor_status(), unit.get_rtu_statuses() } + end + + _send(SCADA_CRDN_TYPES.UNIT_STATUSES, status) + end + -- handle a packet ---@param pkt crdn_frame local function _handle_packet(pkt) @@ -120,10 +162,11 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units) log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type) end elseif pkt.scada_frame.protocol() == PROTOCOLS.SCADA_CRDN then - if pkt.type == SCADA_CRDN_TYPES.QUERY_UNIT then - -- return unit statuses - + if pkt.type == SCADA_CRDN_TYPES.STRUCT_BUILDS then + -- acknowledgement to coordinator receiving builds + self.acks.builds = true else + log.debug(log_header .. "handler received unexpected SCADA_CRDN packet type " .. pkt.type) end end end @@ -202,7 +245,30 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units) periodics.keep_alive = 0 end + -- unit statuses to coordinator + + periodics.status_packet = periodics.status_packet + elapsed + if periodics.status_packet >= PERIODICS.STATUS then + _send_status() + periodics.status_packet = 0 + end + self.periodics.last_update = util.time() + + --------------------- + -- attempt retries -- + --------------------- + + local rtimes = self.retry_times + + -- builds packet retry + + if not self.acks.builds then + if rtimes.builds_packet - util.time() <= 0 then + _send_builds() + rtimes.builds_packet = util.time() + RETRY_PERIOD + end + end end return self.connected diff --git a/supervisor/session/unit.lua b/supervisor/session/unit.lua index 0ca2637..051cb15 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()] = { formed = boiler.get_db().formed, build = boiler.get_db().build } + build.boilers[boiler.get_device_idx()] = { boiler.get_db().formed, boiler.get_db().build } end build.turbines = {} for i = 1, #self.turbines do local turbine = self.turbines[i] ---@type unit_session - build.turbines[turbine.get_device_idx()] = { formed = turbine.get_db().formed, build = turbine.get_db().build } + build.turbines[turbine.get_device_idx()] = { turbine.get_db().formed, turbine.get_db().build } end return build @@ -438,14 +438,14 @@ function unit.new(for_reactor, num_boilers, num_turbines) status.boilers = {} for i = 1, #self.boilers do local boiler = self.boilers[i] ---@type unit_session - status.boilers[boiler.get_device_idx()] = { state = boiler.get_db().state, tanks = boiler.get_db().tanks } + status.boilers[boiler.get_device_idx()] = { boiler.get_db().state, boiler.get_db().tanks } end -- status of turbines (including tanks) status.turbines = {} for i = 1, #self.turbines do local turbine = self.turbines[i] ---@type unit_session - status.turbines[turbine.get_device_idx()] = { state = turbine.get_db().state, tanks = turbine.get_db().tanks } + status.turbines[turbine.get_device_idx()] = { turbine.get_db().state, turbine.get_db().tanks } end return status @@ -454,6 +454,9 @@ function unit.new(for_reactor, num_boilers, num_turbines) -- get the annunciator status function public.get_annunciator() return self.db.annunciator end + -- get the reactor ID + function public.get_id() return self.r_id end + return public end diff --git a/supervisor/startup.lua b/supervisor/startup.lua index acc80bb..52922ff 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.5" +local SUPERVISOR_VERSION = "beta-v0.5.6" local print = util.print local println = util.println