diff --git a/reactor-plc/plc.lua b/reactor-plc/plc.lua index 3368047..af3383d 100644 --- a/reactor-plc/plc.lua +++ b/reactor-plc/plc.lua @@ -25,7 +25,7 @@ local println_ts = util.println_ts local PCALL_SCRAM_MSG = "pcall: Scram requires the reactor to be active." local PCALL_START_MSG = "pcall: Reactor is already active." --- RPS SAFETY CONSTANTS +--#region RPS SAFETY CONSTANTS local MAX_DAMAGE_PERCENT = 90 local MAX_DAMAGE_TEMPERATURE = 1200 @@ -33,13 +33,12 @@ local MIN_COOLANT_FILL = 0.10 local MAX_WASTE_FILL = 0.8 local MAX_HEATED_COLLANT_FILL = 0.95 --- END RPS SAFETY CONSTANTS +--#endregion END RPS SAFETY CONSTANTS ---- RPS: Reactor Protection System ---- ---- identifies dangerous states and SCRAMs reactor if warranted ---- ---- autonomous from main SCADA supervisor/coordinator control +-- RPS: Reactor Protection System
+-- identifies dangerous states and SCRAMs reactor if warranted
+-- autonomous from main SCADA supervisor/coordinator control +---@nodiscard ---@param reactor table ---@param is_formed boolean function plc.rps_init(reactor, is_formed) @@ -270,6 +269,7 @@ function plc.rps_init(reactor, is_formed) end -- check all safety conditions + ---@nodiscard ---@return boolean tripped, rps_trip_cause trip_status, boolean first_trip function public.check() local status = RPS_TRIP_CAUSE.OK @@ -359,16 +359,23 @@ function plc.rps_init(reactor, is_formed) return self.tripped, status, first_trip end + ---@nodiscard function public.status() return self.state end + ---@nodiscard function public.is_tripped() return self.tripped end + ---@nodiscard function public.get_trip_cause() return self.trip_cause end + ---@nodiscard function public.is_active() return self.reactor_enabled end + ---@nodiscard function public.is_formed() return self.formed end + ---@nodiscard function public.is_force_disabled() return self.force_disabled end -- get the runtime of the reactor if active, or the last runtime if disabled + ---@nodiscard ---@return integer runtime time since last enable function public.get_runtime() return util.trinary(self.reactor_enabled, util.time_ms() - self.enabled_at, self.last_runtime) end @@ -402,6 +409,7 @@ function plc.rps_init(reactor, is_formed) end -- Reactor PLC Communications +---@nodiscard ---@param id integer reactor ID ---@param version string PLC version ---@param modem table modem device @@ -416,8 +424,6 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, seq_num = 0, r_seq_num = nil, modem = modem, - s_port = server_port, - l_port = local_port, reactor = reactor, scrammed = false, linked = false, @@ -428,9 +434,6 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, max_burn_rate = nil } - ---@class plc_comms - local public = {} - comms.set_trusted_range(range) -- PRIVATE FUNCTIONS -- @@ -438,7 +441,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, -- configure modem channels local function _conf_channels() self.modem.closeAll() - self.modem.open(self.l_port) + self.modem.open(local_port) end _conf_channels() @@ -453,7 +456,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, r_pkt.make(id, msg_type, msg) s_pkt.make(self.seq_num, PROTOCOL.RPLC, r_pkt.raw_sendable()) - self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable()) + self.modem.transmit(server_port, local_port, s_pkt.raw_sendable()) self.seq_num = self.seq_num + 1 end @@ -467,7 +470,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, m_pkt.make(msg_type, msg) s_pkt.make(self.seq_num, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable()) - self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable()) + self.modem.transmit(server_port, local_port, s_pkt.raw_sendable()) self.seq_num = self.seq_num + 1 end @@ -614,6 +617,9 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, -- PUBLIC FUNCTIONS -- + ---@class plc_comms + local public = {} + -- reconnect a newly connected modem ---@param modem table ---@diagnostic disable-next-line: redefined-local @@ -679,9 +685,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, _send(RPLC_TYPE.STATUS, sys_status) - if self.resend_build then - _send_struct() - end + if self.resend_build then _send_struct() end end end @@ -696,12 +700,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, ---@param cause rps_trip_cause reactor protection system status function public.send_rps_alarm(cause) if self.linked then - local rps_alarm = { - cause, - table.unpack(rps.status()) - } - - _send(RPLC_TYPE.RPS_ALARM, rps_alarm) + _send(RPLC_TYPE.RPS_ALARM, { cause, table.unpack(rps.status()) }) end end @@ -745,7 +744,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, ---@param plc_state plc_state PLC state ---@param setpoints setpoints setpoint control table function public.handle_packet(packet, plc_state, setpoints) - if packet ~= nil and packet.scada_frame.local_port() == self.l_port then + if packet.scada_frame.local_port() == local_port then -- check sequence number if self.r_seq_num == nil then self.r_seq_num = packet.scada_frame.seq_num() @@ -848,9 +847,8 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, log.debug("AUTO: stopping the reactor to meet 0.0 burn rate") if rps.scram() then ack = AUTO_ACK.ZERO_DIS_OK - self.auto_last_disable = util.time_ms() else - log.debug("AUTO: automatic reactor stop failed") + log.warning("AUTO: automatic reactor stop failed") end else ack = AUTO_ACK.ZERO_DIS_OK @@ -862,10 +860,10 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, self.reactor.setBurnRate(0.01) if self.reactor.__p_is_faulted() then - log.debug("AUTO: failed to reset burn rate for auto activation") + log.warning("AUTO: failed to reset burn rate for auto activation") else if not rps.auto_activate() then - log.debug("AUTO: automatic reactor activation failed") + log.warning("AUTO: automatic reactor activation failed") end end end @@ -965,7 +963,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, if est_ack == ESTABLISH_ACK.ALLOW then println_ts("linked!") - log.debug("supervisor establish request approved") + log.info("supervisor establish request approved, PLC is linked") -- reset remote sequence number and cache self.r_seq_num = nil @@ -978,16 +976,16 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, elseif self.last_est_ack ~= est_ack then if est_ack == ESTABLISH_ACK.DENY then println_ts("link request denied, retrying...") - log.debug("establish request denied") + log.info("supervisor establish request denied, retrying") elseif est_ack == ESTABLISH_ACK.COLLISION then println_ts("reactor PLC ID collision (check config), retrying...") - log.warning("establish request collision") + log.warning("establish request collision, retrying") elseif est_ack == ESTABLISH_ACK.BAD_VERSION then println_ts("supervisor version mismatch (try updating), retrying...") - log.warning("establish request version mismatch") + log.warning("establish request version mismatch, retrying") else println_ts("invalid link response, bad channel? retrying...") - log.error("unknown establish request response") + log.error("unknown establish request response, retrying") end end @@ -1006,7 +1004,9 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor, end end + ---@nodiscard function public.is_scrammed() return self.scrammed end + ---@nodiscard function public.is_linked() return self.linked end return public diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index 90d9207..e55f0df 100644 --- a/reactor-plc/startup.lua +++ b/reactor-plc/startup.lua @@ -145,8 +145,7 @@ local function main() plc_state.no_modem = true end - -- PLC init - --- + -- PLC init
--- EVENT_CONSUMER: this function consumes events local function init() if plc_state.init_ok then @@ -170,13 +169,13 @@ local function main() log.debug("init> comms init") else println("boot> starting in offline mode") - log.debug("init> running without networking") + log.info("init> running without networking") end util.push_event("clock_start") println("boot> completed") - log.debug("init> boot completed") + log.info("init> boot completed") else println("boot> system in degraded state, awaiting devices...") log.warning("init> booted in a degraded state, awaiting peripheral connections...") diff --git a/reactor-plc/threads.lua b/reactor-plc/threads.lua index 4ea34f2..d2708fd 100644 --- a/reactor-plc/threads.lua +++ b/reactor-plc/threads.lua @@ -28,6 +28,7 @@ local MQ__COMM_CMD = { } -- main thread +---@nodiscard ---@param smem plc_shared_memory ---@param init function function threads.thread__main(smem, init) @@ -45,9 +46,9 @@ function threads.thread__main(smem, init) local loop_clock = util.new_clock(MAIN_CLOCK) -- load in from shared memory - local networked = smem.networked - local plc_state = smem.plc_state - local plc_dev = smem.plc_dev + local networked = smem.networked + local plc_state = smem.plc_state + local plc_dev = smem.plc_dev -- event loop while true do @@ -276,6 +277,7 @@ function threads.thread__main(smem, init) end -- RPS operation thread +---@nodiscard ---@param smem plc_shared_memory function threads.thread__rps(smem) ---@class parallel_thread @@ -298,10 +300,10 @@ function threads.thread__rps(smem) -- thread loop while true do -- get plc_sys fields (may have been set late due to degraded boot) - local rps = smem.plc_sys.rps - local plc_comms = smem.plc_sys.plc_comms + local rps = smem.plc_sys.rps + local plc_comms = smem.plc_sys.plc_comms -- get reactor, may have changed do to disconnect/reconnect - local reactor = plc_dev.reactor + local reactor = plc_dev.reactor -- RPS checks if plc_state.init_ok then @@ -416,6 +418,7 @@ function threads.thread__rps(smem) end -- communications sender thread +---@nodiscard ---@param smem plc_shared_memory function threads.thread__comms_tx(smem) ---@class parallel_thread @@ -491,6 +494,7 @@ function threads.thread__comms_tx(smem) end -- communications handler thread +---@nodiscard ---@param smem plc_shared_memory function threads.thread__comms_rx(smem) ---@class parallel_thread @@ -565,7 +569,8 @@ function threads.thread__comms_rx(smem) return public end --- apply setpoints +-- ramp control outputs to desired setpoints +---@nodiscard ---@param smem plc_shared_memory function threads.thread__setpoint_control(smem) ---@class parallel_thread diff --git a/scada-common/comms.lua b/scada-common/comms.lua index 1556203..0c2ccbe 100644 --- a/scada-common/comms.lua +++ b/scada-common/comms.lua @@ -334,7 +334,7 @@ function comms.rplc_packet() frame = nil, raw = {}, id = 0, - type = -1, + type = 0, ---@type RPLC_TYPE length = 0, data = {} } @@ -436,7 +436,7 @@ function comms.mgmt_packet() local self = { frame = nil, raw = {}, - type = -1, + type = 0, ---@type SCADA_MGMT_TYPE length = 0, data = {} } @@ -528,7 +528,7 @@ function comms.crdn_packet() local self = { frame = nil, raw = {}, - type = -1, + type = 0, ---@type SCADA_CRDN_TYPE length = 0, data = {} } @@ -617,13 +617,13 @@ function comms.crdn_packet() end -- coordinator API (CAPI) packet ----@todo implement for pocket access +---@todo implement for pocket access, set enum type for self.type ---@nodiscard function comms.capi_packet() local self = { frame = nil, raw = {}, - type = -1, + type = 0, length = 0, data = {} }