diff --git a/reactor-plc/plc.lua b/reactor-plc/plc.lua index fc41f80..d2991ae 100644 --- a/reactor-plc/plc.lua +++ b/reactor-plc/plc.lua @@ -445,14 +445,14 @@ end ---@nodiscard ---@param id integer reactor ID ---@param version string PLC version ----@param modem table modem device +---@param nic nic network interface device ---@param plc_channel integer PLC comms channel ---@param svr_channel integer supervisor server channel ---@param range integer trusted device connection range ---@param reactor table reactor device ---@param rps rps RPS reference ---@param conn_watchdog watchdog watchdog reference -function plc.comms(id, version, modem, plc_channel, svr_channel, range, reactor, rps, conn_watchdog) +function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, rps, conn_watchdog) local self = { sv_addr = comms.BROADCAST, seq_num = 0, @@ -470,13 +470,9 @@ function plc.comms(id, version, modem, plc_channel, svr_channel, range, reactor, -- PRIVATE FUNCTIONS -- - -- configure modem channels - local function _conf_channels() - modem.closeAll() - modem.open(plc_channel) - end - - _conf_channels() + -- configure network channels + nic.closeAll() + nic.open(plc_channel) -- send an RPLC packet ---@param msg_type RPLC_TYPE @@ -488,7 +484,7 @@ function plc.comms(id, version, modem, plc_channel, svr_channel, range, reactor, r_pkt.make(id, msg_type, msg) s_pkt.make(self.sv_addr, self.seq_num, PROTOCOL.RPLC, r_pkt.raw_sendable()) - modem.transmit(svr_channel, plc_channel, s_pkt.raw_sendable()) + nic.transmit(svr_channel, plc_channel, s_pkt) self.seq_num = self.seq_num + 1 end @@ -502,7 +498,7 @@ function plc.comms(id, version, modem, plc_channel, svr_channel, range, reactor, m_pkt.make(msg_type, msg) s_pkt.make(self.sv_addr, self.seq_num, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable()) - modem.transmit(svr_channel, plc_channel, s_pkt.raw_sendable()) + nic.transmit(svr_channel, plc_channel, s_pkt) self.seq_num = self.seq_num + 1 end @@ -650,13 +646,6 @@ function plc.comms(id, version, modem, plc_channel, svr_channel, range, reactor, ---@class plc_comms local public = {} - -- reconnect a newly connected modem - ---@param new_modem table - function public.reconnect_modem(new_modem) - modem = new_modem - _conf_channels() - end - -- reconnect a newly connected reactor ---@param new_reactor table function public.reconnect_reactor(new_reactor) @@ -744,12 +733,9 @@ function plc.comms(id, version, modem, plc_channel, svr_channel, range, reactor, ---@return rplc_frame|mgmt_frame|nil packet function public.parse_packet(side, sender, reply_to, message, distance) local pkt = nil - local s_pkt = comms.scada_packet() + local s_pkt = nic.receive(side, sender, reply_to, message, distance) - -- parse packet as generic SCADA packet - s_pkt.receive(side, sender, reply_to, message, distance) - - if s_pkt.is_valid() then + if s_pkt and s_pkt.is_valid() then -- get as RPLC packet if s_pkt.protocol() == PROTOCOL.RPLC then local rplc_pkt = comms.rplc_packet() diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index a6a47a6..284008f 100644 --- a/reactor-plc/startup.lua +++ b/reactor-plc/startup.lua @@ -8,6 +8,7 @@ local comms = require("scada-common.comms") local crash = require("scada-common.crash") local log = require("scada-common.log") local mqueue = require("scada-common.mqueue") +local network = require("scada-common.network") local ppm = require("scada-common.ppm") local rsio = require("scada-common.rsio") local util = require("scada-common.util") @@ -18,7 +19,7 @@ local plc = require("reactor-plc.plc") local renderer = require("reactor-plc.renderer") local threads = require("reactor-plc.threads") -local R_PLC_VERSION = "v1.4.7" +local R_PLC_VERSION = "v1.5.0" local println = util.println local println_ts = util.println_ts @@ -88,13 +89,13 @@ local function main() -- PLC system state flags ---@class plc_state plc_state = { - init_ok = true, - fp_ok = false, - shutdown = false, - degraded = false, + init_ok = true, + fp_ok = false, + shutdown = false, + degraded = true, reactor_formed = true, - no_reactor = false, - no_modem = false + no_reactor = true, + no_modem = true }, -- control setpoints @@ -113,6 +114,7 @@ local function main() -- system objects plc_sys = { rps = nil, ---@type rps + nic = nil, ---@type nic plc_comms = nil, ---@type plc_comms conn_watchdog = nil ---@type watchdog }, @@ -130,14 +132,17 @@ local function main() local plc_state = __shared_memory.plc_state + -- initial state evaluation + plc_state.no_reactor = smem_dev.reactor == nil + plc_state.no_modem = smem_dev.modem == nil + -- we need a reactor, can at least do some things even if it isn't formed though - if smem_dev.reactor == nil then + if plc_state.no_reactor then println("init> fission reactor not found"); log.warning("init> no reactor on startup") plc_state.init_ok = false plc_state.degraded = true - plc_state.no_reactor = true elseif not smem_dev.reactor.isFormed() then println("init> fission reactor not formed"); log.warning("init> reactor logic adapter present, but reactor is not formed") @@ -147,7 +152,7 @@ local function main() end -- modem is required if networked - if __shared_memory.networked and smem_dev.modem == nil then + if __shared_memory.networked and plc_state.no_modem then println("init> wireless modem not found") log.warning("init> no wireless modem on startup") @@ -158,7 +163,6 @@ local function main() plc_state.init_ok = false plc_state.degraded = true - plc_state.no_modem = true end -- print a log message to the terminal as long as the UI isn't running @@ -196,8 +200,9 @@ local function main() smem_sys.conn_watchdog = util.new_watchdog(config.COMMS_TIMEOUT) log.debug("init> conn watchdog started") - -- start comms - smem_sys.plc_comms = plc.comms(config.REACTOR_ID, R_PLC_VERSION, smem_dev.modem, config.PLC_CHANNEL, config.SVR_CHANNEL, + -- init network interface then start comms + smem_sys.nic = network.nic(smem_dev.modem) + smem_sys.plc_comms = plc.comms(config.REACTOR_ID, R_PLC_VERSION, smem_sys.nic, config.PLC_CHANNEL, config.SVR_CHANNEL, config.TRUSTED_RANGE, smem_dev.reactor, smem_sys.rps, smem_sys.conn_watchdog) log.debug("init> comms init") else diff --git a/reactor-plc/threads.lua b/reactor-plc/threads.lua index b9c986d..17f6661 100644 --- a/reactor-plc/threads.lua +++ b/reactor-plc/threads.lua @@ -59,6 +59,7 @@ function threads.thread__main(smem, init) while true do -- get plc_sys fields (may have been set late due to degraded boot) local rps = smem.plc_sys.rps + local nic = smem.plc_sys.nic local plc_comms = smem.plc_sys.plc_comms local conn_watchdog = smem.plc_sys.conn_watchdog @@ -66,6 +67,7 @@ function threads.thread__main(smem, init) -- handle event if event == "timer" and loop_clock.is_clock(param1) then + -- note: loop clock is only running if init_ok = true -- blink heartbeat indicator databus.heartbeat() @@ -75,7 +77,7 @@ function threads.thread__main(smem, init) loop_clock.start() -- send updated data - if not plc_state.no_modem then + if not nic.connected() then if plc_comms.is_linked() then smem.q.mq_comms_tx.push_command(MQ__COMM_CMD.SEND_STATUS) else @@ -114,7 +116,7 @@ function threads.thread__main(smem, init) smem.q.mq_rps.push_command(MQ__RPS_CMD.SCRAM) -- determine if we are still in a degraded state - if not networked or not plc_state.no_modem then + if (not networked) or nic.connected() then plc_state.degraded = false end @@ -144,7 +146,7 @@ function threads.thread__main(smem, init) -- update indicators databus.tx_hw_status(plc_state) - elseif event == "modem_message" and networked and plc_state.init_ok and not plc_state.no_modem then + elseif event == "modem_message" and networked and plc_state.init_ok and nic.connected() then -- got a packet local packet = plc_comms.parse_packet(param1, param2, param3, param4, param5) if packet ~= nil then @@ -171,7 +173,9 @@ function threads.thread__main(smem, init) plc_state.degraded = true elseif networked and type == "modem" then -- we only care if this is our wireless modem - if device == plc_dev.modem then + if nic.is_modem(device) then + nic.disconnect() + println_ts("comms modem disconnected!") log.error("comms modem disconnected") @@ -199,12 +203,11 @@ function threads.thread__main(smem, init) if type == "fissionReactorLogicAdapter" then -- reconnected reactor plc_dev.reactor = device + plc_state.no_reactor = false println_ts("reactor reconnected.") log.info("reactor reconnected") - plc_state.no_reactor = false - -- we need to assume formed here as we cannot check in this main loop -- RPS will identify if it isn't and this will get set false later plc_state.reactor_formed = true @@ -230,14 +233,12 @@ function threads.thread__main(smem, init) if device.isWireless() then -- reconnected modem plc_dev.modem = device + plc_state.no_modem = false - if plc_state.init_ok then - plc_comms.reconnect_modem(plc_dev.modem) - end + if plc_state.init_ok then nic.connect(device) end println_ts("wireless modem reconnected.") log.info("comms modem reconnected") - plc_state.no_modem = false -- determine if we are still in a degraded state if not plc_state.no_reactor then @@ -709,9 +710,7 @@ function threads.thread__setpoint_control(smem) end -- if ramping completed or was aborted, reset last burn setpoint so that if it is requested again it will be re-attempted - if not setpoints.burn_rate_en then - last_burn_sp = 0 - end + if not setpoints.burn_rate_en then last_burn_sp = 0 end end -- check for termination request