#61 monitor configuration and init, render engine started, dmesg changes, ppm monitor listing changes

This commit is contained in:
Mikayla Fischler
2022-05-29 14:34:09 -04:00
parent ff5b163c1d
commit e65a1bf6e1
8 changed files with 333 additions and 23 deletions

22
coordinator/config.lua Normal file
View File

@@ -0,0 +1,22 @@
local config = {}
-- port of the SCADA supervisor
config.SCADA_SV_PORT = 16100
-- port to listen to incoming packets from supervisor
config.SCADA_SV_LISTEN = 16101
-- listen port for SCADA coordinator API access
config.SCADA_API_LISTEN = 16200
-- expected number of reactor units
config.NUM_UNITS = 4
-- log path
config.LOG_PATH = "/log.txt"
-- log mode
-- 0 = APPEND (adds to existing file on start)
-- 1 = NEW (replaces existing file on start)
config.LOG_MODE = 0
-- crypto config
config.SECURE = true
-- must be common between all devices
config.PASSWORD = "testpassword!"
return config

View File

@@ -1,9 +1,141 @@
local comms = require("scada-common.comms")
local log = require("scada-common.log")
local ppm = require("scada-common.ppm")
local util = require("scada-common.util")
local dialog = require("coordinator.util.dialog")
local print = util.print
local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts
local coordinator = {}
local function ask_monitor(names)
println("available monitors:")
for i = 1, #names do
print(" " .. names[i])
end
println("")
println("select a monitor or type c to cancel")
local iface = dialog.ask_options(names, "c")
if iface ~= false and iface ~= nil then
util.filter_table(names, function (x) return x ~= iface end)
end
return iface
end
function coordinator.configure_monitors(num_units)
---@class monitors_struct
local monitors = {
primary = nil,
unit_displays = {}
}
local monitors_avail = ppm.get_monitor_list()
local names = {}
-- get all interface names
for iface, _ in pairs(monitors_avail) do
table.insert(names, iface)
end
-- we need a certain number of monitors (1 per unit + 1 primary display)
if #names ~= num_units + 1 then
println("not enough monitors connected (need " .. num_units + 1 .. ")")
log.warning("insufficient monitors present (need " .. num_units + 1 .. ")")
return false
end
-- attempt to load settings
settings.load("/coord.settings")
---------------------
-- PRIMARY DISPLAY --
---------------------
local iface_primary_display = settings.get("PRIMARY_DISPLAY")
if not util.table_contains(names, iface_primary_display) then
println("primary display is not connected")
local response = dialog.ask_y_n("would you like to change it", true)
if response == false then return false end
iface_primary_display = nil
end
while iface_primary_display == nil and #names > 0 do
-- lets get a monitor
iface_primary_display = ask_monitor(names)
end
if iface_primary_display == false then return false end
settings.set("PRIMARY_DISPLAY", iface_primary_display)
util.filter_table(names, function (x) return x ~= iface_primary_display end)
monitors.primary = ppm.get_periph(iface_primary_display)
-------------------
-- UNIT DISPLAYS --
-------------------
local unit_displays = settings.get("UNIT_DISPLAYS")
if unit_displays == nil then
unit_displays = {}
for i = 1, num_units do
local display = nil
while display == nil and #names > 0 do
-- lets get a monitor
println("please select monitor for unit " .. i)
display = ask_monitor(names)
end
if display == false then return false end
unit_displays[i] = display
end
else
-- make sure all displays are connected
for i = 1, num_units do
---@diagnostic disable-next-line: need-check-nil
local display = unit_displays[i]
if not util.table_contains(names, display) then
local response = dialog.ask_y_n("unit display " .. i .. " is not connected, would you like to change it?", true)
if response == false then return false end
display = nil
end
while display == nil and #names > 0 do
-- lets get a monitor
display = ask_monitor(names)
end
if display == false then return false end
unit_displays[i] = display
end
end
settings.set("UNIT_DISPLAYS", unit_displays)
settings.save("/coord.settings")
for i = 1, #unit_displays do
monitors.unit_displays[i] = ppm.get_periph(unit_displays[i])
end
return true, monitors
end
-- coordinator communications
coordinator.coord_comms = function ()
function coordinator.coord_comms()
local self = {
reactor_struct_cache = nil
}

41
coordinator/renderer.lua Normal file
View File

@@ -0,0 +1,41 @@
local log = require("scada-common.log")
local util = require("scada-common.util")
local renderer = {}
local engine = {
monitors = nil,
dmesg_window = nil
}
---@param monitors monitors_struct
function renderer.set_displays(monitors)
engine.monitors = monitors
end
function renderer.reset()
-- reset primary monitor
engine.monitors.primary.setTextScale(0.5)
engine.monitors.primary.setTextColor(colors.white)
engine.monitors.primary.setBackgroundColor(colors.black)
engine.monitors.primary.clear()
engine.monitors.primary.setCursorPos(1, 1)
-- reset unit displays
for _, monitor in pairs(engine.monitors.unit_displays) do
monitor.setTextScale(0.5)
monitor.setTextColor(colors.white)
monitor.setBackgroundColor(colors.black)
monitor.clear()
monitor.setCursorPos(1, 1)
end
end
function renderer.init_dmesg()
local disp_x, disp_y = engine.monitors.primary.getSize()
engine.dmesg_window = window.create(engine.monitors.primary, 1, 1, disp_x, disp_y)
log.direct_dmesg(engine.dmesg_window)
end
return renderer

View File

@@ -10,6 +10,7 @@ local util = require("scada-common.util")
local config = require("coordinator.config")
local coordinator = require("coordinator.coordinator")
local renderer = require("coordinator.renderer")
local COORDINATOR_VERSION = "alpha-v0.1.2"
@@ -18,7 +19,7 @@ local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts
log.init("/log.txt", log.MODE.APPEND)
log.init(config.LOG_PATH, config.LOG_MODE)
log.info("========================================")
log.info("BOOTING coordinator.startup " .. COORDINATOR_VERSION)
@@ -28,10 +29,31 @@ println(">> SCADA Coordinator " .. COORDINATOR_VERSION .. " <<")
-- mount connected devices
ppm.mount_all()
local modem = ppm.get_wireless_modem()
-- we need a modem
if modem == nil then
println("please connect a wireless modem")
-- setup monitors
local configured, monitors = coordinator.configure_monitors(config.NUM_UNITS)
if not configured then
println("boot> monitor setup failed")
log.fatal("monitor configuration failed")
return
end
log.info("monitors ready, dmesg input incoming...")
-- init renderer
renderer.set_displays(monitors)
renderer.reset()
renderer.init_dmesg()
log.dmesg("displays connected and reset", "GRAPHICS", colors.green)
log.dmesg("system start on " .. os.date("%c"), "SYSTEM", colors.cyan)
log.dmesg("starting " .. COORDINATOR_VERSION, "BOOT", colors.blue)
-- get the communications 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
log.dmesg("wireless modem connected", "COMMS", colors.purple)

View File

@@ -0,0 +1,45 @@
local completion = require("cc.completion")
local util = require("scada-common.util")
local print = util.print
local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts
local dialog = {}
function dialog.ask_y_n(question, default)
print(question)
if default == true then
print(" (Y/n)? ")
else
print(" (y/N)? ")
end
local response = read(nil, nil)
if response == "" then
return default
elseif response == "Y" or response == "y" then
return true
elseif response == "N" or response == "n" then
return false
else
return nil
end
end
function dialog.ask_options(options, cancel)
print("> ")
local response = read(nil, nil, function(text) return completion.choice(text, options) end)
if response == cancel then return false end
if util.table_contains(options, response) then
return response
else return nil end
end
return dialog