#642 RTU gateway connection test

This commit is contained in:
Mikayla Fischler
2025-11-08 18:22:27 -05:00
parent 3f1cf217ac
commit 46b23414b0
3 changed files with 108 additions and 40 deletions

View File

@@ -27,13 +27,17 @@ local ESTABLISH_ACK = comms.ESTABLISH_ACK
local MGMT_TYPE = comms.MGMT_TYPE local MGMT_TYPE = comms.MGMT_TYPE
local self = { local self = {
checking_wl = true,
wd_modem = nil, ---@type Modem|nil
wl_modem = nil, ---@type Modem|nil
nic = nil, ---@type nic nic = nil, ---@type nic
net_listen = false, net_listen = false,
sv_addr = comms.BROADCAST,
sv_seq_num = util.time_ms() * 10,
self_check_pass = true, self_check_pass = true,
self_check_wireless = true,
settings = nil, ---@type rtu_config settings = nil, ---@type rtu_config
run_test_btn = nil, ---@type PushButton run_test_btn = nil, ---@type PushButton
@@ -59,10 +63,9 @@ local function send_sv(msg_type, msg)
local pkt = comms.mgmt_packet() local pkt = comms.mgmt_packet()
pkt.make(msg_type, msg) 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.nic.transmit(self.settings.SVR_Channel, self.settings.RTU_Channel, s_pkt)
self.sv_seq_num = self.sv_seq_num + 1
end end
-- handle an establish message from the supervisor -- handle an establish message from the supervisor
@@ -78,10 +81,7 @@ local function handle_packet(packet)
local est_ack = packet.data[1] local est_ack = packet.data[1]
if est_ack== ESTABLISH_ACK.ALLOW then if est_ack== ESTABLISH_ACK.ALLOW then
self.self_check_msg(nil, true, "") -- OK
self.sv_addr = packet.scada_frame.src_addr()
send_sv(MGMT_TYPE.CLOSE, {})
if self.self_check_pass then check_complete() end
elseif est_ack == ESTABLISH_ACK.DENY then elseif est_ack == ESTABLISH_ACK.DENY then
error_msg = "error: supervisor connection denied" error_msg = "error: supervisor connection denied"
elseif est_ack == ESTABLISH_ACK.BAD_VERSION then elseif est_ack == ESTABLISH_ACK.BAD_VERSION then
@@ -98,18 +98,20 @@ local function handle_packet(packet)
end end
self.net_listen = false self.net_listen = false
self.run_test_btn.enable()
if error_msg then if error_msg then
self.self_check_msg(nil, false, error_msg) self.self_check_msg(nil, false, error_msg)
else
self.self_check_msg(nil, true, "")
end end
util.push_event("conn_test_complete", error_msg == nil)
end end
-- handle supervisor connection failure -- handle supervisor connection failure
local function handle_timeout() local function handle_timeout()
self.net_listen = false self.net_listen = false
self.run_test_btn.enable() util.push_event("conn_test_complete", false)
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")
end end
@@ -129,10 +131,18 @@ local function self_check()
self.self_check_pass = true self.self_check_pass = true
local cfg = self.settings 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) 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") 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 -- check redstone configurations
@@ -211,27 +221,37 @@ local function self_check()
end end
end end
if valid_cfg and modem then if valid_cfg then
self.self_check_msg("> check supervisor connection...") self.checking_wl = true
-- init mac as needed if cfg.WirelessModem and self.wl_modem then
if cfg.AuthKey and string.len(cfg.AuthKey) >= 8 then self.self_check_msg("> check wireless supervisor connection...")
network.init_mac(cfg.AuthKey)
-- 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 else
network.deinit_mac() self.self_check_msg("> no modem, can't test supervisor connection", false)
end 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 else
if self.self_check_pass then check_complete() end if self.self_check_pass then check_complete() end
self.run_test_btn.enable() self.run_test_btn.enable()
@@ -315,4 +335,44 @@ function check.receive_sv(side, sender, reply_to, message, distance)
end end
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 return check

View File

@@ -359,6 +359,8 @@ function configurator.configure(ask_config)
display.handle_paste(param1) display.handle_paste(param1)
elseif event == "modem_message" then elseif event == "modem_message" then
check.receive_sv(param1, param2, param3, param4, param5) check.receive_sv(param1, param2, param3, param4, param5)
elseif event == "conn_test_complete" then
check.conn_test_callback(param1)
elseif event == "peripheral_detach" then elseif event == "peripheral_detach" then
---@diagnostic disable-next-line: discard-returns ---@diagnostic disable-next-line: discard-returns
ppm.handle_unmount(param1) ppm.handle_unmount(param1)

View File

@@ -282,25 +282,31 @@ function supervisor.comms(_version, fp_ok, facility)
-- drop if not listening -- drop if not listening
elseif comms_v ~= comms.version then elseif comms_v ~= comms.version then
if last_ack ~= ESTABLISH_ACK.BAD_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 end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.BAD_VERSION) _send_establish(nic, packet.scada_frame, ESTABLISH_ACK.BAD_VERSION)
elseif dev_type == DEVICE_TYPE.RTU then elseif dev_type == DEVICE_TYPE.RTU then
if packet.length == 4 then if packet.length == 4 then
-- this is an RTU advertisement for a new session if firmware_v ~= comms.CONN_TEST_FWV then
local rtu_advert = packet.data[4] -- this is an RTU advertisement for a new session
local s_id = svsessions.establish_rtu_session(nic, src_addr, i_seq_num, rtu_advert, firmware_v) 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")) 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())) 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) _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 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) _send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end end
else 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) _send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end end
end end