#51 nic integration with rtu and supervisor

This commit is contained in:
Mikayla Fischler 2023-06-25 12:59:38 -04:00
parent 9073009eb0
commit 336662de62
9 changed files with 52 additions and 82 deletions

View File

@ -148,7 +148,7 @@ local function main()
conn_watchdog.cancel() conn_watchdog.cancel()
log.debug("startup> conn watchdog created") log.debug("startup> conn watchdog created")
-- init network interface then start comms -- create network interface then setup comms
local nic = network.nic(modem) local nic = network.nic(modem)
local coord_comms = coordinator.comms(COORDINATOR_VERSION, nic, config.CRD_CHANNEL, config.SVR_CHANNEL, local coord_comms = coordinator.comms(COORDINATOR_VERSION, nic, config.CRD_CHANNEL, config.SVR_CHANNEL,
config.PKT_CHANNEL, config.TRUSTED_RANGE, conn_watchdog) config.PKT_CHANNEL, config.TRUSTED_RANGE, conn_watchdog)

View File

@ -89,7 +89,7 @@ local function main()
log.debug("startup> conn watchdogs created") log.debug("startup> conn watchdogs created")
-- init network interface then start comms -- create network interface then setup comms
local nic = network.nic(modem) local nic = network.nic(modem)
local pocket_comms = pocket.comms(POCKET_VERSION, nic, config.PKT_CHANNEL, config.SVR_CHANNEL, local pocket_comms = pocket.comms(POCKET_VERSION, nic, config.PKT_CHANNEL, config.SVR_CHANNEL,
config.CRD_CHANNEL, config.TRUSTED_RANGE, conn_wd.sv, conn_wd.api) config.CRD_CHANNEL, config.TRUSTED_RANGE, conn_wd.sv, conn_wd.api)

View File

@ -200,7 +200,7 @@ local function main()
smem_sys.conn_watchdog = util.new_watchdog(config.COMMS_TIMEOUT) smem_sys.conn_watchdog = util.new_watchdog(config.COMMS_TIMEOUT)
log.debug("init> conn watchdog started") log.debug("init> conn watchdog started")
-- init network interface then start comms -- create network interface then setup comms
smem_sys.nic = network.nic(smem_dev.modem) 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, 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) config.TRUSTED_RANGE, smem_dev.reactor, smem_sys.rps, smem_sys.conn_watchdog)

View File

@ -158,12 +158,12 @@ end
-- RTU Communications -- RTU Communications
---@nodiscard ---@nodiscard
---@param version string RTU version ---@param version string RTU version
---@param modem table modem device ---@param nic nic network interface device
---@param rtu_channel integer PLC comms channel ---@param rtu_channel integer PLC comms channel
---@param svr_channel integer supervisor server channel ---@param svr_channel integer supervisor server channel
---@param range integer trusted device connection range ---@param range integer trusted device connection range
---@param conn_watchdog watchdog watchdog reference ---@param conn_watchdog watchdog watchdog reference
function rtu.comms(version, modem, rtu_channel, svr_channel, range, conn_watchdog) function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
local self = { local self = {
sv_addr = comms.BROADCAST, sv_addr = comms.BROADCAST,
seq_num = 0, seq_num = 0,
@ -179,12 +179,8 @@ function rtu.comms(version, modem, rtu_channel, svr_channel, range, conn_watchdo
-- PRIVATE FUNCTIONS -- -- PRIVATE FUNCTIONS --
-- configure modem channels -- configure modem channels
local function _conf_channels() nic.closeAll()
modem.closeAll() nic.open(rtu_channel)
modem.open(rtu_channel)
end
_conf_channels()
-- send a scada management packet -- send a scada management packet
---@param msg_type SCADA_MGMT_TYPE ---@param msg_type SCADA_MGMT_TYPE
@ -196,7 +192,7 @@ function rtu.comms(version, modem, rtu_channel, svr_channel, range, conn_watchdo
m_pkt.make(msg_type, msg) m_pkt.make(msg_type, msg)
s_pkt.make(self.sv_addr, self.seq_num, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable()) s_pkt.make(self.sv_addr, self.seq_num, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
modem.transmit(svr_channel, rtu_channel, s_pkt.raw_sendable()) nic.transmit(svr_channel, rtu_channel, s_pkt)
self.seq_num = self.seq_num + 1 self.seq_num = self.seq_num + 1
end end
@ -240,17 +236,10 @@ function rtu.comms(version, modem, rtu_channel, svr_channel, range, conn_watchdo
function public.send_modbus(m_pkt) function public.send_modbus(m_pkt)
local s_pkt = comms.scada_packet() local s_pkt = comms.scada_packet()
s_pkt.make(self.sv_addr, self.seq_num, PROTOCOL.MODBUS_TCP, m_pkt.raw_sendable()) s_pkt.make(self.sv_addr, self.seq_num, PROTOCOL.MODBUS_TCP, m_pkt.raw_sendable())
modem.transmit(svr_channel, rtu_channel, s_pkt.raw_sendable()) nic.transmit(svr_channel, rtu_channel, s_pkt)
self.seq_num = self.seq_num + 1 self.seq_num = self.seq_num + 1
end end
-- reconnect a newly connected modem
---@param new_modem table
function public.reconnect_modem(new_modem)
modem = new_modem
_conf_channels()
end
-- unlink from the server -- unlink from the server
---@param rtu_state rtu_state ---@param rtu_state rtu_state
function public.unlink(rtu_state) function public.unlink(rtu_state)
@ -295,13 +284,10 @@ function rtu.comms(version, modem, rtu_channel, svr_channel, range, conn_watchdo
---@param distance integer ---@param distance integer
---@return modbus_frame|mgmt_frame|nil packet ---@return modbus_frame|mgmt_frame|nil packet
function public.parse_packet(side, sender, reply_to, message, distance) function public.parse_packet(side, sender, reply_to, message, distance)
local s_pkt = nic.receive(side, sender, reply_to, message, distance)
local pkt = nil local pkt = nil
local s_pkt = comms.scada_packet()
-- parse packet as generic SCADA packet if s_pkt then
s_pkt.receive(side, sender, reply_to, message, distance)
if s_pkt.is_valid() then
-- get as MODBUS TCP packet -- get as MODBUS TCP packet
if s_pkt.protocol() == PROTOCOL.MODBUS_TCP then if s_pkt.protocol() == PROTOCOL.MODBUS_TCP then
local m_pkt = comms.modbus_packet() local m_pkt = comms.modbus_packet()

View File

@ -8,6 +8,7 @@ local comms = require("scada-common.comms")
local crash = require("scada-common.crash") local crash = require("scada-common.crash")
local log = require("scada-common.log") local log = require("scada-common.log")
local mqueue = require("scada-common.mqueue") local mqueue = require("scada-common.mqueue")
local network = require("scada-common.network")
local ppm = require("scada-common.ppm") local ppm = require("scada-common.ppm")
local rsio = require("scada-common.rsio") local rsio = require("scada-common.rsio")
local types = require("scada-common.types") local types = require("scada-common.types")
@ -28,7 +29,7 @@ local sna_rtu = require("rtu.dev.sna_rtu")
local sps_rtu = require("rtu.dev.sps_rtu") local sps_rtu = require("rtu.dev.sps_rtu")
local turbinev_rtu = require("rtu.dev.turbinev_rtu") local turbinev_rtu = require("rtu.dev.turbinev_rtu")
local RTU_VERSION = "v1.3.7" local RTU_VERSION = "v1.4.0"
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE
@ -81,6 +82,14 @@ local function main()
-- mount connected devices -- mount connected devices
ppm.mount_all() ppm.mount_all()
-- get modem
local modem = ppm.get_wireless_modem()
if modem == nil then
println("boot> wireless modem not found")
log.fatal("no wireless modem on startup")
return
end
---@class rtu_shared_memory ---@class rtu_shared_memory
local __shared_memory = { local __shared_memory = {
-- RTU system state flags -- RTU system state flags
@ -91,16 +100,12 @@ local function main()
shutdown = false shutdown = false
}, },
-- core RTU devices
rtu_dev = {
modem = ppm.get_wireless_modem()
},
-- system objects -- system objects
rtu_sys = { rtu_sys = {
nic = network.nic(modem),
rtu_comms = nil, ---@type rtu_comms rtu_comms = nil, ---@type rtu_comms
conn_watchdog = nil, ---@type watchdog conn_watchdog = nil, ---@type watchdog
units = {} ---@type table units = {}
}, },
-- message queues -- message queues
@ -109,16 +114,8 @@ local function main()
} }
} }
local smem_dev = __shared_memory.rtu_dev
local smem_sys = __shared_memory.rtu_sys local smem_sys = __shared_memory.rtu_sys
-- get modem
if smem_dev.modem == nil then
println("boot> wireless modem not found")
log.fatal("no wireless modem on startup")
return
end
databus.tx_hw_modem(true) databus.tx_hw_modem(true)
---------------------------------------- ----------------------------------------
@ -471,7 +468,7 @@ local function main()
log.debug("startup> conn watchdog started") log.debug("startup> conn watchdog started")
-- setup comms -- setup comms
smem_sys.rtu_comms = rtu.comms(RTU_VERSION, smem_dev.modem, config.RTU_CHANNEL, config.SVR_CHANNEL, smem_sys.rtu_comms = rtu.comms(RTU_VERSION, smem_sys.nic, config.RTU_CHANNEL, config.SVR_CHANNEL,
config.TRUSTED_RANGE, smem_sys.conn_watchdog) config.TRUSTED_RANGE, smem_sys.conn_watchdog)
log.debug("startup> comms init") log.debug("startup> comms init")

View File

@ -46,7 +46,7 @@ function threads.thread__main(smem)
-- load in from shared memory -- load in from shared memory
local rtu_state = smem.rtu_state local rtu_state = smem.rtu_state
local rtu_dev = smem.rtu_dev local nic = smem.rtu_sys.nic
local rtu_comms = smem.rtu_sys.rtu_comms local rtu_comms = smem.rtu_sys.rtu_comms
local conn_watchdog = smem.rtu_sys.conn_watchdog local conn_watchdog = smem.rtu_sys.conn_watchdog
local units = smem.rtu_sys.units local units = smem.rtu_sys.units
@ -93,7 +93,9 @@ function threads.thread__main(smem)
if type ~= nil and device ~= nil then if type ~= nil and device ~= nil then
if type == "modem" then if type == "modem" then
-- we only care if this is our wireless modem -- we only care if this is our wireless modem
if device == rtu_dev.modem then if nic.is_modem(device) then
nic.disconnect()
println_ts("wireless modem disconnected!") println_ts("wireless modem disconnected!")
log.warning("comms modem disconnected!") log.warning("comms modem disconnected!")
@ -127,8 +129,7 @@ function threads.thread__main(smem)
if type == "modem" then if type == "modem" then
if device.isWireless() then if device.isWireless() then
-- reconnected modem -- reconnected modem
rtu_dev.modem = device nic.connect(device)
rtu_comms.reconnect_modem(rtu_dev.modem)
println_ts("wireless modem reconnected.") println_ts("wireless modem reconnected.")
log.info("comms modem reconnected") log.info("comms modem reconnected")

View File

@ -34,7 +34,7 @@ local SESSION_TYPE = {
svsessions.SESSION_TYPE = SESSION_TYPE svsessions.SESSION_TYPE = SESSION_TYPE
local self = { local self = {
modem = nil, ---@type table|nil nic = nil, ---@type nic|nil
fp_ok = false, fp_ok = false,
num_reactors = 0, num_reactors = 0,
facility = nil, ---@type facility|nil facility = nil, ---@type facility|nil
@ -60,7 +60,7 @@ local function _sv_handle_outq(session)
if msg ~= nil then if msg ~= nil then
if msg.qtype == mqueue.TYPE.PACKET then if msg.qtype == mqueue.TYPE.PACKET then
-- handle a packet to be sent -- handle a packet to be sent
self.modem.transmit(session.r_chan, config.SVR_CHANNEL, msg.message.raw_sendable()) self.nic.transmit(session.r_chan, config.SVR_CHANNEL, msg.message)
elseif msg.qtype == mqueue.TYPE.COMMAND then elseif msg.qtype == mqueue.TYPE.COMMAND then
-- handle instruction/notification -- handle instruction/notification
elseif msg.qtype == mqueue.TYPE.DATA then elseif msg.qtype == mqueue.TYPE.DATA then
@ -135,7 +135,7 @@ local function _shutdown(session)
while session.out_queue.ready() do while session.out_queue.ready() do
local msg = session.out_queue.pop() local msg = session.out_queue.pop()
if msg ~= nil and msg.qtype == mqueue.TYPE.PACKET then if msg ~= nil and msg.qtype == mqueue.TYPE.PACKET then
self.modem.transmit(session.r_chan, config.SVR_CHANNEL, msg.message.raw_sendable()) self.nic.transmit(session.r_chan, config.SVR_CHANNEL, msg.message)
end end
end end
@ -195,23 +195,17 @@ end
-- PUBLIC FUNCTIONS -- -- PUBLIC FUNCTIONS --
-- initialize svsessions -- initialize svsessions
---@param modem table modem device ---@param nic nic network interface device
---@param fp_ok boolean front panel active ---@param fp_ok boolean front panel active
---@param num_reactors integer number of reactors ---@param num_reactors integer number of reactors
---@param cooling_conf table cooling configuration definition ---@param cooling_conf table cooling configuration definition
function svsessions.init(modem, fp_ok, num_reactors, cooling_conf) function svsessions.init(nic, fp_ok, num_reactors, cooling_conf)
self.modem = modem self.nic = nic
self.fp_ok = fp_ok self.fp_ok = fp_ok
self.num_reactors = num_reactors self.num_reactors = num_reactors
self.facility = facility.new(num_reactors, cooling_conf) self.facility = facility.new(num_reactors, cooling_conf)
end end
-- re-link the modem
---@param modem table
function svsessions.relink_modem(modem)
self.modem = modem
end
-- find an RTU session by the computer ID -- find an RTU session by the computer ID
---@nodiscard ---@nodiscard
---@param source_addr integer ---@param source_addr integer

View File

@ -7,6 +7,7 @@ require("/initenv").init_env()
local crash = require("scada-common.crash") local crash = require("scada-common.crash")
local comms = require("scada-common.comms") local comms = require("scada-common.comms")
local log = require("scada-common.log") local log = require("scada-common.log")
local network = require("scada-common.network")
local ppm = require("scada-common.ppm") local ppm = require("scada-common.ppm")
local tcd = require("scada-common.tcd") local tcd = require("scada-common.tcd")
local util = require("scada-common.util") local util = require("scada-common.util")
@ -20,7 +21,7 @@ local supervisor = require("supervisor.supervisor")
local svsessions = require("supervisor.session.svsessions") local svsessions = require("supervisor.session.svsessions")
local SUPERVISOR_VERSION = "v0.17.10" local SUPERVISOR_VERSION = "v0.18.0"
local println = util.println local println = util.println
local println_ts = util.println_ts local println_ts = util.println_ts
@ -115,8 +116,9 @@ local function main()
println_ts = function (_) end println_ts = function (_) end
end end
-- start comms -- create network interface then setup comms
local superv_comms = supervisor.comms(SUPERVISOR_VERSION, modem, fp_ok) local nic = network.nic(modem)
local superv_comms = supervisor.comms(SUPERVISOR_VERSION, nic, fp_ok)
-- base loop clock (6.67Hz, 3 ticks) -- base loop clock (6.67Hz, 3 ticks)
local MAIN_CLOCK = 0.15 local MAIN_CLOCK = 0.15
@ -139,9 +141,12 @@ local function main()
if type ~= nil and device ~= nil then if type ~= nil and device ~= nil then
if type == "modem" then if type == "modem" then
-- we only care if this is our wireless modem -- we only care if this is our wireless modem
if device == modem then if nic.is_modem(device) then
nic.disconnect()
println_ts("wireless modem disconnected!") println_ts("wireless modem disconnected!")
log.warning("comms modem disconnected") log.warning("comms modem disconnected")
databus.tx_hw_modem(false) databus.tx_hw_modem(false)
else else
log.warning("non-comms modem disconnected") log.warning("non-comms modem disconnected")
@ -153,10 +158,9 @@ local function main()
if type ~= nil and device ~= nil then if type ~= nil and device ~= nil then
if type == "modem" then if type == "modem" then
if device.isWireless() then if device.isWireless() and not nic.connected() then
-- reconnected modem -- reconnected modem
modem = device nic.connect(device)
superv_comms.reconnect_modem(modem)
println_ts("wireless modem reconnected.") println_ts("wireless modem reconnected.")
log.info("comms modem reconnected") log.info("comms modem reconnected")

View File

@ -16,10 +16,10 @@ local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
-- supervisory controller communications -- supervisory controller communications
---@nodiscard ---@nodiscard
---@param _version string supervisor version ---@param _version string supervisor version
---@param modem table modem device ---@param nic nic network interface device
---@param fp_ok boolean if the front panel UI is running ---@param fp_ok boolean if the front panel UI is running
---@diagnostic disable-next-line: unused-local ---@diagnostic disable-next-line: unused-local
function supervisor.comms(_version, modem, fp_ok) function supervisor.comms(_version, nic, fp_ok)
-- print a log message to the terminal as long as the UI isn't running -- print a log message to the terminal as long as the UI isn't running
local function println(message) if not fp_ok then util.println_ts(message) end end local function println(message) if not fp_ok then util.println_ts(message) end end
@ -43,15 +43,11 @@ function supervisor.comms(_version, modem, fp_ok)
-- PRIVATE FUNCTIONS -- -- PRIVATE FUNCTIONS --
-- configure modem channels -- configure modem channels
local function _conf_channels() nic.closeAll()
modem.closeAll() nic.open(svr_channel)
modem.open(svr_channel)
end
_conf_channels()
-- pass modem, status, and config data to svsessions -- pass modem, status, and config data to svsessions
svsessions.init(modem, fp_ok, num_reactors, cooling_conf) svsessions.init(nic, fp_ok, num_reactors, cooling_conf)
-- send an establish request response -- send an establish request response
---@param packet scada_packet ---@param packet scada_packet
@ -64,7 +60,7 @@ function supervisor.comms(_version, modem, fp_ok)
m_pkt.make(SCADA_MGMT_TYPE.ESTABLISH, { ack, data }) m_pkt.make(SCADA_MGMT_TYPE.ESTABLISH, { ack, data })
s_pkt.make(packet.src_addr(), packet.seq_num() + 1, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable()) s_pkt.make(packet.src_addr(), packet.seq_num() + 1, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
modem.transmit(packet.remote_channel(), svr_channel, s_pkt.raw_sendable()) nic.transmit(packet.remote_channel(), svr_channel, s_pkt)
self.last_est_acks[packet.src_addr()] = ack self.last_est_acks[packet.src_addr()] = ack
end end
@ -73,14 +69,6 @@ function supervisor.comms(_version, modem, fp_ok)
---@class superv_comms ---@class superv_comms
local public = {} local public = {}
-- reconnect a newly connected modem
---@param new_modem table
function public.reconnect_modem(new_modem)
modem = new_modem
svsessions.relink_modem(new_modem)
_conf_channels()
end
-- parse a packet -- parse a packet
---@nodiscard ---@nodiscard
---@param side string ---@param side string