#580 supervisor backplane
This commit is contained in:
parent
9e3922a972
commit
4d6c388f37
@ -104,6 +104,8 @@ function network.nic(modem)
|
|||||||
modem = reconnected_modem
|
modem = reconnected_modem
|
||||||
self.connected = true
|
self.connected = true
|
||||||
|
|
||||||
|
modem.closeAll()
|
||||||
|
|
||||||
-- open previously opened channels
|
-- open previously opened channels
|
||||||
for _, channel in ipairs(self.channels) do
|
for _, channel in ipairs(self.channels) do
|
||||||
modem.open(channel)
|
modem.open(channel)
|
||||||
|
|||||||
@ -24,7 +24,7 @@ local t_pack = table.pack
|
|||||||
local util = {}
|
local util = {}
|
||||||
|
|
||||||
-- scada-common version
|
-- scada-common version
|
||||||
util.version = "1.5.4"
|
util.version = "1.5.5"
|
||||||
|
|
||||||
util.TICK_TIME_S = 0.05
|
util.TICK_TIME_S = 0.05
|
||||||
util.TICK_TIME_MS = 50
|
util.TICK_TIME_MS = 50
|
||||||
|
|||||||
183
supervisor/backplane.lua
Normal file
183
supervisor/backplane.lua
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
--
|
||||||
|
-- Supervisor System Core Peripheral Backplane
|
||||||
|
--
|
||||||
|
|
||||||
|
local log = require("scada-common.log")
|
||||||
|
local network = require("scada-common.network")
|
||||||
|
local ppm = require("scada-common.ppm")
|
||||||
|
local util = require("scada-common.util")
|
||||||
|
|
||||||
|
local databus = require("supervisor.databus")
|
||||||
|
|
||||||
|
---@class supervisor_backplane
|
||||||
|
local backplane = {}
|
||||||
|
|
||||||
|
local _bp = {
|
||||||
|
config = nil, ---@type svr_config
|
||||||
|
lan_iface = false, ---@type string|false wired comms modem name
|
||||||
|
|
||||||
|
wd_nic = nil, ---@type nic|nil wired nic
|
||||||
|
wl_nic = nil, ---@type nic|nil wireless nic
|
||||||
|
nic_map = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
backplane.nics = _bp.nic_map
|
||||||
|
|
||||||
|
-- initialize the system peripheral backplane
|
||||||
|
---@param config svr_config
|
||||||
|
---@param println function
|
||||||
|
---@return boolean success
|
||||||
|
function backplane.init(config, println)
|
||||||
|
-- setup the wired modem, if configured
|
||||||
|
if type(config.WiredModem) == "string" then
|
||||||
|
_bp.lan_iface = config.WiredModem
|
||||||
|
|
||||||
|
local modem = ppm.get_modem(_bp.lan_iface)
|
||||||
|
if not (modem and _bp.lan_iface) then
|
||||||
|
println("startup> wired comms modem not found")
|
||||||
|
log.fatal("no wired comms modem on startup")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local nic = network.nic(modem)
|
||||||
|
_bp.wd_nic = nic
|
||||||
|
_bp.nic_map[_bp.lan_iface] = nic
|
||||||
|
|
||||||
|
nic.closeAll()
|
||||||
|
|
||||||
|
if config.PLC_Listen > 0 then nic.open(config.PLC_Channel) end
|
||||||
|
if config.RTU_Listen > 0 then nic.open(config.RTU_Channel) end
|
||||||
|
if config.CRD_Listen > 0 then nic.open(config.CRD_Channel) end
|
||||||
|
|
||||||
|
databus.tx_hw_wd_modem(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- setup the wireless modem, if configured
|
||||||
|
if config.WirelessModem then
|
||||||
|
local modem, iface = ppm.get_wireless_modem()
|
||||||
|
if not (modem and iface) then
|
||||||
|
println("startup> wireless comms modem not found")
|
||||||
|
log.fatal("no wireless comms modem on startup")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local nic = network.nic(modem)
|
||||||
|
_bp.wl_nic = nic
|
||||||
|
_bp.nic_map[iface] = nic
|
||||||
|
|
||||||
|
nic.closeAll()
|
||||||
|
|
||||||
|
if config.PLC_Listen % 2 == 0 then nic.open(config.PLC_Channel) end
|
||||||
|
if config.RTU_Listen % 2 == 0 then nic.open(config.RTU_Channel) end
|
||||||
|
if config.CRD_Listen % 2 == 0 then nic.open(config.CRD_Channel) end
|
||||||
|
if config.PocketEnabled then nic.open(config.PKT_Channel) end
|
||||||
|
|
||||||
|
databus.tx_hw_wl_modem(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not ((type(config.WiredModem) == "string" or config.WirelessModem)) then
|
||||||
|
println("startup> no modems configured")
|
||||||
|
log.fatal("no modems configured")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- handle a backplane peripheral attach
|
||||||
|
---@param iface string
|
||||||
|
---@param type string
|
||||||
|
---@param device table
|
||||||
|
---@param println function
|
||||||
|
function backplane.attach(iface, type, device, println)
|
||||||
|
if type == "modem" then
|
||||||
|
---@cast device Modem
|
||||||
|
|
||||||
|
local m_is_wl = device.isWireless()
|
||||||
|
|
||||||
|
log.info(util.c("BKPLN: ", util.trinary(m_is_wl, "WIRELESS", "WIRED"), " PHY_ATTACH ", iface))
|
||||||
|
|
||||||
|
local is_wd = _bp.wd_nic and (_bp.lan_iface == iface)
|
||||||
|
local is_wl = _bp.wl_nic and (not _bp.wl_nic.is_connected()) and m_is_wl
|
||||||
|
|
||||||
|
if is_wd then
|
||||||
|
-- connect this as the wired NIC
|
||||||
|
_bp.wd_nic.connect(device)
|
||||||
|
|
||||||
|
log.info("BKPLN: WIRED PHY_UP " .. iface)
|
||||||
|
println("wired comms modem reconnected")
|
||||||
|
|
||||||
|
databus.tx_hw_wd_modem(true)
|
||||||
|
elseif is_wl then
|
||||||
|
-- connect this as the wireless NIC
|
||||||
|
_bp.wl_nic.connect(device)
|
||||||
|
_bp.nic_map[iface] = _bp.wl_nic
|
||||||
|
|
||||||
|
log.info("BKPLN: WIRELESS PHY_UP " .. iface)
|
||||||
|
println("wireless comms modem reconnected")
|
||||||
|
|
||||||
|
databus.tx_hw_wl_modem(true)
|
||||||
|
elseif _bp.wl_nic and m_is_wl then
|
||||||
|
-- the wireless NIC already has a modem
|
||||||
|
println("standby wireless modem connected")
|
||||||
|
log.info("BKPLN: standby wireless modem connected")
|
||||||
|
else
|
||||||
|
println("unassigned modem connected")
|
||||||
|
log.warning("BKPLN: unassigned modem connected")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- handle a backplane peripheral detach
|
||||||
|
---@param iface string
|
||||||
|
---@param type string
|
||||||
|
---@param device table
|
||||||
|
---@param println function
|
||||||
|
function backplane.detach(iface, type, device, println)
|
||||||
|
if type == "modem" then
|
||||||
|
---@cast device Modem
|
||||||
|
|
||||||
|
local m_is_wl = device.isWireless()
|
||||||
|
local was_wd = _bp.wd_nic and _bp.wd_nic.is_modem(device)
|
||||||
|
local was_wl = _bp.wl_nic and _bp.wl_nic.is_modem(device)
|
||||||
|
|
||||||
|
log.info(util.c("BKPLN: ", util.trinary(m_is_wl, "WIRELESS", "WIRED"), " PHY_DETACH ", iface))
|
||||||
|
|
||||||
|
_bp.nic_map[iface] = nil
|
||||||
|
|
||||||
|
if _bp.wd_nic and was_wd then
|
||||||
|
_bp.wd_nic.disconnect()
|
||||||
|
log.info("BKPLN: WIRED PHY_DOWN " .. iface)
|
||||||
|
|
||||||
|
println("wired modem disconnected")
|
||||||
|
log.warning("BKPLN: wired comms modem disconnected")
|
||||||
|
|
||||||
|
databus.tx_hw_wd_modem(false)
|
||||||
|
elseif _bp.wl_nic and was_wl then
|
||||||
|
_bp.wl_nic.disconnect()
|
||||||
|
log.info("BKPLN: WIRELESS PHY_DOWN " .. iface)
|
||||||
|
|
||||||
|
println("wireless comms modem disconnected")
|
||||||
|
log.warning("BKPLN: wireless comms modem disconnected")
|
||||||
|
|
||||||
|
local modem, m_iface = ppm.get_wireless_modem()
|
||||||
|
if modem then
|
||||||
|
log.info("BKPLN: found another wireless modem, using it for comms")
|
||||||
|
|
||||||
|
_bp.wl_nic.connect(modem)
|
||||||
|
log.info("BKPLN: WIRELESS PHY_UP " .. m_iface)
|
||||||
|
else
|
||||||
|
databus.tx_hw_wl_modem(false)
|
||||||
|
end
|
||||||
|
elseif _bp.wl_nic and m_is_wl then
|
||||||
|
-- wireless, but not active
|
||||||
|
println("standby wireless modem disconnected")
|
||||||
|
log.info("BKPLN: standby wireless modem disconnected")
|
||||||
|
else
|
||||||
|
println("unassigned modem disconnected")
|
||||||
|
log.warning("BKPLN: unassigned modem disconnected")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return backplane
|
||||||
@ -1,177 +0,0 @@
|
|||||||
--
|
|
||||||
-- PCIe - Borrowed the name of that protocol for fun (this manages physical peripherals)
|
|
||||||
--
|
|
||||||
|
|
||||||
local log = require("scada-common.log")
|
|
||||||
local network = require("scada-common.network")
|
|
||||||
local ppm = require("scada-common.ppm")
|
|
||||||
|
|
||||||
local databus = require("supervisor.databus")
|
|
||||||
|
|
||||||
local pcie_bus = {}
|
|
||||||
|
|
||||||
local bus = {
|
|
||||||
wired_modem = false, ---@type string|false wired comms modem name
|
|
||||||
wl_nic = nil, ---@type nic|nil wireless nic
|
|
||||||
wd_nic = nil ---@type nic|nil wired nic
|
|
||||||
}
|
|
||||||
|
|
||||||
-- network cards
|
|
||||||
---@class _svr_pcie_nic
|
|
||||||
---@field wl nic|nil the wireless comms NIC
|
|
||||||
---@field wd nic|nil the wired comms NIC
|
|
||||||
pcie_bus.nic = {
|
|
||||||
-- close all channels and then open the configured channels on the appropriate nic(s)
|
|
||||||
---@param config svr_config
|
|
||||||
reset_open = function (config)
|
|
||||||
if bus.wl_nic then
|
|
||||||
bus.wl_nic.closeAll()
|
|
||||||
|
|
||||||
if config.PLC_Listen % 2 == 0 then bus.wl_nic.open(config.PLC_Channel) end
|
|
||||||
if config.RTU_Listen % 2 == 0 then bus.wl_nic.open(config.RTU_Channel) end
|
|
||||||
if config.CRD_Listen % 2 == 0 then bus.wl_nic.open(config.CRD_Channel) end
|
|
||||||
if config.PocketEnabled then bus.wl_nic.open(config.PKT_Channel) end
|
|
||||||
end
|
|
||||||
|
|
||||||
if bus.wd_nic then
|
|
||||||
bus.wd_nic.closeAll()
|
|
||||||
|
|
||||||
if config.PLC_Listen > 0 then bus.wd_nic.open(config.PLC_Channel) end
|
|
||||||
if config.RTU_Listen > 0 then bus.wd_nic.open(config.RTU_Channel) end
|
|
||||||
if config.CRD_Listen > 0 then bus.wd_nic.open(config.CRD_Channel) end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
-- get the requested nic by interface
|
|
||||||
---@param iface string
|
|
||||||
---@return nic|nil
|
|
||||||
get = function(iface)
|
|
||||||
local dev = ppm.get_device(iface)
|
|
||||||
|
|
||||||
if dev then
|
|
||||||
if bus.wl_nic and bus.wl_nic.is_modem(dev) then return bus.wl_nic end
|
|
||||||
if bus.wd_nic and bus.wd_nic.is_modem(dev) then return bus.wd_nic end
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end,
|
|
||||||
-- cards by interface
|
|
||||||
---@type { string: nic }
|
|
||||||
cards = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
-- initialize peripherals
|
|
||||||
---@param config svr_config
|
|
||||||
---@param println function
|
|
||||||
---@return boolean success
|
|
||||||
function pcie_bus.init(config, println)
|
|
||||||
-- setup networking peripheral(s)
|
|
||||||
if type(config.WiredModem) == "string" then
|
|
||||||
bus.wired_modem = config.WiredModem
|
|
||||||
|
|
||||||
local wired_modem = ppm.get_modem(bus.wired_modem)
|
|
||||||
|
|
||||||
if not (wired_modem and bus.wired_modem) then
|
|
||||||
println("startup> wired comms modem not found")
|
|
||||||
log.fatal("no wired comms modem on startup")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
bus.wd_nic = network.nic(wired_modem)
|
|
||||||
pcie_bus.nic.cards[bus.wired_modem] = bus.wd_nic
|
|
||||||
end
|
|
||||||
|
|
||||||
if config.WirelessModem then
|
|
||||||
local wireless_modem, wireless_iface = ppm.get_wireless_modem()
|
|
||||||
|
|
||||||
if not (wireless_modem and wireless_iface) then
|
|
||||||
println("startup> wireless comms modem not found")
|
|
||||||
log.fatal("no wireless comms modem on startup")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
bus.wl_nic = network.nic(wireless_modem)
|
|
||||||
pcie_bus.nic.cards[wireless_iface] = bus.wl_nic
|
|
||||||
end
|
|
||||||
|
|
||||||
pcie_bus.nic.wl = bus.wl_nic
|
|
||||||
pcie_bus.nic.wd = bus.wd_nic
|
|
||||||
|
|
||||||
databus.tx_hw_wl_modem(true)
|
|
||||||
databus.tx_hw_wd_modem(config.WirelessModem)
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- handle the connecting of a device
|
|
||||||
---@param iface string
|
|
||||||
---@param type string
|
|
||||||
---@param device table
|
|
||||||
---@param println function
|
|
||||||
function pcie_bus.connect(iface, type, device, println)
|
|
||||||
if type == "modem" then
|
|
||||||
---@cast device Modem
|
|
||||||
if device.isWireless() then
|
|
||||||
if bus.wl_nic and not bus.wl_nic.is_connected() then
|
|
||||||
-- reconnected wireless comms modem
|
|
||||||
bus.wl_nic.connect(device)
|
|
||||||
pcie_bus.nic.cards[iface] = bus.wl_nic
|
|
||||||
|
|
||||||
println("wireless comms modem reconnected")
|
|
||||||
log.info("wireless comms modem reconnected")
|
|
||||||
|
|
||||||
databus.tx_hw_wl_modem(true)
|
|
||||||
else
|
|
||||||
log.info("unused wireless modem reconnected")
|
|
||||||
end
|
|
||||||
elseif bus.wd_nic and (iface == bus.wired_modem) then
|
|
||||||
-- reconnected wired comms modem
|
|
||||||
bus.wd_nic.connect(device)
|
|
||||||
pcie_bus.nic.cards[iface] = bus.wd_nic
|
|
||||||
|
|
||||||
println("wired comms modem reconnected")
|
|
||||||
log.info("wired comms modem reconnected")
|
|
||||||
|
|
||||||
databus.tx_hw_wl_modem(true)
|
|
||||||
else
|
|
||||||
log.info("wired modem reconnected")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- handle the removal of a device
|
|
||||||
---@param iface string
|
|
||||||
---@param type string
|
|
||||||
---@param device table
|
|
||||||
---@param println function
|
|
||||||
function pcie_bus.remove(iface, type, device, println)
|
|
||||||
if type == "modem" then
|
|
||||||
pcie_bus.nic.cards[iface] = nil
|
|
||||||
|
|
||||||
---@cast device Modem
|
|
||||||
if bus.wl_nic and bus.wl_nic.is_modem(device) then
|
|
||||||
bus.wl_nic.disconnect()
|
|
||||||
|
|
||||||
println("wireless comms modem disconnected")
|
|
||||||
log.warning("wireless comms modem disconnected")
|
|
||||||
|
|
||||||
local other_modem = ppm.get_wireless_modem()
|
|
||||||
if other_modem then
|
|
||||||
log.info("found another wireless modem, using it for comms")
|
|
||||||
bus.wl_nic.connect(other_modem)
|
|
||||||
else
|
|
||||||
databus.tx_hw_wl_modem(false)
|
|
||||||
end
|
|
||||||
elseif bus.wd_nic and bus.wd_nic.is_modem(device) then
|
|
||||||
bus.wd_nic.disconnect()
|
|
||||||
|
|
||||||
println("wired modem disconnected")
|
|
||||||
log.warning("wired modem disconnected")
|
|
||||||
|
|
||||||
databus.tx_hw_wd_modem(false)
|
|
||||||
else
|
|
||||||
log.warning("non-comms modem disconnected")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return pcie_bus
|
|
||||||
@ -3,7 +3,6 @@
|
|||||||
--
|
--
|
||||||
|
|
||||||
require("/initenv").init_env()
|
require("/initenv").init_env()
|
||||||
local pcie = require("supervisor.pcie")
|
|
||||||
|
|
||||||
local crash = require("scada-common.crash")
|
local crash = require("scada-common.crash")
|
||||||
local comms = require("scada-common.comms")
|
local comms = require("scada-common.comms")
|
||||||
@ -16,6 +15,7 @@ local util = require("scada-common.util")
|
|||||||
|
|
||||||
local core = require("graphics.core")
|
local core = require("graphics.core")
|
||||||
|
|
||||||
|
local backplane = require("supervisor.backplane")
|
||||||
local configure = require("supervisor.configure")
|
local configure = require("supervisor.configure")
|
||||||
local databus = require("supervisor.databus")
|
local databus = require("supervisor.databus")
|
||||||
local facility = require("supervisor.facility")
|
local facility = require("supervisor.facility")
|
||||||
@ -24,7 +24,7 @@ local supervisor = require("supervisor.supervisor")
|
|||||||
|
|
||||||
local svsessions = require("supervisor.session.svsessions")
|
local svsessions = require("supervisor.session.svsessions")
|
||||||
|
|
||||||
local SUPERVISOR_VERSION = "v1.7.1"
|
local SUPERVISOR_VERSION = "v1.8.0"
|
||||||
|
|
||||||
local println = util.println
|
local println = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
@ -126,8 +126,8 @@ local function main()
|
|||||||
network.init_mac(config.AuthKey)
|
network.init_mac(config.AuthKey)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- hardware bus initialization
|
-- hardware backplane initialization
|
||||||
if not pcie.init(config, println) then return end
|
if not backplane.init(config, println) then return end
|
||||||
|
|
||||||
-- start UI
|
-- start UI
|
||||||
local fp_ok, message = renderer.try_start_ui(config)
|
local fp_ok, message = renderer.try_start_ui(config)
|
||||||
@ -167,12 +167,12 @@ local function main()
|
|||||||
if event == "peripheral_detach" then
|
if event == "peripheral_detach" then
|
||||||
local type, device = ppm.handle_unmount(param1)
|
local type, device = ppm.handle_unmount(param1)
|
||||||
if type ~= nil and device ~= nil then
|
if type ~= nil and device ~= nil then
|
||||||
pcie.remove(param1, type, device, println_ts)
|
backplane.detach(param1, type, device, println_ts)
|
||||||
end
|
end
|
||||||
elseif event == "peripheral" then
|
elseif event == "peripheral" then
|
||||||
local type, device = ppm.mount(param1)
|
local type, device = ppm.mount(param1)
|
||||||
if type ~= nil and device ~= nil then
|
if type ~= nil and device ~= nil then
|
||||||
pcie.connect(param1, type, device, println_ts)
|
backplane.attach(param1, type, device, println_ts)
|
||||||
end
|
end
|
||||||
elseif event == "timer" and loop_clock.is_clock(param1) then
|
elseif event == "timer" and loop_clock.is_clock(param1) then
|
||||||
-- main loop tick
|
-- main loop tick
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
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 util = require("scada-common.util")
|
local util = require("scada-common.util")
|
||||||
local pcie = require("supervisor.pcie")
|
|
||||||
|
|
||||||
local themes = require("graphics.themes")
|
local themes = require("graphics.themes")
|
||||||
|
|
||||||
|
local backplane = require("supervisor.backplane")
|
||||||
|
|
||||||
local svsessions = require("supervisor.session.svsessions")
|
local svsessions = require("supervisor.session.svsessions")
|
||||||
|
|
||||||
local supervisor = {}
|
local supervisor = {}
|
||||||
@ -198,8 +199,11 @@ function supervisor.comms(_version, fp_ok, facility)
|
|||||||
---@param distance integer
|
---@param distance integer
|
||||||
---@return modbus_frame|rplc_frame|mgmt_frame|crdn_frame|nil packet
|
---@return modbus_frame|rplc_frame|mgmt_frame|crdn_frame|nil packet
|
||||||
function public.parse_packet(side, sender, reply_to, message, distance)
|
function public.parse_packet(side, sender, reply_to, message, distance)
|
||||||
local pkt, nic = nil, pcie.nic.cards[side]
|
local pkt, s_pkt, nic = nil, nil, backplane.nics[side]
|
||||||
local s_pkt = nic.receive(side, sender, reply_to, message, distance)
|
|
||||||
|
if nic then
|
||||||
|
s_pkt = nic.receive(side, sender, reply_to, message, distance)
|
||||||
|
end
|
||||||
|
|
||||||
if s_pkt then
|
if s_pkt then
|
||||||
-- get as MODBUS TCP packet
|
-- get as MODBUS TCP packet
|
||||||
@ -229,7 +233,7 @@ function supervisor.comms(_version, fp_ok, facility)
|
|||||||
-- handle a packet
|
-- handle a packet
|
||||||
---@param packet modbus_frame|rplc_frame|mgmt_frame|crdn_frame
|
---@param packet modbus_frame|rplc_frame|mgmt_frame|crdn_frame
|
||||||
function public.handle_packet(packet)
|
function public.handle_packet(packet)
|
||||||
local nic = pcie.nic.get(packet.scada_frame.interface())
|
local nic = backplane.nics[packet.scada_frame.interface()]
|
||||||
local l_chan = packet.scada_frame.local_channel()
|
local l_chan = packet.scada_frame.local_channel()
|
||||||
local r_chan = packet.scada_frame.remote_channel()
|
local r_chan = packet.scada_frame.remote_channel()
|
||||||
local src_addr = packet.scada_frame.src_addr()
|
local src_addr = packet.scada_frame.src_addr()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user