From 46b23414b0d7a7edb0def7f0c9426a1e29ad8920 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 8 Nov 2025 18:22:27 -0500 Subject: [PATCH] #642 RTU gateway connection test --- rtu/config/check.lua | 122 ++++++++++++++++++++++++++++---------- rtu/configure.lua | 2 + supervisor/supervisor.lua | 24 +++++--- 3 files changed, 108 insertions(+), 40 deletions(-) diff --git a/rtu/config/check.lua b/rtu/config/check.lua index 2956560..59d2930 100644 --- a/rtu/config/check.lua +++ b/rtu/config/check.lua @@ -27,13 +27,17 @@ local ESTABLISH_ACK = comms.ESTABLISH_ACK local MGMT_TYPE = comms.MGMT_TYPE local self = { + checking_wl = true, + wd_modem = nil, ---@type Modem|nil + wl_modem = nil, ---@type Modem|nil + nic = nil, ---@type nic net_listen = false, - sv_addr = comms.BROADCAST, - sv_seq_num = util.time_ms() * 10, self_check_pass = true, + self_check_wireless = true, + settings = nil, ---@type rtu_config run_test_btn = nil, ---@type PushButton @@ -59,10 +63,9 @@ local function send_sv(msg_type, msg) local pkt = comms.mgmt_packet() pkt.make(msg_type, msg) - s_pkt.make(self.sv_addr, self.sv_seq_num, PROTOCOL.SCADA_MGMT, pkt.raw_sendable()) + s_pkt.make(comms.BROADCAST, util.time_ms() * 10, PROTOCOL.SCADA_MGMT, pkt.raw_sendable()) self.nic.transmit(self.settings.SVR_Channel, self.settings.RTU_Channel, s_pkt) - self.sv_seq_num = self.sv_seq_num + 1 end -- handle an establish message from the supervisor @@ -78,10 +81,7 @@ local function handle_packet(packet) local est_ack = packet.data[1] if est_ack== ESTABLISH_ACK.ALLOW then - self.self_check_msg(nil, true, "") - self.sv_addr = packet.scada_frame.src_addr() - send_sv(MGMT_TYPE.CLOSE, {}) - if self.self_check_pass then check_complete() end + -- OK elseif est_ack == ESTABLISH_ACK.DENY then error_msg = "error: supervisor connection denied" elseif est_ack == ESTABLISH_ACK.BAD_VERSION then @@ -98,18 +98,20 @@ local function handle_packet(packet) end self.net_listen = false - self.run_test_btn.enable() if error_msg then self.self_check_msg(nil, false, error_msg) + else + self.self_check_msg(nil, true, "") end + + util.push_event("conn_test_complete", error_msg == nil) end -- handle supervisor connection failure local function handle_timeout() self.net_listen = false - self.run_test_btn.enable() - self.self_check_msg(nil, false, "make sure your supervisor is running, your channels are correct, trusted ranges are set properly (if enabled), facility keys match (if set), and if you are using wireless modems rather than ender modems, that your devices are close together in the same dimension") + util.push_event("conn_test_complete", false) end @@ -129,10 +131,18 @@ local function self_check() self.self_check_pass = true local cfg = self.settings - local modem = ppm.get_wireless_modem() + self.wd_modem = ppm.get_modem(cfg.WiredModem) + self.wl_modem = ppm.get_wireless_modem() local valid_cfg = rtu.validate_config(cfg) - self.self_check_msg("> check wireless/ender modem connected...", modem ~= nil, "you must connect an ender or wireless modem to the RTU gateway") + if cfg.WiredModem then + self.self_check_msg("> check wired comms modem connected...", self.wd_modem, "please connect the wired comms modem " .. cfg.WiredModem) + end + + if cfg.WirelessModem then + self.self_check_msg("> check wireless/ender modem connected...", self.wl_modem, "please connect an ender or wireless modem for wireless comms") + end + self.self_check_msg("> check gateway configuration...", valid_cfg, "go through Configure Gateway and apply settings to set any missing settings and repair any corrupted ones") -- check redstone configurations @@ -211,27 +221,37 @@ local function self_check() end end - if valid_cfg and modem then - self.self_check_msg("> check supervisor connection...") + if valid_cfg then + self.checking_wl = true - -- init mac as needed - if cfg.AuthKey and string.len(cfg.AuthKey) >= 8 then - network.init_mac(cfg.AuthKey) + if cfg.WirelessModem and self.wl_modem then + self.self_check_msg("> check wireless supervisor connection...") + + -- init mac as needed + if cfg.AuthKey and string.len(cfg.AuthKey) >= 8 then + network.init_mac(cfg.AuthKey) + else + network.deinit_mac() + end + + comms.set_trusted_range(cfg.TrustedRange) + + self.nic = network.nic(self.wl_modem) + + self.nic.closeAll() + self.nic.open(cfg.RTU_Channel) + + self.net_listen = true + + send_sv(MGMT_TYPE.ESTABLISH, { comms.version, comms.CONN_TEST_FWV, DEVICE_TYPE.RTU, {} }) + + tcd.dispatch_unique(8, handle_timeout) + elseif cfg.WiredModem and self.wd_modem then + -- skip to wired + util.push_event("conn_test_complete", true) else - network.deinit_mac() + self.self_check_msg("> no modem, can't test supervisor connection", false) end - - self.nic = network.nic(modem) - - self.nic.closeAll() - self.nic.open(cfg.RTU_Channel) - - self.sv_addr = comms.BROADCAST - self.net_listen = true - - send_sv(MGMT_TYPE.ESTABLISH, { comms.version, "0.0.0", DEVICE_TYPE.RTU, {} }) - - tcd.dispatch_unique(8, handle_timeout) else if self.self_check_pass then check_complete() end self.run_test_btn.enable() @@ -315,4 +335,44 @@ function check.receive_sv(side, sender, reply_to, message, distance) end end +-- handle completed connection tests +---@param pass boolean +function check.conn_test_callback(pass) + local cfg = self.settings + + if self.checking_wl then + if not pass then + self.self_check_msg(nil, false, "make sure your supervisor is running, listening on the wireless interface, your channels are correct, trusted ranges are set properly (if enabled), facility keys match (if set), and if you are using wireless modems rather than ender modems, that your devices are close together in the same dimension") + end + + if cfg.WiredModem and self.wd_modem then + self.checking_wl = false + self.self_check_msg("> check wired supervisor connection...") + + comms.set_trusted_range(0) + + self.nic = network.nic(self.wd_modem) + + self.nic.closeAll() + self.nic.open(cfg.RTU_Channel) + + self.net_listen = true + + send_sv(MGMT_TYPE.ESTABLISH, { comms.version, comms.CONN_TEST_FWV, DEVICE_TYPE.RTU, {} }) + + tcd.dispatch_unique(8, handle_timeout) + else + if self.self_check_pass then check_complete() end + self.run_test_btn.enable() + end + else + if not pass then + self.self_check_msg(nil, false, "make sure your supervisor is running, listening on the wired interface, the wire is intact, and your channels are correct") + end + + if self.self_check_pass then check_complete() end + self.run_test_btn.enable() + end +end + return check diff --git a/rtu/configure.lua b/rtu/configure.lua index 6b119af..8a43fef 100644 --- a/rtu/configure.lua +++ b/rtu/configure.lua @@ -359,6 +359,8 @@ function configurator.configure(ask_config) display.handle_paste(param1) elseif event == "modem_message" then check.receive_sv(param1, param2, param3, param4, param5) + elseif event == "conn_test_complete" then + check.conn_test_callback(param1) elseif event == "peripheral_detach" then ---@diagnostic disable-next-line: discard-returns ppm.handle_unmount(param1) diff --git a/supervisor/supervisor.lua b/supervisor/supervisor.lua index b1b0447..9250e60 100644 --- a/supervisor/supervisor.lua +++ b/supervisor/supervisor.lua @@ -282,25 +282,31 @@ function supervisor.comms(_version, fp_ok, facility) -- drop if not listening elseif comms_v ~= comms.version then if last_ack ~= ESTABLISH_ACK.BAD_VERSION then - log.info(util.c("dropping RTU_GW establish packet with incorrect comms version v", comms_v, " (expected v", comms.version, ")")) + log.info(util.c("RTU_GW_ESTABLISH: [@", src_addr, "] dropping RTU_GW establish packet with incorrect comms version v", comms_v, " (expected v", comms.version, ")")) end _send_establish(nic, packet.scada_frame, ESTABLISH_ACK.BAD_VERSION) elseif dev_type == DEVICE_TYPE.RTU then if packet.length == 4 then - -- this is an RTU advertisement for a new session - local rtu_advert = packet.data[4] - local s_id = svsessions.establish_rtu_session(nic, src_addr, i_seq_num, rtu_advert, firmware_v) + if firmware_v ~= comms.CONN_TEST_FWV then + -- this is an RTU advertisement for a new session + local rtu_advert = packet.data[4] + local s_id = svsessions.establish_rtu_session(nic, src_addr, i_seq_num, rtu_advert, firmware_v) - println(util.c("RTU (", firmware_v, ") [@", src_addr, "] \xbb connected")) - log.info(util.c("RTU_GW_ESTABLISH: RTU_GW (",firmware_v, ") [@", src_addr, "] connected with session ID ", s_id, " on ", nic.phy_name())) - _send_establish(nic, packet.scada_frame, ESTABLISH_ACK.ALLOW) + println(util.c("RTU (", firmware_v, ") [@", src_addr, "] \xbb connected")) + log.info(util.c("RTU_GW_ESTABLISH: [@", src_addr, "] RTU_GW (",firmware_v, ") connected with session ID ", s_id, " on ", nic.phy_name())) + _send_establish(nic, packet.scada_frame, ESTABLISH_ACK.ALLOW) + else + -- valid, but this was just a test + log.info(util.c("RTU_GW_ESTABLISH: RTU_GW [@", src_addr, "] sending connection test success response on ", nic.phy_name())) + _send_establish(nic, packet.scada_frame, ESTABLISH_ACK.ALLOW) + end else - log.debug("RTU_GW_ESTABLISH: packet length mismatch") + log.debug(util.c("RTU_GW_ESTABLISH: [@", src_addr, "] packet length mismatch")) _send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY) end else - log.debug(util.c("illegal establish packet for device ", dev_type, " on RTU channel")) + log.debug(util.c("RTU_GW_ESTABLISH: [@", src_addr, "] illegal establish packet for device ", dev_type, " on RTU channel")) _send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY) end end