#634 coordinator backplane interface
This commit is contained in:
228
coordinator/backplane.lua
Normal file
228
coordinator/backplane.lua
Normal file
@@ -0,0 +1,228 @@
|
||||
--
|
||||
-- Coordinator 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 coordinator = require("coordinator.coordinator")
|
||||
local iocontrol = require("coordinator.iocontrol")
|
||||
local sounder = require("coordinator.sounder")
|
||||
|
||||
local println = util.println
|
||||
|
||||
local log_sys = coordinator.log_sys
|
||||
local log_boot = coordinator.log_boot
|
||||
local log_comms = coordinator.log_comms
|
||||
|
||||
---@class crd_backplane
|
||||
local backplane = {}
|
||||
|
||||
local _bp = {
|
||||
smem = nil, ---@type crd_shared_memory
|
||||
|
||||
wlan_pref = true,
|
||||
lan_iface = "",
|
||||
|
||||
act_nic = nil, ---@type nic
|
||||
wd_nic = nil, ---@type nic|nil
|
||||
wl_nic = nil, ---@type nic|nil
|
||||
|
||||
speaker = nil, ---@type Speaker|nil
|
||||
|
||||
---@class crd_displays
|
||||
displays = {
|
||||
main = nil, ---@type Monitor|nil
|
||||
main_iface = "",
|
||||
flow = nil, ---@type Monitor|nil
|
||||
flow_iface = "",
|
||||
unit_displays = {}, ---@type Monitor[]
|
||||
unit_ifaces = {} ---@type string[]
|
||||
}
|
||||
}
|
||||
|
||||
-- initialize the display peripheral backplane
|
||||
---@param config crd_config
|
||||
---@return boolean success, string error_msg
|
||||
function backplane.init_displays(config)
|
||||
local displays = _bp.displays
|
||||
|
||||
local w, h, _
|
||||
|
||||
log.info("BKPLN: DISPLAY INIT")
|
||||
|
||||
-- monitor configuration verification
|
||||
|
||||
local mon_cfv = util.new_validator()
|
||||
|
||||
mon_cfv.assert_type_str(config.MainDisplay)
|
||||
if not config.DisableFlowView then mon_cfv.assert_type_str(config.FlowDisplay) end
|
||||
|
||||
mon_cfv.assert_eq(#config.UnitDisplays, config.UnitCount)
|
||||
for i = 1, #config.UnitDisplays do
|
||||
mon_cfv.assert_type_str(config.UnitDisplays[i])
|
||||
end
|
||||
|
||||
if not mon_cfv.valid() then
|
||||
return false, "Monitor configuration invalid."
|
||||
end
|
||||
|
||||
-- setup and check display peripherals
|
||||
|
||||
-- main display
|
||||
|
||||
local disp, iface = ppm.get_periph(config.MainDisplay), config.MainDisplay
|
||||
|
||||
displays.main = disp
|
||||
displays.main_iface = iface
|
||||
|
||||
log.info("BKPLN: DISPLAY LINK_" .. util.trinary(disp, "UP", "DOWN") .. " MAIN/" .. iface)
|
||||
|
||||
if not disp then
|
||||
return false, "Main monitor is not connected."
|
||||
end
|
||||
|
||||
disp.setTextScale(0.5)
|
||||
w, _ = ppm.monitor_block_size(disp.getSize())
|
||||
if w ~= 8 then
|
||||
log.info("BKPLN: DISPLAY MAIN/" .. iface .. " BAD RESOLUTION")
|
||||
return false, util.c("Main monitor width is incorrect (was ", w, ", must be 8).")
|
||||
end
|
||||
|
||||
-- flow display
|
||||
|
||||
if not config.DisableFlowView then
|
||||
disp, iface = ppm.get_periph(config.FlowDisplay), config.FlowDisplay
|
||||
|
||||
displays.flow = disp
|
||||
displays.flow_iface = iface
|
||||
|
||||
log.info("BKPLN: DISPLAY LINK_" .. util.trinary(disp, "UP", "DOWN") .. " FLOW/" .. iface)
|
||||
|
||||
if not disp then
|
||||
return false, "Flow monitor is not connected."
|
||||
end
|
||||
|
||||
disp.setTextScale(0.5)
|
||||
w, _ = ppm.monitor_block_size(disp.getSize())
|
||||
if w ~= 8 then
|
||||
log.info("BKPLN: DISPLAY FLOW/" .. iface .. " BAD RESOLUTION")
|
||||
return false, util.c("Flow monitor width is incorrect (was ", w, ", must be 8).")
|
||||
end
|
||||
end
|
||||
|
||||
-- unit display(s)
|
||||
|
||||
for i = 1, config.UnitCount do
|
||||
disp, iface = ppm.get_periph(config.UnitDisplays[i]), config.UnitDisplays[i]
|
||||
|
||||
displays.unit_displays[i] = disp
|
||||
displays.unit_ifaces[i] = iface
|
||||
|
||||
log.info("BKPLN: DISPLAY LINK_" .. util.trinary(disp, "UP", "DOWN") .. " UNIT_" .. i .. "/" .. iface)
|
||||
|
||||
if not disp then
|
||||
return false, "Unit " .. i .. " monitor is not connected."
|
||||
end
|
||||
|
||||
disp.setTextScale(0.5)
|
||||
w, h = ppm.monitor_block_size(disp.getSize())
|
||||
if w ~= 4 or h ~= 4 then
|
||||
log.info("BKPLN: DISPLAY UNIT_" .. i .. "/" .. iface .. " BAD RESOLUTION")
|
||||
return false, util.c("Unit ", i, " monitor size is incorrect (was ", w, " by ", h,", must be 4 by 4).")
|
||||
end
|
||||
end
|
||||
|
||||
log.info("BKPLN: DISPLAY INIT OK")
|
||||
|
||||
return true, ""
|
||||
end
|
||||
|
||||
-- initialize the system peripheral backplane
|
||||
---@param config crd_config
|
||||
---@param __shared_memory crd_shared_memory
|
||||
---@return boolean success
|
||||
function backplane.init(config, __shared_memory)
|
||||
_bp.smem = __shared_memory
|
||||
_bp.wlan_pref = config.PreferWireless
|
||||
_bp.lan_iface = config.WiredModem
|
||||
|
||||
-- Modem Init
|
||||
|
||||
-- init wired NIC
|
||||
if type(config.WiredModem) == "string" then
|
||||
local modem = ppm.get_modem(_bp.lan_iface)
|
||||
local wd_nic = network.nic(modem)
|
||||
|
||||
log.info("BKPLN: WIRED PHY_" .. util.trinary(modem, "UP ", "DOWN ") .. _bp.lan_iface)
|
||||
log_comms("wired comms modem " .. util.trinary(modem, "connected", "not found"))
|
||||
|
||||
-- set this as active for now
|
||||
_bp.act_nic = wd_nic
|
||||
_bp.wd_nic = wd_nic
|
||||
|
||||
iocontrol.fp_has_wd_modem(modem ~= nil)
|
||||
end
|
||||
|
||||
-- init wireless NIC(s)
|
||||
if config.WirelessModem then
|
||||
local modem, iface = ppm.get_wireless_modem()
|
||||
local wl_nic = network.nic(modem)
|
||||
|
||||
log.info("BKPLN: WIRELESS PHY_" .. util.trinary(modem, "UP ", "DOWN ") .. iface)
|
||||
log_comms("wireless comms modem " .. util.trinary(modem, "connected", "not found"))
|
||||
|
||||
-- set this as active if connected or if both modems are disconnected and this is preferred
|
||||
if (modem and _bp.wlan_pref) or not (_bp.act_nic and _bp.act_nic.is_connected()) then
|
||||
_bp.act_nic = wl_nic
|
||||
end
|
||||
|
||||
_bp.wl_nic = wl_nic
|
||||
|
||||
iocontrol.fp_has_wl_modem(modem ~= nil)
|
||||
end
|
||||
|
||||
-- at least one comms modem is required
|
||||
if not ((_bp.wd_nic and _bp.wd_nic.is_connected()) or (_bp.wl_nic and _bp.wl_nic.is_connected())) then
|
||||
log_comms("no comms modem found")
|
||||
println("startup> no comms modem found")
|
||||
log.warning("BKPLN: no comms modem on startup")
|
||||
return false
|
||||
end
|
||||
|
||||
-- Speaker Init
|
||||
|
||||
_bp.speaker = ppm.get_device("speaker")
|
||||
|
||||
if not _bp.speaker then
|
||||
log_boot("annunciator alarm speaker not found")
|
||||
|
||||
println("startup> speaker not found")
|
||||
log.fatal("BKPLN: no annunciator alarm speaker found")
|
||||
|
||||
return false
|
||||
else
|
||||
log.info("BKPLN: SPEAKER LINK_UP " .. ppm.get_iface(_bp.speaker))
|
||||
log_boot("annunciator alarm speaker connected")
|
||||
|
||||
local sounder_start = util.time_ms()
|
||||
sounder.init(_bp.speaker, config.SpeakerVolume)
|
||||
|
||||
log_boot("tone generation took " .. (util.time_ms() - sounder_start) .. "ms")
|
||||
log_sys("annunciator alarm configured")
|
||||
|
||||
iocontrol.fp_has_speaker(true)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- get the active NIC
|
||||
---@return nic
|
||||
function backplane.active_nic() return _bp.act_nic end
|
||||
|
||||
function backplane.displays() return _bp.displays end
|
||||
|
||||
return backplane
|
||||
@@ -29,11 +29,9 @@ local config = {}
|
||||
|
||||
coordinator.config = config
|
||||
|
||||
-- load the coordinator configuration<br>
|
||||
-- status of 0 is OK, 1 is bad config, 2 is bad monitor config
|
||||
---@return 0|1|2 status, nil|monitors_struct|string monitors (or error message)
|
||||
-- load the coordinator configuration
|
||||
function coordinator.load_config()
|
||||
if not settings.load("/coordinator.settings") then return 1 end
|
||||
if not settings.load("/coordinator.settings") then return false end
|
||||
|
||||
config.UnitCount = settings.get("UnitCount")
|
||||
config.SpeakerVolume = settings.get("SpeakerVolume")
|
||||
@@ -121,85 +119,7 @@ function coordinator.load_config()
|
||||
cfv.assert_type_int(config.ColorMode)
|
||||
cfv.assert_range(config.ColorMode, 1, themes.COLOR_MODE.NUM_MODES)
|
||||
|
||||
-- Monitor Setup
|
||||
|
||||
---@class monitors_struct
|
||||
local monitors = {
|
||||
main = nil, ---@type Monitor|nil
|
||||
main_name = "",
|
||||
flow = nil, ---@type Monitor|nil
|
||||
flow_name = "",
|
||||
unit_displays = {}, ---@type Monitor[]
|
||||
unit_name_map = {} ---@type string[]
|
||||
}
|
||||
|
||||
local mon_cfv = util.new_validator()
|
||||
|
||||
-- get all interface names
|
||||
local names = {}
|
||||
for iface, _ in pairs(ppm.get_monitor_list()) do table.insert(names, iface) end
|
||||
|
||||
local function setup_monitors()
|
||||
mon_cfv.assert_type_str(config.MainDisplay)
|
||||
if not config.DisableFlowView then mon_cfv.assert_type_str(config.FlowDisplay) end
|
||||
mon_cfv.assert_eq(#config.UnitDisplays, config.UnitCount)
|
||||
|
||||
if mon_cfv.valid() then
|
||||
local w, h, _
|
||||
|
||||
if not util.table_contains(names, config.MainDisplay) then
|
||||
return 2, "Main monitor is not connected."
|
||||
end
|
||||
|
||||
monitors.main = ppm.get_periph(config.MainDisplay)
|
||||
monitors.main_name = config.MainDisplay
|
||||
|
||||
monitors.main.setTextScale(0.5)
|
||||
w, _ = ppm.monitor_block_size(monitors.main.getSize())
|
||||
if w ~= 8 then
|
||||
return 2, util.c("Main monitor width is incorrect (was ", w, ", must be 8).")
|
||||
end
|
||||
|
||||
if not config.DisableFlowView then
|
||||
if not util.table_contains(names, config.FlowDisplay) then
|
||||
return 2, "Flow monitor is not connected."
|
||||
end
|
||||
|
||||
monitors.flow = ppm.get_periph(config.FlowDisplay)
|
||||
monitors.flow_name = config.FlowDisplay
|
||||
|
||||
monitors.flow.setTextScale(0.5)
|
||||
w, _ = ppm.monitor_block_size(monitors.flow.getSize())
|
||||
if w ~= 8 then
|
||||
return 2, util.c("Flow monitor width is incorrect (was ", w, ", must be 8).")
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, config.UnitCount do
|
||||
local display = config.UnitDisplays[i]
|
||||
if type(display) ~= "string" or not util.table_contains(names, display) then
|
||||
return 2, "Unit " .. i .. " monitor is not connected."
|
||||
end
|
||||
|
||||
monitors.unit_displays[i] = ppm.get_periph(display)
|
||||
monitors.unit_name_map[i] = display
|
||||
|
||||
monitors.unit_displays[i].setTextScale(0.5)
|
||||
w, h = ppm.monitor_block_size(monitors.unit_displays[i].getSize())
|
||||
if w ~= 4 or h ~= 4 then
|
||||
return 2, util.c("Unit ", i, " monitor size is incorrect (was ", w, " by ", h,", must be 4 by 4).")
|
||||
end
|
||||
end
|
||||
else return 2, "Monitor configuration invalid." end
|
||||
end
|
||||
|
||||
if cfv.valid() then
|
||||
local ok, result, message = pcall(setup_monitors)
|
||||
assert(ok, util.c("fatal error while trying to verify monitors: ", result))
|
||||
if result == 2 then return 2, message end
|
||||
else return 1 end
|
||||
|
||||
return 0, monitors
|
||||
return cfv.valid()
|
||||
end
|
||||
|
||||
-- dmesg print wrapper
|
||||
|
||||
@@ -290,9 +290,13 @@ end
|
||||
-- toggle heartbeat indicator
|
||||
function iocontrol.heartbeat() io.fp.ps.toggle("heartbeat") end
|
||||
|
||||
-- report presence of the wired modem
|
||||
---@param has_modem boolean
|
||||
function iocontrol.fp_has_wd_modem(has_modem) io.fp.ps.publish("has_wd_modem", has_modem) end
|
||||
|
||||
-- report presence of the wireless modem
|
||||
---@param has_modem boolean
|
||||
function iocontrol.fp_has_modem(has_modem) io.fp.ps.publish("has_modem", has_modem) end
|
||||
function iocontrol.fp_has_wl_modem(has_modem) io.fp.ps.publish("has_wl_modem", has_modem) end
|
||||
|
||||
-- report presence of the speaker
|
||||
---@param has_speaker boolean
|
||||
|
||||
@@ -29,7 +29,7 @@ local renderer = {}
|
||||
-- render engine
|
||||
local engine = {
|
||||
color_mode = 1, ---@type COLOR_MODE
|
||||
monitors = nil, ---@type monitors_struct|nil
|
||||
monitors = nil, ---@type crd_displays|nil
|
||||
dmesg_window = nil, ---@type Window|nil
|
||||
ui_ready = false,
|
||||
fp_ready = false,
|
||||
@@ -83,7 +83,7 @@ function renderer.configure(config)
|
||||
end
|
||||
|
||||
-- link to the monitor peripherals
|
||||
---@param monitors monitors_struct
|
||||
---@param monitors crd_displays
|
||||
function renderer.set_displays(monitors)
|
||||
engine.monitors = monitors
|
||||
|
||||
@@ -336,18 +336,18 @@ function renderer.handle_reconnect(name, device)
|
||||
-- note: handle_resize is a more adaptive way of re-initializing a connected monitor
|
||||
-- since it can handle a monitor being reconnected that isn't the right size
|
||||
|
||||
if engine.monitors.main_name == name then
|
||||
if engine.monitors.main_iface == name then
|
||||
is_used = true
|
||||
engine.monitors.main = device
|
||||
|
||||
renderer.handle_resize(name)
|
||||
elseif engine.monitors.flow_name == name then
|
||||
elseif engine.monitors.flow_iface == name then
|
||||
is_used = true
|
||||
engine.monitors.flow = device
|
||||
|
||||
renderer.handle_resize(name)
|
||||
else
|
||||
for idx, monitor in ipairs(engine.monitors.unit_name_map) do
|
||||
for idx, monitor in ipairs(engine.monitors.unit_ifaces) do
|
||||
if monitor == name then
|
||||
is_used = true
|
||||
engine.monitors.unit_displays[idx] = device
|
||||
@@ -372,7 +372,7 @@ function renderer.handle_resize(name)
|
||||
|
||||
if not engine.monitors then return false, false end
|
||||
|
||||
if engine.monitors.main_name == name and engine.monitors.main then
|
||||
if engine.monitors.main_iface == name and engine.monitors.main then
|
||||
local device = engine.monitors.main ---@type Monitor
|
||||
|
||||
-- this is necessary if the bottom left block was broken and on reconnect
|
||||
@@ -415,7 +415,7 @@ function renderer.handle_resize(name)
|
||||
is_ok = false
|
||||
end
|
||||
else engine.dmesg_window.redraw() end
|
||||
elseif engine.monitors.flow_name == name and engine.monitors.flow then
|
||||
elseif engine.monitors.flow_iface == name and engine.monitors.flow then
|
||||
local device = engine.monitors.flow ---@type Monitor
|
||||
|
||||
-- this is necessary if the bottom left block was broken and on reconnect
|
||||
@@ -452,7 +452,7 @@ function renderer.handle_resize(name)
|
||||
end
|
||||
end
|
||||
else
|
||||
for idx, monitor in ipairs(engine.monitors.unit_name_map) do
|
||||
for idx, monitor in ipairs(engine.monitors.unit_ifaces) do
|
||||
local device = engine.monitors.unit_displays[idx]
|
||||
|
||||
if monitor == name and device then
|
||||
@@ -505,12 +505,12 @@ function renderer.handle_mouse(event)
|
||||
if engine.fp_ready and event.monitor == "terminal" then
|
||||
engine.ui.front_panel.handle_mouse(event)
|
||||
elseif engine.ui_ready then
|
||||
if event.monitor == engine.monitors.main_name then
|
||||
if event.monitor == engine.monitors.main_iface then
|
||||
if engine.ui.main_display then engine.ui.main_display.handle_mouse(event) end
|
||||
elseif event.monitor == engine.monitors.flow_name then
|
||||
elseif event.monitor == engine.monitors.flow_iface then
|
||||
if engine.ui.flow_display then engine.ui.flow_display.handle_mouse(event) end
|
||||
else
|
||||
for id, monitor in ipairs(engine.monitors.unit_name_map) do
|
||||
for id, monitor in ipairs(engine.monitors.unit_ifaces) do
|
||||
local display = engine.ui.unit_displays[id]
|
||||
if event.monitor == monitor and display then
|
||||
if display then display.handle_mouse(event) end
|
||||
|
||||
@@ -12,6 +12,7 @@ local network = require("scada-common.network")
|
||||
local ppm = require("scada-common.ppm")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local backplane = require("coordinator.backplane")
|
||||
local configure = require("coordinator.configure")
|
||||
local coordinator = require("coordinator.coordinator")
|
||||
local iocontrol = require("coordinator.iocontrol")
|
||||
@@ -36,45 +37,13 @@ local log_crypto = coordinator.log_crypto
|
||||
-- get configuration
|
||||
----------------------------------------
|
||||
|
||||
-- mount connected devices (required for monitor setup)
|
||||
ppm.mount_all()
|
||||
|
||||
local wait_on_load = true
|
||||
local loaded, monitors = coordinator.load_config()
|
||||
|
||||
-- if the computer just started, its chunk may have just loaded (...or the user rebooted)
|
||||
-- if monitor config failed, maybe an adjacent chunk containing all or part of a monitor has not loaded yet, so keep trying
|
||||
while wait_on_load and loaded == 2 and os.clock() < CHUNK_LOAD_DELAY_S do
|
||||
term.clear()
|
||||
term.setCursorPos(1, 1)
|
||||
println("There was a monitor configuration problem at boot.\n")
|
||||
println("Startup will keep trying every 2s in case of chunk load delays.\n")
|
||||
println(util.sprintf("The configurator will be started in %ds if all attempts fail.\n", math.max(0, CHUNK_LOAD_DELAY_S - os.clock())))
|
||||
println("(click to skip to the configurator)")
|
||||
|
||||
local timer_id = util.start_timer(2)
|
||||
|
||||
while true do
|
||||
local event, param1 = util.pull_event()
|
||||
if event == "timer" and param1 == timer_id then
|
||||
-- remount and re-attempt
|
||||
ppm.mount_all()
|
||||
loaded, monitors = coordinator.load_config()
|
||||
break
|
||||
elseif event == "mouse_click" or event == "terminate" then
|
||||
wait_on_load = false
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if loaded ~= 0 then
|
||||
-- first pass configuration check before validating monitors
|
||||
if not coordinator.load_config() then
|
||||
-- try to reconfigure (user action)
|
||||
local success, error = configure.configure(loaded, monitors)
|
||||
local success, error = configure.configure(1)
|
||||
if success then
|
||||
loaded, monitors = coordinator.load_config()
|
||||
if loaded ~= 0 then
|
||||
println(util.trinary(loaded == 2, "monitor configuration invalid", "failed to load a valid configuration") .. ", please reconfigure")
|
||||
if not coordinator.load_config() then
|
||||
println("failed to load a valid configuration, please reconfigure")
|
||||
return
|
||||
end
|
||||
else
|
||||
@@ -83,9 +52,6 @@ if loaded ~= 0 then
|
||||
end
|
||||
end
|
||||
|
||||
-- passed checks, good now
|
||||
---@cast monitors monitors_struct
|
||||
|
||||
local config = coordinator.config
|
||||
|
||||
----------------------------------------
|
||||
@@ -102,6 +68,64 @@ println(">> SCADA Coordinator " .. COORDINATOR_VERSION .. " <<")
|
||||
crash.set_env("coordinator", COORDINATOR_VERSION)
|
||||
crash.dbg_log_env()
|
||||
|
||||
----------------------------------------
|
||||
-- display init
|
||||
----------------------------------------
|
||||
|
||||
-- mount connected devices (required for monitor setup)
|
||||
ppm.mount_all()
|
||||
|
||||
local wait_on_load = true
|
||||
|
||||
local disp_ok, disp_err = backplane.init_displays(config)
|
||||
|
||||
-- if the computer just started, its chunk may have just loaded (...or the user rebooted)
|
||||
-- if monitor config failed, maybe an adjacent chunk containing all or part of a monitor has not loaded yet, so keep trying
|
||||
while wait_on_load and (not disp_ok) and os.clock() < CHUNK_LOAD_DELAY_S do
|
||||
term.clear()
|
||||
term.setCursorPos(1, 1)
|
||||
println("There was a monitor configuration problem at boot.\n")
|
||||
println("Startup will keep trying every 2s in case of chunk load delays.\n")
|
||||
println(util.sprintf("The configurator will be started in %ds if all attempts fail.\n", math.max(0, CHUNK_LOAD_DELAY_S - os.clock())))
|
||||
println("(click to skip to the configurator)")
|
||||
|
||||
local timer_id = util.start_timer(2)
|
||||
|
||||
while true do
|
||||
local event, param1 = util.pull_event()
|
||||
if event == "timer" and param1 == timer_id then
|
||||
-- remount and re-attempt
|
||||
ppm.mount_all()
|
||||
disp_ok, disp_err = backplane.init_displays(config)
|
||||
break
|
||||
elseif event == "mouse_click" or event == "terminate" then
|
||||
wait_on_load = false
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not disp_ok then
|
||||
-- try to reconfigure (user action)
|
||||
local success, error = configure.configure(2, disp_err)
|
||||
if success then
|
||||
if not coordinator.load_config() then
|
||||
println("failed to load a valid configuration, please reconfigure")
|
||||
return
|
||||
else
|
||||
disp_ok, disp_err = backplane.init_displays(config)
|
||||
|
||||
if not disp_ok then
|
||||
println("monitor configuration invalid, please reconfigure")
|
||||
return
|
||||
end
|
||||
end
|
||||
else
|
||||
println("configuration error: " .. error)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------
|
||||
-- main application
|
||||
----------------------------------------
|
||||
@@ -111,15 +135,12 @@ local function main()
|
||||
-- system startup
|
||||
----------------------------------------
|
||||
|
||||
-- log mounts now since mounting was done before logging was ready
|
||||
ppm.log_mounts()
|
||||
|
||||
-- report versions/init fp PSIL
|
||||
iocontrol.init_fp(COORDINATOR_VERSION, comms.version)
|
||||
|
||||
-- init renderer
|
||||
renderer.configure(config)
|
||||
renderer.set_displays(monitors)
|
||||
renderer.set_displays(backplane.displays())
|
||||
renderer.init_displays()
|
||||
renderer.init_dmesg()
|
||||
|
||||
@@ -130,6 +151,12 @@ local function main()
|
||||
log_sys("system start on " .. os.date("%c"))
|
||||
log_boot("starting " .. COORDINATOR_VERSION)
|
||||
|
||||
-- message authentication init
|
||||
if type(config.AuthKey) == "string" and string.len(config.AuthKey) > 0 then
|
||||
local init_time = network.init_mac(config.AuthKey)
|
||||
log_crypto("HMAC init took " .. init_time .. "ms")
|
||||
end
|
||||
|
||||
----------------------------------------
|
||||
-- memory allocation
|
||||
----------------------------------------
|
||||
@@ -149,15 +176,9 @@ local function main()
|
||||
shutdown = false
|
||||
},
|
||||
|
||||
-- core coordinator devices
|
||||
crd_dev = {
|
||||
modem = ppm.get_wireless_modem(),
|
||||
speaker = ppm.get_device("speaker") ---@type Speaker|nil
|
||||
},
|
||||
|
||||
-- system objects
|
||||
---@class crd_sys
|
||||
crd_sys = {
|
||||
nic = nil, ---@type nic
|
||||
coord_comms = nil, ---@type coord_comms
|
||||
conn_watchdog = nil ---@type watchdog
|
||||
},
|
||||
@@ -168,65 +189,17 @@ local function main()
|
||||
}
|
||||
}
|
||||
|
||||
local smem_dev = __shared_memory.crd_dev
|
||||
local smem_sys = __shared_memory.crd_sys
|
||||
|
||||
local smem_sys = __shared_memory.crd_sys
|
||||
local crd_state = __shared_memory.crd_state
|
||||
|
||||
----------------------------------------
|
||||
-- setup alarm sounder subsystem
|
||||
-- init system
|
||||
----------------------------------------
|
||||
|
||||
if smem_dev.speaker == nil then
|
||||
log_boot("annunciator alarm speaker not found")
|
||||
println("startup> speaker not found")
|
||||
log.fatal("no annunciator alarm speaker found")
|
||||
return
|
||||
else
|
||||
local sounder_start = util.time_ms()
|
||||
log_boot("annunciator alarm speaker connected")
|
||||
sounder.init(smem_dev.speaker, config.SpeakerVolume)
|
||||
log_boot("tone generation took " .. (util.time_ms() - sounder_start) .. "ms")
|
||||
log_sys("annunciator alarm configured")
|
||||
iocontrol.fp_has_speaker(true)
|
||||
end
|
||||
-- modem and speaker initialization
|
||||
if not backplane.init(config, __shared_memory) then return end
|
||||
|
||||
----------------------------------------
|
||||
-- setup communications
|
||||
----------------------------------------
|
||||
|
||||
-- message authentication init
|
||||
if type(config.AuthKey) == "string" and string.len(config.AuthKey) > 0 then
|
||||
local init_time = network.init_mac(config.AuthKey)
|
||||
log_crypto("HMAC init took " .. init_time .. "ms")
|
||||
end
|
||||
|
||||
-- get the communications modem
|
||||
if smem_dev.modem == nil then
|
||||
log_comms("wireless modem not found")
|
||||
println("startup> wireless modem not found")
|
||||
log.fatal("no wireless modem on startup")
|
||||
return
|
||||
else
|
||||
log_comms("wireless modem connected")
|
||||
iocontrol.fp_has_modem(true)
|
||||
end
|
||||
|
||||
-- create connection watchdog
|
||||
smem_sys.conn_watchdog = util.new_watchdog(config.SVR_Timeout)
|
||||
smem_sys.conn_watchdog.cancel()
|
||||
log.debug("startup> conn watchdog created")
|
||||
|
||||
-- create network interface then setup comms
|
||||
smem_sys.nic = network.nic(smem_dev.modem)
|
||||
smem_sys.coord_comms = coordinator.comms(COORDINATOR_VERSION, smem_sys.nic, smem_sys.conn_watchdog)
|
||||
log.debug("startup> comms init")
|
||||
log_comms("comms initialized")
|
||||
|
||||
----------------------------------------
|
||||
-- start front panel
|
||||
----------------------------------------
|
||||
|
||||
log_render("starting front panel UI...")
|
||||
|
||||
local fp_message
|
||||
@@ -238,6 +211,16 @@ local function main()
|
||||
return
|
||||
else log_render("front panel ready") end
|
||||
|
||||
-- create connection watchdog
|
||||
smem_sys.conn_watchdog = util.new_watchdog(config.SVR_Timeout)
|
||||
smem_sys.conn_watchdog.cancel()
|
||||
log.debug("startup> conn watchdog created")
|
||||
|
||||
-- setup comms
|
||||
smem_sys.coord_comms = coordinator.comms(COORDINATOR_VERSION, backplane.active_nic(), smem_sys.conn_watchdog)
|
||||
log.debug("startup> comms init")
|
||||
log_comms("comms initialized")
|
||||
|
||||
----------------------------------------
|
||||
-- start system
|
||||
----------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user