From 1be57aaf13faeb7acd306c34f17f8627bfff18a8 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Mon, 20 Feb 2023 00:49:37 -0500 Subject: [PATCH] #140 partial build packet updates --- coordinator/coordinator.lua | 12 ++++-- coordinator/startup.lua | 2 +- install_manifest.json | 10 ++--- supervisor/facility.lua | 13 +++--- supervisor/session/coordinator.lua | 53 +++++++++++++++++++------ supervisor/session/plc.lua | 2 +- supervisor/session/rtu.lua | 8 ++-- supervisor/session/rtu/boilerv.lua | 10 ++--- supervisor/session/rtu/imatrix.lua | 10 ++--- supervisor/session/rtu/sna.lua | 10 ++--- supervisor/session/rtu/sps.lua | 10 ++--- supervisor/session/rtu/turbinev.lua | 10 ++--- supervisor/session/rtu/unit_session.lua | 2 +- supervisor/session/svqtypes.lua | 5 ++- supervisor/session/svsessions.lua | 19 ++++----- supervisor/startup.lua | 2 +- supervisor/unit.lua | 31 ++++++++++----- 17 files changed, 128 insertions(+), 81 deletions(-) diff --git a/coordinator/coordinator.lua b/coordinator/coordinator.lua index ff8bcee..c62bbe1 100644 --- a/coordinator/coordinator.lua +++ b/coordinator/coordinator.lua @@ -465,11 +465,15 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range end elseif packet.type == SCADA_CRDN_TYPES.UNIT_BUILDS then -- record builds - if iocontrol.record_unit_builds(packet.data) then - -- acknowledge receipt of builds - _send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.UNIT_BUILDS, {}) + if packet.length == 1 then + if iocontrol.record_unit_builds(packet.data[1]) then + -- acknowledge receipt of builds + _send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.UNIT_BUILDS, {}) + else + log.error("received invalid UNIT_BUILDS packet") + end else - log.error("received invalid UNIT_BUILDS packet") + log.debug("UNIT_BUILDS packet length mismatch") end elseif packet.type == SCADA_CRDN_TYPES.UNIT_STATUSES then -- update statuses diff --git a/coordinator/startup.lua b/coordinator/startup.lua index 1623615..85670b4 100644 --- a/coordinator/startup.lua +++ b/coordinator/startup.lua @@ -19,7 +19,7 @@ local iocontrol = require("coordinator.iocontrol") local renderer = require("coordinator.renderer") local sounder = require("coordinator.sounder") -local COORDINATOR_VERSION = "beta-v0.9.16" +local COORDINATOR_VERSION = "beta-v0.10.0" local print = util.print local println = util.println diff --git a/install_manifest.json b/install_manifest.json index 07f929a..910a948 100644 --- a/install_manifest.json +++ b/install_manifest.json @@ -4,8 +4,8 @@ "comms": "1.3.3", "reactor-plc": "beta-v0.10.11", "rtu": "beta-v0.11.1", - "supervisor": "beta-v0.11.13", - "coordinator": "beta-v0.9.16", + "supervisor": "beta-v0.12.0", + "coordinator": "beta-v0.10.0", "pocket": "alpha-v0.0.0" }, "files": { @@ -180,10 +180,10 @@ "common": 88049, "graphics": 99360, "lockbox": 100797, - "reactor-plc": 75956, + "reactor-plc": 75915, "rtu": 81676, - "supervisor": 261745, - "coordinator": 180622, + "supervisor": 265030, + "coordinator": 180849, "pocket": 335 } } \ No newline at end of file diff --git a/supervisor/facility.lua b/supervisor/facility.lua index 2dd07d5..fe9db20 100644 --- a/supervisor/facility.lua +++ b/supervisor/facility.lua @@ -814,13 +814,16 @@ function facility.new(num_reactors, cooling_conf) -- READ STATES/PROPERTIES -- -- get build properties of all machines - function public.get_build() + ---@param inc_imatrix boolean? true/nil to include induction matrix build, false to exclude + function public.get_build(inc_imatrix) local build = {} - build.induction = {} - for i = 1, #self.induction do - local matrix = self.induction[i] ---@type unit_session - build.induction[matrix.get_device_idx()] = { matrix.get_db().formed, matrix.get_db().build } + if inc_imatrix ~= false then + build.induction = {} + for i = 1, #self.induction do + local matrix = self.induction[i] ---@type unit_session + build.induction[matrix.get_device_idx()] = { matrix.get_db().formed, matrix.get_db().build } + end end return build diff --git a/supervisor/session/coordinator.lua b/supervisor/session/coordinator.lua index e49e065..ab829f4 100644 --- a/supervisor/session/coordinator.lua +++ b/supervisor/session/coordinator.lua @@ -12,6 +12,7 @@ local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES local SCADA_CRDN_TYPES = comms.SCADA_CRDN_TYPES local UNIT_COMMANDS = comms.UNIT_COMMANDS local FAC_COMMANDS = comms.FAC_COMMANDS +local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES local SV_Q_CMDS = svqtypes.SV_Q_CMDS local SV_Q_DATA = svqtypes.SV_Q_DATA @@ -24,13 +25,15 @@ local println_ts = util.println_ts -- retry time constants in ms local INITIAL_WAIT = 1500 local RETRY_PERIOD = 1000 +local PARTIAL_RETRY_PERIOD = 2000 local CRD_S_CMDS = { - RESEND_BUILDS = 1 } local CRD_S_DATA = { - CMD_ACK = 1 + CMD_ACK = 1, + RESEND_PLC_BUILD = 2, + RESEND_RTU_BUILD = 3 } coordinator.CRD_S_CMDS = CRD_S_CMDS @@ -129,7 +132,7 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility) builds[unit.get_id()] = unit.get_build() end - _send(SCADA_CRDN_TYPES.UNIT_BUILDS, builds) + _send(SCADA_CRDN_TYPES.UNIT_BUILDS, { builds }) end -- send facility status @@ -350,15 +353,6 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility) _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.retry_times.builds_packet = util.time() + RETRY_PERIOD - _send_fac_builds() - _send_unit_builds() - else - log.warning(log_header .. "unsupported command received in in_queue (this is a bug)") - end elseif message.qtype == mqueue.TYPE.DATA then -- instruction with body local cmd = message.message ---@type queue_data @@ -366,6 +360,41 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility) if cmd.key == CRD_S_DATA.CMD_ACK then local ack = cmd.val ---@type coord_ack _send(SCADA_CRDN_TYPES.UNIT_CMD, { ack.cmd, ack.unit, ack.ack }) + elseif cmd.key == CRD_S_DATA.RESEND_PLC_BUILD then + -- re-send PLC build + -- retry logic will be kept as-is, so as long as no retry is needed, this will be a small update + self.retry_times.builds_packet = util.time() + PARTIAL_RETRY_PERIOD + self.acks.unit_builds = false + + local unit_id = cmd.val + local builds = {} + + local unit = self.units[unit_id] ---@type reactor_unit + builds[unit_id] = unit.get_build(true, false, false) + + _send(SCADA_CRDN_TYPES.UNIT_BUILDS, { builds }) + elseif cmd.key == CRD_S_DATA.RESEND_RTU_BUILD then + local unit_id = cmd.val.unit + if unit_id > 0 then + -- re-send unit RTU builds + -- retry logic will be kept as-is, so as long as no retry is needed, this will be a small update + self.retry_times.u_builds_packet = util.time() + PARTIAL_RETRY_PERIOD + self.acks.unit_builds = false + + local builds = {} + + local unit = self.units[unit_id] ---@type reactor_unit + builds[unit_id] = unit.get_build(false, cmd.val.type == RTU_UNIT_TYPES.BOILER_VALVE, cmd.val.type == RTU_UNIT_TYPES.TURBINE_VALVE) + + _send(SCADA_CRDN_TYPES.UNIT_BUILDS, { builds }) + else + -- re-send facility RTU builds + -- retry logic will be kept as-is, so as long as no retry is needed, this will be a small update + self.retry_times.f_builds_packet = util.time() + PARTIAL_RETRY_PERIOD + self.acks.fac_builds = false + + _send(SCADA_CRDN_TYPES.FAC_BUILDS, { facility.get_build(cmd.val.type == RTU_UNIT_TYPES.IMATRIX) }) + end else log.warning(log_header .. "unsupported data command received in in_queue (this is a bug)") end diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index f78c6e6..3d3270b 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.lua @@ -342,7 +342,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout) if status then -- copied in structure data OK self.received_struct = true - self.out_q.push_command(svqtypes.SV_Q_CMDS.BUILD_CHANGED) + self.out_q.push_data(svqtypes.SV_Q_DATA.PLC_BUILD_CHANGED, for_reactor) 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 35eaf87..1db89cb 100644 --- a/supervisor/session/rtu.lua +++ b/supervisor/session/rtu.lua @@ -385,12 +385,12 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili _send_modbus(msg.message) elseif msg.qtype == mqueue.TYPE.COMMAND then -- handle instruction - local cmd = msg.message - if cmd == unit_session.RTU_US_CMDS.BUILD_CHANGED then - self.out_q.push_command(svqtypes.SV_Q_CMDS.BUILD_CHANGED) - end elseif msg.qtype == mqueue.TYPE.DATA then -- instruction with body + local cmd = msg.message ---@type queue_data + if cmd.key == unit_session.RTU_US_DATA.BUILD_CHANGED then + self.out_q.push_data(svqtypes.SV_Q_DATA.RTU_BUILD_CHANGED, cmd.val) + end end end end diff --git a/supervisor/session/rtu/boilerv.lua b/supervisor/session/rtu/boilerv.lua index 2f3b5b5..0cc4945 100644 --- a/supervisor/session/rtu/boilerv.lua +++ b/supervisor/session/rtu/boilerv.lua @@ -32,10 +32,10 @@ local PERIODICS = { } -- create a new boilerv rtu session runner ----@param session_id integer ----@param unit_id integer ----@param advert rtu_advertisement ----@param out_queue mqueue +---@param session_id integer RTU session ID +---@param unit_id integer RTU unit ID +---@param advert rtu_advertisement RTU advertisement table +---@param out_queue mqueue RTU unit message out queue function boilerv.new(session_id, unit_id, advert, out_queue) -- type check if advert.type ~= RTU_UNIT_TYPES.BOILER_VALVE then @@ -161,7 +161,7 @@ function boilerv.new(session_id, unit_id, advert, out_queue) self.db.build.max_boil_rate = m_pkt.data[12] self.has_build = true - out_queue.push_command(unit_session.RTU_US_CMDS.BUILD_CHANGED) + out_queue.push_data(unit_session.RTU_US_DATA.BUILD_CHANGED, { unit = advert.reactor, type = advert.type }) else log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")") end diff --git a/supervisor/session/rtu/imatrix.lua b/supervisor/session/rtu/imatrix.lua index 3ab5d4a..607c22d 100644 --- a/supervisor/session/rtu/imatrix.lua +++ b/supervisor/session/rtu/imatrix.lua @@ -32,10 +32,10 @@ local PERIODICS = { } -- create a new imatrix rtu session runner ----@param session_id integer ----@param unit_id integer ----@param advert rtu_advertisement ----@param out_queue mqueue +---@param session_id integer RTU session ID +---@param unit_id integer RTU unit ID +---@param advert rtu_advertisement RTU advertisement table +---@param out_queue mqueue RTU unit message out queue function imatrix.new(session_id, unit_id, advert, out_queue) -- type check if advert.type ~= RTU_UNIT_TYPES.IMATRIX then @@ -145,7 +145,7 @@ function imatrix.new(session_id, unit_id, advert, out_queue) self.db.build.providers = m_pkt.data[9] self.has_build = true - out_queue.push_command(unit_session.RTU_US_CMDS.BUILD_CHANGED) + out_queue.push_data(unit_session.RTU_US_DATA.BUILD_CHANGED, { unit = advert.reactor, type = advert.type }) else log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")") end diff --git a/supervisor/session/rtu/sna.lua b/supervisor/session/rtu/sna.lua index cd3415f..e2a667e 100644 --- a/supervisor/session/rtu/sna.lua +++ b/supervisor/session/rtu/sna.lua @@ -29,10 +29,10 @@ local PERIODICS = { } -- create a new sna rtu session runner ----@param session_id integer ----@param unit_id integer ----@param advert rtu_advertisement ----@param out_queue mqueue +---@param session_id integer RTU session ID +---@param unit_id integer RTU unit ID +---@param advert rtu_advertisement RTU advertisement table +---@param out_queue mqueue RTU unit message out queue function sna.new(session_id, unit_id, advert, out_queue) -- type check if advert.type ~= RTU_UNIT_TYPES.SNA then @@ -113,7 +113,7 @@ function sna.new(session_id, unit_id, advert, out_queue) self.db.build.output_cap = m_pkt.data[2] self.has_build = true - out_queue.push_command(unit_session.RTU_US_CMDS.BUILD_CHANGED) + out_queue.push_data(unit_session.RTU_US_DATA.BUILD_CHANGED, { unit = advert.reactor, type = advert.type }) else log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")") end diff --git a/supervisor/session/rtu/sps.lua b/supervisor/session/rtu/sps.lua index 3a6f4c3..9b07f3e 100644 --- a/supervisor/session/rtu/sps.lua +++ b/supervisor/session/rtu/sps.lua @@ -32,10 +32,10 @@ local PERIODICS = { } -- create a new sps rtu session runner ----@param session_id integer ----@param unit_id integer ----@param advert rtu_advertisement ----@param out_queue mqueue +---@param session_id integer RTU session ID +---@param unit_id integer RTU unit ID +---@param advert rtu_advertisement RTU advertisement table +---@param out_queue mqueue RTU unit message out queue function sps.new(session_id, unit_id, advert, out_queue) -- type check if advert.type ~= RTU_UNIT_TYPES.SPS then @@ -150,7 +150,7 @@ function sps.new(session_id, unit_id, advert, out_queue) self.db.build.max_energy = m_pkt.data[9] self.has_build = true - out_queue.push_command(unit_session.RTU_US_CMDS.BUILD_CHANGED) + out_queue.push_data(unit_session.RTU_US_DATA.BUILD_CHANGED, { unit = advert.reactor, type = advert.type }) else log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")") end diff --git a/supervisor/session/rtu/turbinev.lua b/supervisor/session/rtu/turbinev.lua index 0ac793a..3f8357f 100644 --- a/supervisor/session/rtu/turbinev.lua +++ b/supervisor/session/rtu/turbinev.lua @@ -44,10 +44,10 @@ local PERIODICS = { } -- create a new turbinev rtu session runner ----@param session_id integer ----@param unit_id integer ----@param advert rtu_advertisement ----@param out_queue mqueue +---@param session_id integer RTU session ID +---@param unit_id integer RTU unit ID +---@param advert rtu_advertisement RTU advertisement table +---@param out_queue mqueue RTU unit message out queue function turbinev.new(session_id, unit_id, advert, out_queue) -- type check if advert.type ~= RTU_UNIT_TYPES.TURBINE_VALVE then @@ -192,7 +192,7 @@ function turbinev.new(session_id, unit_id, advert, out_queue) self.db.build.max_water_output = m_pkt.data[15] self.has_build = true - out_queue.push_command(unit_session.RTU_US_CMDS.BUILD_CHANGED) + out_queue.push_data(unit_session.RTU_US_DATA.BUILD_CHANGED, { unit = advert.reactor, type = advert.type }) else log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")") end diff --git a/supervisor/session/rtu/unit_session.lua b/supervisor/session/rtu/unit_session.lua index f6e4297..27b21c0 100644 --- a/supervisor/session/rtu/unit_session.lua +++ b/supervisor/session/rtu/unit_session.lua @@ -13,10 +13,10 @@ local MODBUS_FCODE = types.MODBUS_FCODE local MODBUS_EXCODE = types.MODBUS_EXCODE local RTU_US_CMDS = { - BUILD_CHANGED = 1 } local RTU_US_DATA = { + BUILD_CHANGED = 1 } unit_session.RTU_US_CMDS = RTU_US_CMDS diff --git a/supervisor/session/svqtypes.lua b/supervisor/session/svqtypes.lua index 09ef4f1..6503d59 100644 --- a/supervisor/session/svqtypes.lua +++ b/supervisor/session/svqtypes.lua @@ -1,7 +1,6 @@ local svqtypes = {} local SV_Q_CMDS = { - BUILD_CHANGED = 1 } local SV_Q_DATA = { @@ -10,7 +9,9 @@ local SV_Q_DATA = { RESET_RPS = 3, SET_BURN = 4, __END_PLC_CMDS__ = 5, - CRDN_ACK = 6 + CRDN_ACK = 6, + PLC_BUILD_CHANGED = 7, + RTU_BUILD_CHANGED = 8 } ---@class coord_ack diff --git a/supervisor/session/svsessions.lua b/supervisor/session/svsessions.lua index b70096e..b7c8ef5 100644 --- a/supervisor/session/svsessions.lua +++ b/supervisor/session/svsessions.lua @@ -62,11 +62,6 @@ local function _sv_handle_outq(session) self.modem.transmit(session.r_port, session.l_port, msg.message.raw_sendable()) elseif msg.qtype == mqueue.TYPE.COMMAND then -- handle instruction/notification - local cmd = msg.message - 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 local cmd = msg.message ---@type queue_data @@ -89,11 +84,17 @@ local function _sv_handle_outq(session) end end else - if cmd.key == SV_Q_DATA.CRDN_ACK then - -- ack to be sent to coordinator - local crd_s = svsessions.get_coord_session() - if crd_s ~= nil then + local crd_s = svsessions.get_coord_session() + if crd_s ~= nil then + if cmd.key == SV_Q_DATA.CRDN_ACK then + -- ack to be sent to coordinator crd_s.in_queue.push_data(CRD_S_DATA.CMD_ACK, cmd.val) + elseif cmd.key == SV_Q_DATA.PLC_BUILD_CHANGED then + -- a PLC build has changed + crd_s.in_queue.push_data(CRD_S_DATA.RESEND_PLC_BUILD, cmd.val) + elseif cmd.key == SV_Q_DATA.RTU_BUILD_CHANGED then + -- an RTU build has changed + crd_s.in_queue.push_data(CRD_S_DATA.RESEND_RTU_BUILD, cmd.val) end end end diff --git a/supervisor/startup.lua b/supervisor/startup.lua index b380410..8e8246e 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -14,7 +14,7 @@ local svsessions = require("supervisor.session.svsessions") local config = require("supervisor.config") local supervisor = require("supervisor.supervisor") -local SUPERVISOR_VERSION = "beta-v0.11.13" +local SUPERVISOR_VERSION = "beta-v0.12.0" local print = util.print local println = util.println diff --git a/supervisor/unit.lua b/supervisor/unit.lua index 1eff099..258b297 100644 --- a/supervisor/unit.lua +++ b/supervisor/unit.lua @@ -678,23 +678,32 @@ function unit.new(for_reactor, num_boilers, num_turbines) end -- get build properties of all machines - function public.get_build() + ---@param inc_plc boolean? true/nil to include PLC build, false to exclude + ---@param inc_boilers boolean? true/nil to include boiler builds, false to exclude + ---@param inc_turbines boolean? true/nil to include turbine builds, false to exclude + function public.get_build(inc_plc, inc_boilers, inc_turbines) local build = {} - if self.plc_i ~= nil then - build.reactor = self.plc_i.get_struct() + if inc_plc ~= false then + if self.plc_i ~= nil then + build.reactor = self.plc_i.get_struct() + end end - 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 } + if inc_boilers ~= false then + 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 } + end 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 } + if inc_turbines ~= false then + 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 } + end end return build