Merge pull request #422 from MikaylaFischler/145-graphical-configure-utilities

Pocket Configurator and Other Fixes
This commit is contained in:
Mikayla 2024-02-19 20:34:41 -05:00 committed by GitHub
commit 940f71aa35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 813 additions and 206 deletions

121
ccmsi.lua
View File

@ -18,7 +18,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local function println(message) print(tostring(message)) end local function println(message) print(tostring(message)) end
local function print(message) term.write(tostring(message)) end local function print(message) term.write(tostring(message)) end
local CCMSI_VERSION = "v1.12b" local CCMSI_VERSION = "v1.13"
local install_dir = "/.install-cache" local install_dir = "/.install-cache"
local manifest_path = "https://mikaylafischler.github.io/cc-mek-scada/manifests/" local manifest_path = "https://mikaylafischler.github.io/cc-mek-scada/manifests/"
@ -26,7 +26,7 @@ local repo_path = "http://raw.githubusercontent.com/MikaylaFischler/cc-mek-scada
local opts = { ... } local opts = { ... }
local mode, app, target local mode, app, target
local install_manifest = manifest_path .. "main/install_manifest.json" local install_manifest = manifest_path.."main/install_manifest.json"
local function red() term.setTextColor(colors.red) end local function red() term.setTextColor(colors.red) end
local function orange() term.setTextColor(colors.orange) end local function orange() term.setTextColor(colors.orange) end
@ -59,17 +59,17 @@ local function ask_y_n(question, default)
end end
-- print out a white + blue text message -- print out a white + blue text message
local function pkg_message(message, package) white();print(message .. " ");blue();println(package);white() end local function pkg_message(message, package) white();print(message.." ");blue();println(package);white() end
-- indicate actions to be taken based on package differences for installs/updates -- indicate actions to be taken based on package differences for installs/updates
local function show_pkg_change(name, v) local function show_pkg_change(name, v)
if v.v_local ~= nil then if v.v_local ~= nil then
if v.v_local ~= v.v_remote then if v.v_local ~= v.v_remote then
print("[" .. name .. "] updating ");blue();print(v.v_local);white();print(" \xbb ");blue();println(v.v_remote);white() print("["..name.."] updating ");blue();print(v.v_local);white();print(" \xbb ");blue();println(v.v_remote);white()
elseif mode == "install" then elseif mode == "install" then
pkg_message("[" .. name .. "] reinstalling", v.v_local) pkg_message("["..name.."] reinstalling", v.v_local)
end end
else pkg_message("[" .. name .. "] new install of", v.v_remote) end else pkg_message("["..name.."] new install of", v.v_remote) end
return v.v_local ~= v.v_remote return v.v_local ~= v.v_remote
end end
@ -90,7 +90,7 @@ local function get_remote_manifest()
local response, error = http.get(install_manifest) local response, error = http.get(install_manifest)
if response == nil then if response == nil then
orange();println("Failed to get installation manifest from GitHub, cannot update or install.") orange();println("Failed to get installation manifest from GitHub, cannot update or install.")
red();println("HTTP error: " .. error);white() red();println("HTTP error: "..error);white()
return false, {} return false, {}
end end
@ -155,13 +155,13 @@ local function _clean_dir(dir, tree)
if tree == nil then tree = {} end if tree == nil then tree = {} end
local ls = fs.list(dir) local ls = fs.list(dir)
for _, val in pairs(ls) do for _, val in pairs(ls) do
local path = dir .. "/" .. val local path = dir.."/"..val
if fs.isDir(path) then if fs.isDir(path) then
_clean_dir(path, tree[val]) _clean_dir(path, tree[val])
if #fs.list(path) == 0 then fs.delete(path);println("deleted " .. path) end if #fs.list(path) == 0 then fs.delete(path);println("deleted "..path) end
elseif (not _in_array(val, tree)) and (val ~= "config.lua" ) then ---@fixme remove condition after migration to settings files elseif (not _in_array(val, tree)) and (val ~= "config.lua" ) then
fs.delete(path) fs.delete(path)
println("deleted " .. path) println("deleted "..path)
end end
end end
end end
@ -177,13 +177,13 @@ local function clean(manifest)
local ls = fs.list("/") local ls = fs.list("/")
for _, val in pairs(ls) do for _, val in pairs(ls) do
if fs.isDriveRoot(val) then if fs.isDriveRoot(val) then
yellow();println("skipped mount '" .. val .. "'") yellow();println("skipped mount '"..val.."'")
elseif fs.isDir(val) then elseif fs.isDir(val) then
if tree[val] ~= nil then lgray();_clean_dir("/" .. val, tree[val]) if tree[val] ~= nil then lgray();_clean_dir("/"..val, tree[val])
else white(); if ask_y_n("delete the unused directory '" .. val .. "'") then lgray();_clean_dir("/" .. val) end end else white(); if ask_y_n("delete the unused directory '"..val.."'") then lgray();_clean_dir("/"..val) end end
if #fs.list(val) == 0 then fs.delete(val);lgray();println("deleted empty directory '" .. val .. "'") end if #fs.list(val) == 0 then fs.delete(val);lgray();println("deleted empty directory '"..val.."'") end
elseif not _in_array(val, tree) and (string.find(val, ".settings") == nil) then elseif not _in_array(val, tree) and (string.find(val, ".settings") == nil) then
white();if ask_y_n("delete the unused file '" .. val .. "'") then fs.delete(val);lgray();println("deleted " .. val) end white();if ask_y_n("delete the unused file '"..val.."'") then fs.delete(val);lgray();println("deleted "..val) end
end end
end end
@ -192,7 +192,7 @@ end
-- get and validate command line options -- get and validate command line options
println("-- CC Mekanism SCADA Installer " .. CCMSI_VERSION .. " --") println("-- CC Mekanism SCADA Installer "..CCMSI_VERSION.." --")
if #opts == 0 or opts[1] == "help" then if #opts == 0 or opts[1] == "help" then
println("usage: ccmsi <mode> <app> <branch>") println("usage: ccmsi <mode> <app> <branch>")
@ -202,8 +202,8 @@ if #opts == 0 or opts[1] == "help" then
yellow() yellow()
println(" ccmsi check <branch> for target") println(" ccmsi check <branch> for target")
lgray() lgray()
println(" install - fresh install, overwrites config.lua") println(" install - fresh install")
println(" update - update files EXCEPT for config.lua") println(" update - update files")
println(" uninstall - delete files INCLUDING config/logs") println(" uninstall - delete files INCLUDING config/logs")
white();println("<app>");lgray() white();println("<app>");lgray()
println(" reactor-plc - reactor PLC firmware") println(" reactor-plc - reactor PLC firmware")
@ -239,8 +239,8 @@ else
end end
-- set paths -- set paths
install_manifest = manifest_path .. target .. "/install_manifest.json" install_manifest = manifest_path..target.."/install_manifest.json"
repo_path = repo_path .. target .. "/" repo_path = repo_path..target.."/"
end end
-- run selected mode -- run selected mode
@ -260,7 +260,7 @@ if mode == "check" then
-- list all versions -- list all versions
for key, value in pairs(manifest.versions) do for key, value in pairs(manifest.versions) do
term.setTextColor(colors.purple) term.setTextColor(colors.purple)
print(string.format("%-14s", "[" .. key .. "]")) print(string.format("%-14s", "["..key.."]"))
if key == "installer" or (local_ok and (local_manifest.versions[key] ~= nil)) then if key == "installer" or (local_ok and (local_manifest.versions[key] ~= nil)) then
blue();print(local_manifest.versions[key]) blue();print(local_manifest.versions[key])
if value ~= local_manifest.versions[key] then if value ~= local_manifest.versions[key] then
@ -315,10 +315,10 @@ elseif mode == "install" or mode == "update" then
if not update_installer then yellow();println("A different version of the installer is available, it is recommended to update to it.");white() end if not update_installer then yellow();println("A different version of the installer is available, it is recommended to update to it.");white() end
if update_installer or ask_y_n("Would you like to update now") then if update_installer or ask_y_n("Would you like to update now") then
lgray();println("GET ccmsi.lua") lgray();println("GET ccmsi.lua")
local dl, err = http.get(repo_path .. "ccmsi.lua") local dl, err = http.get(repo_path.."ccmsi.lua")
if dl == nil then if dl == nil then
red();println("HTTP Error " .. err) red();println("HTTP Error "..err)
println("Installer download failed.");white() println("Installer download failed.");white()
else else
local handle = fs.open(debug.getinfo(1, "S").source:sub(2), "w") -- this file, regardless of name or location local handle = fs.open(debug.getinfo(1, "S").source:sub(2), "w") -- this file, regardless of name or location
@ -342,13 +342,8 @@ elseif mode == "install" or mode == "update" then
ver.lockbox.v_remote = manifest.versions.lockbox ver.lockbox.v_remote = manifest.versions.lockbox
green() green()
if mode == "install" then if mode == "install" then print("Installing ") else print("Updating ") end
println("Installing " .. app .. " files...") println(app.." files...");white()
elseif mode == "update" then
if app == "pocket" then println("Updating " .. app .. " files... (keeping old config.lua)")
else println("Updating " .. app .. " files...") end
end
white()
ver.boot.changed = show_pkg_change("bootldr", ver.boot) ver.boot.changed = show_pkg_change("bootldr", ver.boot)
ver.common.changed = show_pkg_change("common", ver.common) ver.common.changed = show_pkg_change("common", ver.common)
@ -374,7 +369,6 @@ elseif mode == "install" or mode == "update" then
local file_list = manifest.files local file_list = manifest.files
local size_list = manifest.sizes local size_list = manifest.sizes
local dependencies = manifest.depends[app] local dependencies = manifest.depends[app]
local config_file = app .. "/config.lua"
table.insert(dependencies, app) table.insert(dependencies, app)
@ -421,15 +415,15 @@ elseif mode == "install" or mode == "update" then
local files = file_list[dependency] local files = file_list[dependency]
for _, file in pairs(files) do for _, file in pairs(files) do
println("GET " .. file) println("GET "..file)
local dl, err = http.get(repo_path .. file) local dl, err = http.get(repo_path..file)
if dl == nil then if dl == nil then
red();println("HTTP Error " .. err) red();println("HTTP Error "..err)
success = false success = false
break break
else else
local handle = fs.open(install_dir .. "/" .. file, "w") local handle = fs.open(install_dir.."/"..file, "w")
handle.write(dl.readAll()) handle.write(dl.readAll())
handle.close() handle.close()
end end
@ -448,11 +442,9 @@ elseif mode == "install" or mode == "update" then
local files = file_list[dependency] local files = file_list[dependency]
for _, file in pairs(files) do for _, file in pairs(files) do
if mode == "install" or file ~= config_file then local temp_file = install_dir.."/"..file
local temp_file = install_dir .. "/" .. file if fs.exists(file) then fs.delete(file) end
if fs.exists(file) then fs.delete(file) end fs.move(temp_file, file)
fs.move(temp_file, file)
end
end end
end end
end end
@ -485,19 +477,17 @@ elseif mode == "install" or mode == "update" then
local files = file_list[dependency] local files = file_list[dependency]
for _, file in pairs(files) do for _, file in pairs(files) do
if mode == "install" or file ~= config_file then println("GET "..file)
println("GET " .. file) local dl, err = http.get(repo_path..file)
local dl, err = http.get(repo_path .. file)
if dl == nil then if dl == nil then
red();println("HTTP Error " .. err) red();println("HTTP Error "..err)
success = false success = false
break break
else else
local handle = fs.open("/" .. file, "w") local handle = fs.open("/"..file, "w")
handle.write(dl.readAll()) handle.write(dl.readAll())
handle.close() handle.close()
end
end end
end end
end end
@ -527,11 +517,11 @@ elseif mode == "uninstall" then
end end
if manifest.versions[app] == nil then if manifest.versions[app] == nil then
red();println("Error: '" .. app .. "' is not installed.") red();println("Error: '"..app.."' is not installed.")
return return
end end
orange();println("Uninstalling all " .. app .. " files...") orange();println("Uninstalling all "..app.." files...")
-- ask for confirmation -- ask for confirmation
if not ask_y_n("Continue", false) then return end if not ask_y_n("Continue", false) then return end
@ -546,16 +536,16 @@ elseif mode == "uninstall" then
-- delete log file -- delete log file
local log_deleted = false local log_deleted = false
local settings_file = app .. ".settings" local settings_file = app..".settings"
local legacy_config_file = app .. "/config.lua" local legacy_config_file = app.."/config.lua"
lgray() lgray()
if fs.exists(legacy_config_file) then if fs.exists(legacy_config_file) then
log_deleted = pcall(function () log_deleted = pcall(function ()
local config = require(app .. ".config") local config = require(app..".config")
if fs.exists(config.LOG_PATH) then if fs.exists(config.LOG_PATH) then
fs.delete(config.LOG_PATH) fs.delete(config.LOG_PATH)
println("deleted log file " .. config.LOG_PATH) println("deleted log file "..config.LOG_PATH)
end end
end) end)
elseif fs.exists(settings_file) and settings.load(settings_file) then elseif fs.exists(settings_file) and settings.load(settings_file) then
@ -563,7 +553,7 @@ elseif mode == "uninstall" then
if log ~= nil and fs.exists(log) then if log ~= nil and fs.exists(log) then
log_deleted = true log_deleted = true
fs.delete(log) fs.delete(log)
println("deleted log file " .. log) println("deleted log file "..log)
end end
end end
@ -577,7 +567,7 @@ elseif mode == "uninstall" then
for _, dependency in pairs(dependencies) do for _, dependency in pairs(dependencies) do
local files = file_list[dependency] local files = file_list[dependency]
for _, file in pairs(files) do for _, file in pairs(files) do
if fs.exists(file) then fs.delete(file);println("deleted " .. file) end if fs.exists(file) then fs.delete(file);println("deleted "..file) end
end end
local folder = files[1] local folder = files[1]
@ -588,13 +578,16 @@ elseif mode == "uninstall" then
if fs.isDir(folder) then if fs.isDir(folder) then
fs.delete(folder) fs.delete(folder)
println("deleted directory " .. folder) println("deleted directory "..folder)
end end
end end
if fs.exists(legacy_config_file) then
fs.delete(legacy_config_file);println("deleted "..legacy_config_file)
end
if fs.exists(settings_file) then if fs.exists(settings_file) then
fs.delete(settings_file) fs.delete(settings_file);println("deleted "..settings_file)
println("deleted " .. settings_file)
end end
fs.delete("install_manifest.json") fs.delete("install_manifest.json")

View File

@ -1,15 +1,10 @@
print("CONFIGURE> SCANNING FOR CONFIGURATOR...") print("CONFIGURE> SCANNING FOR CONFIGURATOR...")
if fs.exists("reactor-plc/configure.lua") then if fs.exists("reactor-plc/configure.lua") then require("reactor-plc.configure").configure()
require("reactor-plc.configure").configure() elseif fs.exists("rtu/configure.lua") then require("rtu.configure").configure()
elseif fs.exists("rtu/configure.lua") then elseif fs.exists("supervisor/configure.lua") then require("supervisor.configure").configure()
require("rtu.configure").configure() elseif fs.exists("coordinator/configure.lua") then require("coordinator.configure").configure()
elseif fs.exists("supervisor/configure.lua") then elseif fs.exists("pocket/configure.lua") then require("pocket.configure").configure()
require("supervisor.configure").configure()
elseif fs.exists("coordinator/configure.lua") then
require("coordinator.configure").configure()
elseif fs.exists("pocket/startup.lua") then
print("CONFIGURE> pocket configurator not yet implemented (use 'edit pocket/config.lua' to configure)")
else else
print("CONFIGURE> NO CONFIGURATOR FOUND") print("CONFIGURE> NO CONFIGURATOR FOUND")
print("CONFIGURE> EXIT") print("CONFIGURE> EXIT")

View File

@ -347,7 +347,7 @@ local function config_view(display)
if not tool_ctl.has_config then tool_ctl.view_cfg.disable() end if not tool_ctl.has_config then tool_ctl.view_cfg.disable() end
PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg} PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg}
PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(6)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(9)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
--#region Network --#region Network
@ -453,20 +453,22 @@ local function config_view(display)
local function submit_auth() local function submit_auth()
local v = key.get_value() local v = key.get_value()
if string.len(v) == 0 or string.len(v) >= 8 then if string.len(v) == 0 or string.len(v) >= 8 then
-- prep supervisor connection screen
tool_ctl.sv_next.hide()
tool_ctl.sv_skip.disable()
tool_ctl.sv_skip.show()
tool_ctl.sv_conn_button.enable()
tool_ctl.sv_conn_status.set_value("")
tool_ctl.sv_conn_detail.set_value("")
tmp_cfg.AuthKey = key.get_value() tmp_cfg.AuthKey = key.get_value()
main_pane.set_value(3)
key_err.hide(true) key_err.hide(true)
-- init mac for supervisor connection -- init mac for supervisor connection
if string.len(v) >= 8 then network.init_mac(tmp_cfg.AuthKey) end if string.len(v) >= 8 then network.init_mac(tmp_cfg.AuthKey) end
-- prep supervisor connection screen main_pane.set_value(3)
tool_ctl.sv_conn_button.enable()
tool_ctl.sv_conn_status.set_value("")
tool_ctl.sv_conn_detail.set_value("")
tool_ctl.sv_next.hide()
tool_ctl.sv_skip.show()
tool_ctl.sv_skip.disable()
tcd.dispatch_unique(2, function () tool_ctl.sv_skip.enable() end) tcd.dispatch_unique(2, function () tool_ctl.sv_skip.enable() end)
else key_err.show() end else key_err.show() end
end end
@ -534,7 +536,7 @@ local function config_view(display)
TextBox{parent=fac_c_3,x=1,y=1,height=2,text="The following facility configuration was fetched from your supervisor computer."} TextBox{parent=fac_c_3,x=1,y=1,height=2,text="The following facility configuration was fetched from your supervisor computer."}
local fac_config_list = ListBox{parent=fac_c_3,x=1,y=4,height=9,width=51,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local fac_config_list = ListBox{parent=fac_c_3,x=1,y=4,height=9,width=49,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
PushButton{parent=fac_c_3,x=1,y=14,text="\x1b Back",callback=function()fac_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=fac_c_3,x=1,y=14,text="\x1b Back",callback=function()fac_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=fac_c_3,x=44,y=14,text="Next \x1a",callback=function()main_pane.set_value(4)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=fac_c_3,x=44,y=14,text="Next \x1a",callback=function()main_pane.set_value(4)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
@ -553,7 +555,7 @@ local function config_view(display)
TextBox{parent=mon_cfg,x=1,y=2,height=1,text=" Monitor Configuration",fg_bg=cpair(colors.black,colors.blue)} TextBox{parent=mon_cfg,x=1,y=2,height=1,text=" Monitor Configuration",fg_bg=cpair(colors.black,colors.blue)}
TextBox{parent=mon_c_1,x=1,y=1,height=5,text="Your configuration requires the following monitors. The main and flow monitors' heights are dependent on your unit count and cooling setup. If you manually entered the unit count, a * will be shown on potentially inaccurate calculations."} TextBox{parent=mon_c_1,x=1,y=1,height=5,text="Your configuration requires the following monitors. The main and flow monitors' heights are dependent on your unit count and cooling setup. If you manually entered the unit count, a * will be shown on potentially inaccurate calculations."}
local mon_reqs = ListBox{parent=mon_c_1,x=1,y=7,height=6,width=51,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local mon_reqs = ListBox{parent=mon_c_1,x=1,y=7,height=6,width=49,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
local function next_from_reqs() local function next_from_reqs()
-- unassign unit monitors above the unit count -- unassign unit monitors above the unit count
@ -569,7 +571,7 @@ local function config_view(display)
TextBox{parent=mon_c_2,x=1,y=1,height=5,text="Please configure your monitors below. You can go back to the prior page without losing progress to double check what you need. All of those monitors must be assigned before you can proceed."} TextBox{parent=mon_c_2,x=1,y=1,height=5,text="Please configure your monitors below. You can go back to the prior page without losing progress to double check what you need. All of those monitors must be assigned before you can proceed."}
local mon_list = ListBox{parent=mon_c_2,x=1,y=6,height=7,width=51,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local mon_list = ListBox{parent=mon_c_2,x=1,y=6,height=7,width=49,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
local assign_err = TextBox{parent=mon_c_2,x=8,y=14,height=1,width=35,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} local assign_err = TextBox{parent=mon_c_2,x=8,y=14,height=1,width=35,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
@ -796,7 +798,7 @@ local function config_view(display)
TextBox{parent=summary,x=1,y=2,height=1,text=" Summary",fg_bg=cpair(colors.black,colors.green)} TextBox{parent=summary,x=1,y=2,height=1,text=" Summary",fg_bg=cpair(colors.black,colors.green)}
local setting_list = ListBox{parent=sum_c_1,x=1,y=1,height=12,width=51,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local setting_list = ListBox{parent=sum_c_1,x=1,y=1,height=12,width=49,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
local function back_from_summary() local function back_from_summary()
if tool_ctl.viewing_config or tool_ctl.importing_legacy then if tool_ctl.viewing_config or tool_ctl.importing_legacy then
@ -818,7 +820,7 @@ local function config_view(display)
local function save_and_continue() local function save_and_continue()
for k, v in pairs(tmp_cfg) do settings.set(k, v) end for k, v in pairs(tmp_cfg) do settings.set(k, v) end
if settings.save("coordinator.settings") then if settings.save("/coordinator.settings") then
load_settings(settings_cfg, true) load_settings(settings_cfg, true)
load_settings(ini_cfg) load_settings(ini_cfg)
@ -895,7 +897,7 @@ local function config_view(display)
TextBox{parent=changelog,x=1,y=2,height=1,text=" Config Change Log",fg_bg=bw_fg_bg} TextBox{parent=changelog,x=1,y=2,height=1,text=" Config Change Log",fg_bg=bw_fg_bg}
local c_log = ListBox{parent=cl,x=1,y=1,height=12,width=51,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local c_log = ListBox{parent=cl,x=1,y=1,height=12,width=49,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
for _, change in ipairs(changes) do for _, change in ipairs(changes) do
TextBox{parent=c_log,text=change[1],height=1,fg_bg=bw_fg_bg} TextBox{parent=c_log,text=change[1],height=1,fg_bg=bw_fg_bg}

View File

@ -121,8 +121,11 @@ function coordinator.load_config()
monitors.primary = ppm.get_periph(config.MainDisplay) monitors.primary = ppm.get_periph(config.MainDisplay)
monitors.primary_name = config.MainDisplay monitors.primary_name = config.MainDisplay
monitors.primary.setTextScale(0.5)
w, _ = ppm.monitor_block_size(monitors.primary.getSize()) w, _ = ppm.monitor_block_size(monitors.primary.getSize())
if w ~= 8 then return 2, "Main monitor width is incorrect." end 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 config.DisableFlowView then
if not util.table_contains(names, config.FlowDisplay) then if not util.table_contains(names, config.FlowDisplay) then
@ -132,8 +135,11 @@ function coordinator.load_config()
monitors.flow = ppm.get_periph(config.FlowDisplay) monitors.flow = ppm.get_periph(config.FlowDisplay)
monitors.flow_name = config.FlowDisplay monitors.flow_name = config.FlowDisplay
monitors.flow.setTextScale(0.5)
w, _ = ppm.monitor_block_size(monitors.flow.getSize()) w, _ = ppm.monitor_block_size(monitors.flow.getSize())
if w ~= 8 then return 2, "Flow monitor width is incorrect." end if w ~= 8 then
return 2, util.c("Flow monitor width is incorrect (was ", w, ", must be 8).")
end
end end
for i = 1, config.UnitCount do for i = 1, config.UnitCount do
@ -145,8 +151,11 @@ function coordinator.load_config()
monitors.unit_displays[i] = ppm.get_periph(display) monitors.unit_displays[i] = ppm.get_periph(display)
monitors.unit_name_map[i] = 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()) w, h = ppm.monitor_block_size(monitors.unit_displays[i].getSize())
if w ~= 4 or h ~= 4 then return 2, "Unit " .. i .. " monitor size is incorrect." end 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 end
else return 2, "Monitor configuration invalid." end else return 2, "Monitor configuration invalid." end
end end

View File

@ -22,7 +22,7 @@ local sounder = require("coordinator.sounder")
local apisessions = require("coordinator.session.apisessions") local apisessions = require("coordinator.session.apisessions")
local COORDINATOR_VERSION = "v1.2.0" local COORDINATOR_VERSION = "v1.2.1"
local println = util.println local println = util.println
local println_ts = util.println_ts local println_ts = util.println_ts
@ -79,6 +79,9 @@ local function main()
-- system startup -- system startup
---------------------------------------- ----------------------------------------
-- re-mount devices now that logging is ready
ppm.mount_all()
-- report versions/init fp PSIL -- report versions/init fp PSIL
iocontrol.init_fp(COORDINATOR_VERSION, comms.version) iocontrol.init_fp(COORDINATOR_VERSION, comms.version)

View File

@ -1,27 +0,0 @@
local config = {}
-- supervisor comms channel
config.SVR_CHANNEL = 16240
-- coordinator comms channel
config.CRD_CHANNEL = 16243
-- pocket comms channel
config.PKT_CHANNEL = 16244
-- max trusted modem message distance (0 to disable check)
config.TRUSTED_RANGE = 0
-- time in seconds (>= 2) before assuming a remote device is no longer active
config.COMMS_TIMEOUT = 5
-- facility authentication key (do NOT use one of your passwords)
-- this enables verifying that messages are authentic
-- all devices on the same network must use the same key
-- config.AUTH_KEY = "SCADAfacility123"
-- 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
-- true to log verbose debug messages
config.LOG_DEBUG = false
return config

578
pocket/configure.lua Normal file
View File

@ -0,0 +1,578 @@
--
-- Configuration GUI
--
local log = require("scada-common.log")
local tcd = require("scada-common.tcd")
local util = require("scada-common.util")
local core = require("graphics.core")
local DisplayBox = require("graphics.elements.displaybox")
local Div = require("graphics.elements.div")
local ListBox = require("graphics.elements.listbox")
local MultiPane = require("graphics.elements.multipane")
local TextBox = require("graphics.elements.textbox")
local CheckBox = require("graphics.elements.controls.checkbox")
local PushButton = require("graphics.elements.controls.push_button")
local RadioButton = require("graphics.elements.controls.radio_button")
local NumberField = require("graphics.elements.form.number_field")
local TextField = require("graphics.elements.form.text_field")
local println = util.println
local tri = util.trinary
local cpair = core.cpair
local LEFT = core.ALIGN.LEFT
local CENTER = core.ALIGN.CENTER
local RIGHT = core.ALIGN.RIGHT
-- changes to the config data/format to let the user know
local changes = {}
---@class pkt_configurator
local configurator = {}
local style = {}
style.root = cpair(colors.black, colors.lightGray)
style.header = cpair(colors.white, colors.gray)
style.colors = {
{ c = colors.red, hex = 0xdf4949 },
{ c = colors.orange, hex = 0xffb659 },
{ c = colors.yellow, hex = 0xfffc79 },
{ c = colors.lime, hex = 0x80ff80 },
{ c = colors.green, hex = 0x4aee8a },
{ c = colors.cyan, hex = 0x34bac8 },
{ c = colors.lightBlue, hex = 0x6cc0f2 },
{ c = colors.blue, hex = 0x0096ff },
{ c = colors.purple, hex = 0xb156ee },
{ c = colors.pink, hex = 0xf26ba2 },
{ c = colors.magenta, hex = 0xf9488a },
{ c = colors.lightGray, hex = 0xcacaca },
{ c = colors.gray, hex = 0x575757 }
}
local bw_fg_bg = cpair(colors.black, colors.white)
local g_lg_fg_bg = cpair(colors.gray, colors.lightGray)
local nav_fg_bg = bw_fg_bg
local btn_act_fg_bg = cpair(colors.white, colors.gray)
local dis_fg_bg = cpair(colors.lightGray,colors.white)
local tool_ctl = {
ask_config = false,
has_config = false,
viewing_config = false,
importing_legacy = false,
view_cfg = nil, ---@type graphics_element
settings_apply = nil, ---@type graphics_element
set_networked = nil, ---@type function
bundled_emcool = nil, ---@type function
gen_summary = nil, ---@type function
show_current_cfg = nil, ---@type function
load_legacy = nil, ---@type function
show_auth_key = nil, ---@type function
show_key_btn = nil, ---@type graphics_element
auth_key_textbox = nil, ---@type graphics_element
auth_key_value = ""
}
---@class pkt_config
local tmp_cfg = {
SVR_Channel = nil, ---@type integer
CRD_Channel = nil, ---@type integer
PKT_Channel = nil, ---@type integer
ConnTimeout = nil, ---@type number
TrustedRange = nil, ---@type number
AuthKey = nil, ---@type string|nil
LogMode = 0,
LogPath = "",
LogDebug = false,
}
---@class pkt_config
local ini_cfg = {}
---@class pkt_config
local settings_cfg = {}
-- all settings fields, their nice names, and their default values
local fields = {
{ "SVR_Channel", "SVR Channel", 16240 },
{ "CRD_Channel", "CRD Channel", 16243 },
{ "PKT_Channel", "PKT Channel", 16244 },
{ "ConnTimeout", "Connection Timeout", 5 },
{ "TrustedRange", "Trusted Range", 0 },
{ "AuthKey", "Facility Auth Key" , ""},
{ "LogMode", "Log Mode", log.MODE.APPEND },
{ "LogPath", "Log Path", "/log.txt" },
{ "LogDebug","Log Debug Messages", false }
}
-- load data from the settings file
---@param target pkt_config
---@param raw boolean? true to not use default values
local function load_settings(target, raw)
for _, v in pairs(fields) do settings.unset(v[1]) end
local loaded = settings.load("/pocket.settings")
for _, v in pairs(fields) do target[v[1]] = settings.get(v[1], tri(raw, nil, v[3])) end
return loaded
end
-- create the config view
---@param display graphics_element
local function config_view(display)
---@diagnostic disable-next-line: undefined-field
local function exit() os.queueEvent("terminate") end
TextBox{parent=display,y=1,text="Pocket Configurator",alignment=CENTER,height=1,fg_bg=style.header}
local root_pane_div = Div{parent=display,x=1,y=2}
local main_page = Div{parent=root_pane_div,x=1,y=1}
local net_cfg = Div{parent=root_pane_div,x=1,y=1}
local log_cfg = Div{parent=root_pane_div,x=1,y=1}
local summary = Div{parent=root_pane_div,x=1,y=1}
local changelog = Div{parent=root_pane_div,x=1,y=1}
local main_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes={main_page,net_cfg,log_cfg,summary,changelog}}
-- Main Page
local y_start = 7
TextBox{parent=main_page,x=2,y=2,height=4,text="Welcome to the Pocket configurator! Please select one of the following options."}
if tool_ctl.ask_config then
TextBox{parent=main_page,x=2,y=y_start,height=4,width=49,text="Please configure before starting up.",fg_bg=cpair(colors.red,colors.lightGray)}
y_start = y_start + 3
end
local function view_config()
tool_ctl.viewing_config = true
tool_ctl.gen_summary(settings_cfg)
tool_ctl.settings_apply.hide(true)
main_pane.set_value(4)
end
if fs.exists("/pocket/config.lua") then
PushButton{parent=main_page,x=2,y=y_start,min_width=22,text="Import Legacy Config",callback=function()tool_ctl.load_legacy()end,fg_bg=cpair(colors.black,colors.cyan),active_fg_bg=btn_act_fg_bg}
y_start = y_start + 2
end
PushButton{parent=main_page,x=2,y=y_start,min_width=18,text="Configure Device",callback=function()main_pane.set_value(2)end,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=btn_act_fg_bg}
tool_ctl.view_cfg = PushButton{parent=main_page,x=2,y=y_start+2,min_width=20,text="View Configuration",callback=view_config,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=btn_act_fg_bg,dis_fg_bg=dis_fg_bg}
if not tool_ctl.has_config then tool_ctl.view_cfg.disable() end
PushButton{parent=main_page,x=2,y=18,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg}
PushButton{parent=main_page,x=14,y=18,min_width=12,text="Change Log",callback=function()main_pane.set_value(5)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
--#region Network
local net_c_1 = Div{parent=net_cfg,x=2,y=4,width=24}
local net_c_2 = Div{parent=net_cfg,x=2,y=4,width=24}
local net_c_3 = Div{parent=net_cfg,x=2,y=4,width=24}
local net_c_4 = Div{parent=net_cfg,x=2,y=4,width=24}
local net_pane = MultiPane{parent=net_cfg,x=1,y=4,panes={net_c_1,net_c_2,net_c_3,net_c_4}}
TextBox{parent=net_cfg,x=1,y=2,height=1,text=" Network Configuration",fg_bg=cpair(colors.black,colors.lightBlue)}
TextBox{parent=net_c_1,x=1,y=1,height=1,text="Set network channels."}
TextBox{parent=net_c_1,x=1,y=3,height=4,text="Each of the named channels must be the same within a particular SCADA network.",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_1,x=1,y=8,height=1,width=18,text="Supervisor Channel"}
local svr_chan = NumberField{parent=net_c_1,x=1,y=9,width=7,default=ini_cfg.SVR_Channel,min=1,max=65535,fg_bg=bw_fg_bg}
TextBox{parent=net_c_1,x=9,y=9,height=4,text="[SVR_CHANNEL]",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_1,x=1,y=10,height=1,width=19,text="Coordinator Channel"}
local crd_chan = NumberField{parent=net_c_1,x=1,y=11,width=7,default=ini_cfg.CRD_Channel,min=1,max=65535,fg_bg=bw_fg_bg}
TextBox{parent=net_c_1,x=9,y=11,height=4,text="[CRD_CHANNEL]",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_1,x=1,y=12,height=1,width=14,text="Pocket Channel"}
local pkt_chan = NumberField{parent=net_c_1,x=1,y=13,width=7,default=ini_cfg.PKT_Channel,min=1,max=65535,fg_bg=bw_fg_bg}
TextBox{parent=net_c_1,x=9,y=13,height=4,text="[PKT_CHANNEL]",fg_bg=g_lg_fg_bg}
local chan_err = TextBox{parent=net_c_1,x=1,y=14,height=1,width=24,text="Please set all channels.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
local function submit_channels()
local svr_c, crd_c, pkt_c = tonumber(svr_chan.get_value()), tonumber(crd_chan.get_value()), tonumber(pkt_chan.get_value())
if svr_c ~= nil and crd_c ~= nil and pkt_c ~= nil then
tmp_cfg.SVR_Channel, tmp_cfg.CRD_Channel, tmp_cfg.PKT_Channel = svr_c, crd_c, pkt_c
net_pane.set_value(2)
chan_err.hide(true)
else chan_err.show() end
end
PushButton{parent=net_c_1,x=1,y=15,text="\x1b Back",callback=function()main_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=net_c_1,x=19,y=15,text="Next \x1a",callback=submit_channels,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
TextBox{parent=net_c_2,x=1,y=1,height=1,text="Set connection timeout."}
TextBox{parent=net_c_2,x=1,y=3,height=7,text="You generally should not need to modify this. On slow servers, you can try to increase this to make the system wait longer before assuming a disconnection.",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_2,x=1,y=11,height=1,width=19,text="Connection Timeout"}
local timeout = NumberField{parent=net_c_2,x=1,y=12,width=7,default=ini_cfg.ConnTimeout,min=2,max=25,max_chars=6,max_frac_digits=2,allow_decimal=true,fg_bg=bw_fg_bg}
TextBox{parent=net_c_2,x=9,y=12,height=2,text="seconds\n(default 5)",fg_bg=g_lg_fg_bg}
local ct_err = TextBox{parent=net_c_2,x=1,y=14,height=1,width=24,text="Please set timeout.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
local function submit_timeouts()
local timeout_val = tonumber(timeout.get_value())
if timeout_val ~= nil then
tmp_cfg.ConnTimeout = timeout_val
net_pane.set_value(3)
ct_err.hide(true)
else ct_err.show() end
end
PushButton{parent=net_c_2,x=1,y=15,text="\x1b Back",callback=function()net_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=net_c_2,x=19,y=15,text="Next \x1a",callback=submit_timeouts,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
TextBox{parent=net_c_3,x=1,y=1,height=1,text="Set the trusted range."}
TextBox{parent=net_c_3,x=1,y=3,height=4,text="Setting this to a value larger than 0 prevents connections with devices that many blocks away.",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_3,x=1,y=8,height=4,text="This is optional. You can disable this functionality by setting the value to 0.",fg_bg=g_lg_fg_bg}
local range = NumberField{parent=net_c_3,x=1,y=13,width=10,default=ini_cfg.TrustedRange,min=0,max_chars=20,allow_decimal=true,fg_bg=bw_fg_bg}
local tr_err = TextBox{parent=net_c_3,x=1,y=14,height=1,width=24,text="Set the trusted range.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
local function submit_tr()
local range_val = tonumber(range.get_value())
if range_val ~= nil then
tmp_cfg.TrustedRange = range_val
net_pane.set_value(4)
tr_err.hide(true)
else tr_err.show() end
end
PushButton{parent=net_c_3,x=1,y=15,text="\x1b Back",callback=function()net_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=net_c_3,x=19,y=15,text="Next \x1a",callback=submit_tr,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
TextBox{parent=net_c_4,x=1,y=1,height=4,text="Optionally, set the facility authentication key. Do NOT use one of your passwords."}
TextBox{parent=net_c_4,x=1,y=6,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers.",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_4,x=1,y=12,height=1,text="Facility Auth Key"}
local key, _, censor = TextField{parent=net_c_4,x=1,y=13,max_len=64,value=ini_cfg.AuthKey,width=24,height=1,fg_bg=bw_fg_bg}
local function censor_key(enable) censor(util.trinary(enable, "*", nil)) end
-- declare back first so tabbing makes sense visually
PushButton{parent=net_c_4,x=1,y=15,text="\x1b Back",callback=function()net_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
local hide_key = CheckBox{parent=net_c_4,x=8,y=15,label="Hide Key",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key}
hide_key.set_value(true)
censor_key(true)
local key_err = TextBox{parent=net_c_4,x=1,y=14,height=1,width=24,text="Length must be > 7.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
local function submit_auth()
local v = key.get_value()
if string.len(v) == 0 or string.len(v) >= 8 then
tmp_cfg.AuthKey = key.get_value()
main_pane.set_value(3)
key_err.hide(true)
else key_err.show() end
end
PushButton{parent=net_c_4,x=19,y=15,text="Next \x1a",callback=submit_auth,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
--#endregion
--#region Logging
local log_c_1 = Div{parent=log_cfg,x=2,y=4,width=24}
TextBox{parent=log_cfg,x=1,y=2,height=1,text=" Logging Configuration",fg_bg=cpair(colors.black,colors.pink)}
TextBox{parent=log_c_1,x=1,y=1,height=1,text="Configure logging below."}
TextBox{parent=log_c_1,x=1,y=3,height=1,text="Log File Mode"}
local mode = RadioButton{parent=log_c_1,x=1,y=4,default=ini_cfg.LogMode+1,options={"Append on Startup","Replace on Startup"},callback=function()end,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.pink}
TextBox{parent=log_c_1,x=1,y=7,height=1,text="Log File Path"}
local path = TextField{parent=log_c_1,x=1,y=8,width=24,height=1,value=ini_cfg.LogPath,max_len=128,fg_bg=bw_fg_bg}
local en_dbg = CheckBox{parent=log_c_1,x=1,y=10,default=ini_cfg.LogDebug,label="Enable Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)}
TextBox{parent=log_c_1,x=3,y=11,height=4,text="This results in much larger log files. Use only as needed.",fg_bg=g_lg_fg_bg}
local path_err = TextBox{parent=log_c_1,x=1,y=14,height=1,width=24,text="Provide a log file path.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
local function submit_log()
if path.get_value() ~= "" then
path_err.hide(true)
tmp_cfg.LogMode = mode.get_value() - 1
tmp_cfg.LogPath = path.get_value()
tmp_cfg.LogDebug = en_dbg.get_value()
tool_ctl.gen_summary(tmp_cfg)
tool_ctl.viewing_config = false
tool_ctl.importing_legacy = false
tool_ctl.settings_apply.show()
main_pane.set_value(4)
else path_err.show() end
end
PushButton{parent=log_c_1,x=1,y=15,text="\x1b Back",callback=function()main_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=log_c_1,x=19,y=15,text="Next \x1a",callback=submit_log,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
--#endregion
--#region Summary and Saving
local sum_c_1 = Div{parent=summary,x=2,y=4,width=24}
local sum_c_2 = Div{parent=summary,x=2,y=4,width=24}
local sum_c_3 = Div{parent=summary,x=2,y=4,width=24}
local sum_c_4 = Div{parent=summary,x=2,y=4,width=24}
local sum_pane = MultiPane{parent=summary,x=1,y=4,panes={sum_c_1,sum_c_2,sum_c_3,sum_c_4}}
TextBox{parent=summary,x=1,y=2,height=1,text=" Summary",fg_bg=cpair(colors.black,colors.green)}
local setting_list = ListBox{parent=sum_c_1,x=1,y=1,height=11,width=24,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
local function back_from_summary()
if tool_ctl.viewing_config or tool_ctl.importing_legacy then
main_pane.set_value(1)
tool_ctl.viewing_config = false
tool_ctl.importing_legacy = false
tool_ctl.settings_apply.show()
else
main_pane.set_value(3)
end
end
---@param element graphics_element
---@param data any
local function try_set(element, data)
if data ~= nil then element.set_value(data) end
end
local function save_and_continue()
for k, v in pairs(tmp_cfg) do settings.set(k, v) end
if settings.save("/pocket.settings") then
load_settings(settings_cfg, true)
load_settings(ini_cfg)
try_set(svr_chan, ini_cfg.SVR_Channel)
try_set(crd_chan, ini_cfg.CRD_Channel)
try_set(pkt_chan, ini_cfg.PKT_Channel)
try_set(timeout, ini_cfg.ConnTimeout)
try_set(range, ini_cfg.TrustedRange)
try_set(key, ini_cfg.AuthKey)
try_set(mode, ini_cfg.LogMode)
try_set(path, ini_cfg.LogPath)
try_set(en_dbg, ini_cfg.LogDebug)
tool_ctl.view_cfg.enable()
if tool_ctl.importing_legacy then
tool_ctl.importing_legacy = false
sum_pane.set_value(3)
else
sum_pane.set_value(2)
end
else
sum_pane.set_value(4)
end
end
PushButton{parent=sum_c_1,x=1,y=15,text="\x1b Back",callback=back_from_summary,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
tool_ctl.show_key_btn = PushButton{parent=sum_c_1,x=1,y=13,min_width=17,text="Unhide Auth Key",callback=function()tool_ctl.show_auth_key()end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=dis_fg_bg}
tool_ctl.settings_apply = PushButton{parent=sum_c_1,x=18,y=15,min_width=7,text="Apply",callback=save_and_continue,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg}
TextBox{parent=sum_c_2,x=1,y=1,height=1,text="Settings saved!"}
local function go_home()
main_pane.set_value(1)
net_pane.set_value(1)
sum_pane.set_value(1)
end
PushButton{parent=sum_c_2,x=1,y=15,min_width=6,text="Home",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=sum_c_2,x=19,y=15,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)}
TextBox{parent=sum_c_3,x=1,y=1,height=4,text="The old config.lua file will now be deleted, then the configurator will exit."}
local function delete_legacy()
fs.delete("/pocket/config.lua")
exit()
end
PushButton{parent=sum_c_3,x=1,y=15,min_width=8,text="Cancel",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=sum_c_3,x=19,y=15,min_width=6,text="OK",callback=delete_legacy,fg_bg=cpair(colors.black,colors.green),active_fg_bg=cpair(colors.white,colors.gray)}
TextBox{parent=sum_c_4,x=1,y=1,height=8,text="Failed to save the settings file.\n\nThere may not be enough space for the modification or server file permissions may be denying writes."}
PushButton{parent=sum_c_4,x=1,y=15,min_width=6,text="Home",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=sum_c_4,x=19,y=15,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)}
--#endregion
-- Config Change Log
local cl = Div{parent=changelog,x=2,y=4,width=24}
TextBox{parent=changelog,x=1,y=2,height=1,text=" Config Change Log",fg_bg=bw_fg_bg}
local c_log = ListBox{parent=cl,x=1,y=1,height=13,width=24,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
for _, change in ipairs(changes) do
TextBox{parent=c_log,text=change[1],height=1,fg_bg=bw_fg_bg}
for _, v in ipairs(change[2]) do
local e = Div{parent=c_log,height=#util.strwrap(v,21)}
TextBox{parent=e,y=1,x=1,text="- ",height=1,fg_bg=cpair(colors.gray,colors.white)}
TextBox{parent=e,y=1,x=3,text=v,height=e.get_height(),fg_bg=cpair(colors.gray,colors.white)}
end
end
PushButton{parent=cl,x=1,y=15,text="\x1b Back",callback=function()main_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
-- set tool functions now that we have the elements
-- load a legacy config file
function tool_ctl.load_legacy()
local config = require("pocket.config")
tmp_cfg.SVR_Channel = config.SVR_CHANNEL
tmp_cfg.CRD_Channel = config.CRD_CHANNEL
tmp_cfg.PKT_Channel = config.PKT_CHANNEL
tmp_cfg.ConnTimeout = config.COMMS_TIMEOUT
tmp_cfg.TrustedRange = config.TRUSTED_RANGE
tmp_cfg.AuthKey = config.AUTH_KEY or ""
tmp_cfg.LogMode = config.LOG_MODE
tmp_cfg.LogPath = config.LOG_PATH
tmp_cfg.LogDebug = config.LOG_DEBUG or false
tool_ctl.gen_summary(tmp_cfg)
sum_pane.set_value(1)
main_pane.set_value(4)
tool_ctl.importing_legacy = true
end
-- expose the auth key on the summary page
function tool_ctl.show_auth_key()
tool_ctl.show_key_btn.disable()
tool_ctl.auth_key_textbox.set_value(tool_ctl.auth_key_value)
end
-- generate the summary list
---@param cfg pkt_config
function tool_ctl.gen_summary(cfg)
setting_list.remove_all()
local alternate = false
local inner_width = setting_list.get_width() - 1
tool_ctl.show_key_btn.enable()
tool_ctl.auth_key_value = cfg.AuthKey or "" -- to show auth key
for i = 1, #fields do
local f = fields[i]
local height = 1
local label_w = string.len(f[2])
local val_max_w = (inner_width - label_w) - 1
local raw = cfg[f[1]]
local val = util.strval(raw)
if f[1] == "AuthKey" then val = string.rep("*", string.len(val))
elseif f[1] == "LogMode" then val = util.trinary(raw == log.MODE.APPEND, "append", "replace") end
if val == "nil" then val = "<not set>" end
local c = util.trinary(alternate, g_lg_fg_bg, cpair(colors.gray,colors.white))
alternate = not alternate
if string.len(val) > val_max_w then
local lines = util.strwrap(val, inner_width)
height = #lines + 1
end
local line = Div{parent=setting_list,height=height,fg_bg=c}
TextBox{parent=line,text=f[2],width=string.len(f[2]),fg_bg=cpair(colors.black,line.get_fg_bg().bkg)}
local textbox
if height > 1 then
textbox = TextBox{parent=line,x=1,y=2,text=val,height=height-1,alignment=LEFT}
else
textbox = TextBox{parent=line,x=label_w+1,y=1,text=val,alignment=RIGHT}
end
if f[1] == "AuthKey" then tool_ctl.auth_key_textbox = textbox end
end
end
end
-- reset terminal screen
local function reset_term()
term.setTextColor(colors.white)
term.setBackgroundColor(colors.black)
term.clear()
term.setCursorPos(1, 1)
end
-- run the pcoket configurator
---@param ask_config? boolean indicate if this is being called by the startup app due to an invalid configuration
function configurator.configure(ask_config)
tool_ctl.ask_config = ask_config == true
load_settings(settings_cfg, true)
tool_ctl.has_config = load_settings(ini_cfg)
reset_term()
-- set overridden colors
for i = 1, #style.colors do
term.setPaletteColor(style.colors[i].c, style.colors[i].hex)
end
local status, error = pcall(function ()
local display = DisplayBox{window=term.current(),fg_bg=style.root}
config_view(display)
while true do
local event, param1, param2, param3 = util.pull_event()
-- handle event
if event == "timer" then
tcd.handle(param1)
elseif event == "mouse_click" or event == "mouse_up" or event == "mouse_drag" or event == "mouse_scroll" or event == "double_click" then
local m_e = core.events.new_mouse_event(event, param1, param2, param3)
if m_e then display.handle_mouse(m_e) end
elseif event == "char" or event == "key" or event == "key_up" then
local k_e = core.events.new_key_event(event, param1, param2)
if k_e then display.handle_key(k_e) end
elseif event == "paste" then
display.handle_paste(param1)
end
if event == "terminate" then return end
end
end)
-- restore colors
for i = 1, #style.colors do
local r, g, b = term.nativePaletteColor(style.colors[i].c)
term.setPaletteColor(style.colors[i].c, r, g, b)
end
reset_term()
if not status then
println("configurator error: " .. error)
end
return status, error
end
return configurator

View File

@ -13,17 +13,57 @@ local LINK_STATE = iocontrol.LINK_STATE
local pocket = {} local pocket = {}
---@type pkt_config
local config = {}
pocket.config = config
-- load the pocket configuration
function pocket.load_config()
if not settings.load("/pocket.settings") then return false end
config.SVR_Channel = settings.get("SVR_Channel")
config.CRD_Channel = settings.get("CRD_Channel")
config.PKT_Channel = settings.get("PKT_Channel")
config.ConnTimeout = settings.get("ConnTimeout")
config.TrustedRange = settings.get("TrustedRange")
config.AuthKey = settings.get("AuthKey")
config.LogMode = settings.get("LogMode")
config.LogPath = settings.get("LogPath")
config.LogDebug = settings.get("LogDebug")
local cfv = util.new_validator()
cfv.assert_channel(config.SVR_Channel)
cfv.assert_channel(config.CRD_Channel)
cfv.assert_channel(config.PKT_Channel)
cfv.assert_type_num(config.ConnTimeout)
cfv.assert_min(config.ConnTimeout, 2)
cfv.assert_type_num(config.TrustedRange)
cfv.assert_min(config.TrustedRange, 0)
cfv.assert_type_str(config.AuthKey)
if type(config.AuthKey) == "string" then
local len = string.len(config.AuthKey)
cfv.assert(len == 0 or len >= 8)
end
cfv.assert_type_int(config.LogMode)
cfv.assert_range(config.LogMode, 0, 1)
cfv.assert_type_str(config.LogPath)
cfv.assert_type_bool(config.LogDebug)
return cfv.valid()
end
-- pocket coordinator + supervisor communications -- pocket coordinator + supervisor communications
---@nodiscard ---@nodiscard
---@param version string pocket version ---@param version string pocket version
---@param nic nic network interface device ---@param nic nic network interface device
---@param pkt_channel integer pocket comms channel
---@param svr_channel integer supervisor access channel
---@param crd_channel integer coordinator access channel
---@param range integer trusted device connection range
---@param sv_watchdog watchdog ---@param sv_watchdog watchdog
---@param api_watchdog watchdog ---@param api_watchdog watchdog
function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range, sv_watchdog, api_watchdog) function pocket.comms(version, nic, sv_watchdog, api_watchdog)
local self = { local self = {
sv = { sv = {
linked = false, linked = false,
@ -42,13 +82,13 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
establish_delay_counter = 0 establish_delay_counter = 0
} }
comms.set_trusted_range(range) comms.set_trusted_range(config.TrustedRange)
-- PRIVATE FUNCTIONS -- -- PRIVATE FUNCTIONS --
-- configure network channels -- configure network channels
nic.closeAll() nic.closeAll()
nic.open(pkt_channel) nic.open(config.PKT_Channel)
-- send a management packet to the supervisor -- send a management packet to the supervisor
---@param msg_type MGMT_TYPE ---@param msg_type MGMT_TYPE
@ -60,7 +100,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
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(self.sv.addr, self.sv.seq_num, PROTOCOL.SCADA_MGMT, pkt.raw_sendable())
nic.transmit(svr_channel, pkt_channel, s_pkt) nic.transmit(config.SVR_Channel, config.PKT_Channel, s_pkt)
self.sv.seq_num = self.sv.seq_num + 1 self.sv.seq_num = self.sv.seq_num + 1
end end
@ -74,7 +114,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
pkt.make(msg_type, msg) pkt.make(msg_type, msg)
s_pkt.make(self.api.addr, self.api.seq_num, PROTOCOL.SCADA_MGMT, pkt.raw_sendable()) s_pkt.make(self.api.addr, self.api.seq_num, PROTOCOL.SCADA_MGMT, pkt.raw_sendable())
nic.transmit(crd_channel, pkt_channel, s_pkt) nic.transmit(config.CRD_Channel, config.PKT_Channel, s_pkt)
self.api.seq_num = self.api.seq_num + 1 self.api.seq_num = self.api.seq_num + 1
end end
@ -217,9 +257,9 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
local protocol = packet.scada_frame.protocol() local protocol = packet.scada_frame.protocol()
local src_addr = packet.scada_frame.src_addr() local src_addr = packet.scada_frame.src_addr()
if l_chan ~= pkt_channel then if l_chan ~= config.PKT_Channel then
log.debug("received packet on unconfigured channel " .. l_chan, true) log.debug("received packet on unconfigured channel " .. l_chan, true)
elseif r_chan == crd_channel then elseif r_chan == config.CRD_Channel then
-- check sequence number -- check sequence number
if self.api.r_seq_num == nil then if self.api.r_seq_num == nil then
self.api.r_seq_num = packet.scada_frame.seq_num() self.api.r_seq_num = packet.scada_frame.seq_num()
@ -308,7 +348,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
else else
log.debug("illegal packet type " .. protocol .. " from coordinator", true) log.debug("illegal packet type " .. protocol .. " from coordinator", true)
end end
elseif r_chan == svr_channel then elseif r_chan == config.SVR_Channel then
-- check sequence number -- check sequence number
if self.sv.r_seq_num == nil then if self.sv.r_seq_num == nil then
self.sv.r_seq_num = packet.scada_frame.seq_num() self.sv.r_seq_num = packet.scada_frame.seq_num()

View File

@ -13,38 +13,37 @@ local util = require("scada-common.util")
local core = require("graphics.core") local core = require("graphics.core")
local config = require("pocket.config") local configure = require("pocket.configure")
local iocontrol = require("pocket.iocontrol") local iocontrol = require("pocket.iocontrol")
local pocket = require("pocket.pocket") local pocket = require("pocket.pocket")
local renderer = require("pocket.renderer") local renderer = require("pocket.renderer")
local POCKET_VERSION = "v0.6.3-alpha" local POCKET_VERSION = "v0.7.0-alpha"
local println = util.println local println = util.println
local println_ts = util.println_ts local println_ts = util.println_ts
---------------------------------------- ----------------------------------------
-- config validation -- get configuration
---------------------------------------- ----------------------------------------
local cfv = util.new_validator() if not pocket.load_config() then
-- try to reconfigure (user action)
local success, error = configure.configure(true)
if success then
assert(pocket.load_config(), "failed to load valid configuration")
else
assert(success, "pocket configuration error: " .. error)
end
end
cfv.assert_channel(config.SVR_CHANNEL) local config = pocket.config
cfv.assert_channel(config.CRD_CHANNEL)
cfv.assert_channel(config.PKT_CHANNEL)
cfv.assert_type_int(config.TRUSTED_RANGE)
cfv.assert_type_num(config.COMMS_TIMEOUT)
cfv.assert_min(config.COMMS_TIMEOUT, 2)
cfv.assert_type_str(config.LOG_PATH)
cfv.assert_type_int(config.LOG_MODE)
assert(cfv.valid(), "bad config file: missing/invalid fields")
---------------------------------------- ----------------------------------------
-- log init -- log init
---------------------------------------- ----------------------------------------
log.init(config.LOG_PATH, config.LOG_MODE, config.LOG_DEBUG == true) log.init(config.LogPath, config.LogMode, config.LogDebug)
log.info("========================================") log.info("========================================")
log.info("BOOTING pocket.startup " .. POCKET_VERSION) log.info("BOOTING pocket.startup " .. POCKET_VERSION)
@ -69,8 +68,8 @@ local function main()
---------------------------------------- ----------------------------------------
-- message authentication init -- message authentication init
if type(config.AUTH_KEY) == "string" then if type(config.AuthKey) == "string" and string.len(config.AuthKey) > 0 then
network.init_mac(config.AUTH_KEY) network.init_mac(config.AuthKey)
end end
iocontrol.report_link_state(iocontrol.LINK_STATE.UNLINKED) iocontrol.report_link_state(iocontrol.LINK_STATE.UNLINKED)
@ -85,8 +84,8 @@ local function main()
-- create connection watchdogs -- create connection watchdogs
local conn_wd = { local conn_wd = {
sv = util.new_watchdog(config.COMMS_TIMEOUT), sv = util.new_watchdog(config.ConnTimeout),
api = util.new_watchdog(config.COMMS_TIMEOUT) api = util.new_watchdog(config.ConnTimeout)
} }
conn_wd.sv.cancel() conn_wd.sv.cancel()
@ -96,8 +95,7 @@ local function main()
-- create network interface then setup 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, conn_wd.sv, conn_wd.api)
config.CRD_CHANNEL, config.TRUSTED_RANGE, conn_wd.sv, conn_wd.api)
log.debug("startup> comms init") log.debug("startup> comms init")
-- base loop clock (2Hz, 10 ticks) -- base loop clock (2Hz, 10 ticks)

View File

@ -181,7 +181,7 @@ local function config_view(display)
local main_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes={main_page,plc_cfg,net_cfg,log_cfg,summary,changelog}} local main_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes={main_page,plc_cfg,net_cfg,log_cfg,summary,changelog}}
-- MAIN PAGE -- Main Page
local y_start = 5 local y_start = 5
@ -212,7 +212,7 @@ local function config_view(display)
PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg} PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg}
PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(6)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(6)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
-- PLC CONFIG --#region PLC
local plc_c_1 = Div{parent=plc_cfg,x=2,y=4,width=49} local plc_c_1 = Div{parent=plc_cfg,x=2,y=4,width=49}
local plc_c_2 = Div{parent=plc_cfg,x=2,y=4,width=49} local plc_c_2 = Div{parent=plc_cfg,x=2,y=4,width=49}
@ -290,7 +290,9 @@ local function config_view(display)
PushButton{parent=plc_c_4,x=1,y=14,text="\x1b Back",callback=function()plc_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=plc_c_4,x=1,y=14,text="\x1b Back",callback=function()plc_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=plc_c_4,x=44,y=14,text="Next \x1a",callback=submit_emcool,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=plc_c_4,x=44,y=14,text="Next \x1a",callback=submit_emcool,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
-- NET CONFIG --#endregion
--#region Network
local net_c_1 = Div{parent=net_cfg,x=2,y=4,width=49} local net_c_1 = Div{parent=net_cfg,x=2,y=4,width=49}
local net_c_2 = Div{parent=net_cfg,x=2,y=4,width=49} local net_c_2 = Div{parent=net_cfg,x=2,y=4,width=49}
@ -390,7 +392,9 @@ local function config_view(display)
PushButton{parent=net_c_3,x=1,y=14,text="\x1b Back",callback=function()net_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=net_c_3,x=1,y=14,text="\x1b Back",callback=function()net_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=net_c_3,x=44,y=14,text="Next \x1a",callback=submit_auth,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=net_c_3,x=44,y=14,text="Next \x1a",callback=submit_auth,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
-- LOG CONFIG --#endregion
--#region Logging
local log_c_1 = Div{parent=log_cfg,x=2,y=4,width=49} local log_c_1 = Div{parent=log_cfg,x=2,y=4,width=49}
@ -430,7 +434,9 @@ local function config_view(display)
PushButton{parent=log_c_1,x=1,y=14,text="\x1b Back",callback=back_from_log,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=log_c_1,x=1,y=14,text="\x1b Back",callback=back_from_log,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=log_c_1,x=44,y=14,text="Next \x1a",callback=submit_log,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=log_c_1,x=44,y=14,text="Next \x1a",callback=submit_log,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
-- SUMMARY OF CHANGES --#endregion
--#region Summary and Saving
local sum_c_1 = Div{parent=summary,x=2,y=4,width=49} local sum_c_1 = Div{parent=summary,x=2,y=4,width=49}
local sum_c_2 = Div{parent=summary,x=2,y=4,width=49} local sum_c_2 = Div{parent=summary,x=2,y=4,width=49}
@ -441,7 +447,7 @@ local function config_view(display)
TextBox{parent=summary,x=1,y=2,height=1,text=" Summary",fg_bg=cpair(colors.black,colors.green)} TextBox{parent=summary,x=1,y=2,height=1,text=" Summary",fg_bg=cpair(colors.black,colors.green)}
local setting_list = ListBox{parent=sum_c_1,x=1,y=1,height=12,width=51,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local setting_list = ListBox{parent=sum_c_1,x=1,y=1,height=12,width=49,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
local function back_from_settings() local function back_from_settings()
if tool_ctl.viewing_config or tool_ctl.importing_legacy then if tool_ctl.viewing_config or tool_ctl.importing_legacy then
@ -463,7 +469,7 @@ local function config_view(display)
local function save_and_continue() local function save_and_continue()
for k, v in pairs(tmp_cfg) do settings.set(k, v) end for k, v in pairs(tmp_cfg) do settings.set(k, v) end
if settings.save("reactor-plc.settings") then if settings.save("/reactor-plc.settings") then
load_settings(settings_cfg, true) load_settings(settings_cfg, true)
load_settings(ini_cfg) load_settings(ini_cfg)
@ -525,13 +531,15 @@ local function config_view(display)
PushButton{parent=sum_c_4,x=1,y=14,min_width=6,text="Home",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=sum_c_4,x=1,y=14,min_width=6,text="Home",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=sum_c_4,x=44,y=14,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)} PushButton{parent=sum_c_4,x=44,y=14,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)}
-- CONFIG CHANGE LOG --#endregion
-- Config Change Log
local cl = Div{parent=changelog,x=2,y=4,width=49} local cl = Div{parent=changelog,x=2,y=4,width=49}
TextBox{parent=changelog,x=1,y=2,height=1,text=" Config Change Log",fg_bg=bw_fg_bg} TextBox{parent=changelog,x=1,y=2,height=1,text=" Config Change Log",fg_bg=bw_fg_bg}
local c_log = ListBox{parent=cl,x=1,y=1,height=12,width=51,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local c_log = ListBox{parent=cl,x=1,y=1,height=12,width=49,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
for _, change in ipairs(changes) do for _, change in ipairs(changes) do
TextBox{parent=c_log,text=change[1],height=1,fg_bg=bw_fg_bg} TextBox{parent=c_log,text=change[1],height=1,fg_bg=bw_fg_bg}
@ -646,7 +654,7 @@ local function reset_term()
end end
-- run the reactor PLC configurator -- run the reactor PLC configurator
---@param ask_config? boolean indicate if this is being called by the PLC startup app due to an invalid configuration ---@param ask_config? boolean indicate if this is being called by the startup app due to an invalid configuration
function configurator.configure(ask_config) function configurator.configure(ask_config)
tool_ctl.ask_config = ask_config == true tool_ctl.ask_config = ask_config == true

View File

@ -18,7 +18,7 @@ local plc = require("reactor-plc.plc")
local renderer = require("reactor-plc.renderer") local renderer = require("reactor-plc.renderer")
local threads = require("reactor-plc.threads") local threads = require("reactor-plc.threads")
local R_PLC_VERSION = "v1.6.10" local R_PLC_VERSION = "v1.6.11"
local println = util.println local println = util.println
local println_ts = util.println_ts local println_ts = util.println_ts

View File

@ -273,7 +273,7 @@ local function config_view(display)
local main_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes={main_page,spkr_cfg,net_cfg,log_cfg,summary,changelog,peri_cfg,rs_cfg}} local main_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes={main_page,spkr_cfg,net_cfg,log_cfg,summary,changelog,peri_cfg,rs_cfg}}
--#region MAIN PAGE --#region Main Page
local y_start = 2 local y_start = 2
@ -324,7 +324,7 @@ local function config_view(display)
--#endregion --#endregion
--#region SPEAKER CONFIG --#region Speakers
local spkr_c = Div{parent=spkr_cfg,x=2,y=4,width=49} local spkr_c = Div{parent=spkr_cfg,x=2,y=4,width=49}
@ -353,7 +353,7 @@ local function config_view(display)
--#endregion --#endregion
--#region NET CONFIG --#region Network
local net_c_1 = Div{parent=net_cfg,x=2,y=4,width=49} local net_c_1 = Div{parent=net_cfg,x=2,y=4,width=49}
local net_c_2 = Div{parent=net_cfg,x=2,y=4,width=49} local net_c_2 = Div{parent=net_cfg,x=2,y=4,width=49}
@ -455,7 +455,7 @@ local function config_view(display)
--#endregion --#endregion
--#region LOG CONFIG --#region Logging
local log_c_1 = Div{parent=log_cfg,x=2,y=4,width=49} local log_c_1 = Div{parent=log_cfg,x=2,y=4,width=49}
@ -494,7 +494,7 @@ local function config_view(display)
--#endregion --#endregion
--#region SUMMARY OF CHANGES --#region Summary and Saving
local sum_c_1 = Div{parent=summary,x=2,y=4,width=49} local sum_c_1 = Div{parent=summary,x=2,y=4,width=49}
local sum_c_2 = Div{parent=summary,x=2,y=4,width=49} local sum_c_2 = Div{parent=summary,x=2,y=4,width=49}
@ -508,7 +508,7 @@ local function config_view(display)
TextBox{parent=summary,x=1,y=2,height=1,text=" Summary",fg_bg=cpair(colors.black,colors.green)} TextBox{parent=summary,x=1,y=2,height=1,text=" Summary",fg_bg=cpair(colors.black,colors.green)}
local setting_list = ListBox{parent=sum_c_1,x=1,y=1,height=12,width=51,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local setting_list = ListBox{parent=sum_c_1,x=1,y=1,height=12,width=49,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
local function back_from_settings() local function back_from_settings()
if tool_ctl.viewing_config or tool_ctl.importing_legacy then if tool_ctl.viewing_config or tool_ctl.importing_legacy then
@ -539,7 +539,7 @@ local function config_view(display)
if settings.get("Peripherals") == nil then settings.set("Peripherals", {}) end if settings.get("Peripherals") == nil then settings.set("Peripherals", {}) end
if settings.get("Redstone") == nil then settings.set("Redstone", {}) end if settings.get("Redstone") == nil then settings.set("Redstone", {}) end
if settings.save("rtu.settings") then if settings.save("/rtu.settings") then
load_settings(settings_cfg, true) load_settings(settings_cfg, true)
load_settings(ini_cfg) load_settings(ini_cfg)
@ -578,13 +578,13 @@ local function config_view(display)
tool_ctl.settings_confirm.hide() tool_ctl.settings_confirm.hide()
TextBox{parent=sum_c_2,x=1,y=1,height=1,text="The following peripherals will be imported:"} TextBox{parent=sum_c_2,x=1,y=1,height=1,text="The following peripherals will be imported:"}
local peri_import_list = ListBox{parent=sum_c_2,x=1,y=3,height=10,width=51,scroll_height=1000,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local peri_import_list = ListBox{parent=sum_c_2,x=1,y=3,height=10,width=49,scroll_height=1000,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
PushButton{parent=sum_c_2,x=1,y=14,text="\x1b Back",callback=function()sum_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=sum_c_2,x=1,y=14,text="\x1b Back",callback=function()sum_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=sum_c_2,x=41,y=14,min_width=9,text="Confirm",callback=function()sum_pane.set_value(3)end,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg} PushButton{parent=sum_c_2,x=41,y=14,min_width=9,text="Confirm",callback=function()sum_pane.set_value(3)end,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg}
TextBox{parent=sum_c_3,x=1,y=1,height=1,text="The following redstone entries will be imported:"} TextBox{parent=sum_c_3,x=1,y=1,height=1,text="The following redstone entries will be imported:"}
local rs_import_list = ListBox{parent=sum_c_3,x=1,y=3,height=10,width=51,scroll_height=1000,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local rs_import_list = ListBox{parent=sum_c_3,x=1,y=3,height=10,width=49,scroll_height=1000,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
PushButton{parent=sum_c_3,x=1,y=14,text="\x1b Back",callback=function()sum_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=sum_c_3,x=1,y=14,text="\x1b Back",callback=function()sum_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=sum_c_3,x=43,y=14,min_width=7,text="Apply",callback=save_and_continue,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg} PushButton{parent=sum_c_3,x=43,y=14,min_width=7,text="Apply",callback=save_and_continue,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg}
@ -614,13 +614,13 @@ local function config_view(display)
--#endregion --#endregion
--#region CONFIG CHANGE LOG --#region Config Change Log
local cl = Div{parent=changelog,x=2,y=4,width=49} local cl = Div{parent=changelog,x=2,y=4,width=49}
TextBox{parent=changelog,x=1,y=2,height=1,text=" Config Change Log",fg_bg=bw_fg_bg} TextBox{parent=changelog,x=1,y=2,height=1,text=" Config Change Log",fg_bg=bw_fg_bg}
local c_log = ListBox{parent=cl,x=1,y=1,height=12,width=51,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local c_log = ListBox{parent=cl,x=1,y=1,height=12,width=49,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
for _, change in ipairs(changes) do for _, change in ipairs(changes) do
TextBox{parent=c_log,text=change[1],height=1,fg_bg=bw_fg_bg} TextBox{parent=c_log,text=change[1],height=1,fg_bg=bw_fg_bg}
@ -635,7 +635,7 @@ local function config_view(display)
--#endregion --#endregion
--#region DEVICES --#region Peripherals
local peri_c_1 = Div{parent=peri_cfg,x=2,y=4,width=49} local peri_c_1 = Div{parent=peri_cfg,x=2,y=4,width=49}
local peri_c_2 = Div{parent=peri_cfg,x=2,y=4,width=49} local peri_c_2 = Div{parent=peri_cfg,x=2,y=4,width=49}
@ -649,7 +649,7 @@ local function config_view(display)
TextBox{parent=peri_cfg,x=1,y=2,height=1,text=" Peripheral Connections",fg_bg=cpair(colors.black,colors.purple)} TextBox{parent=peri_cfg,x=1,y=2,height=1,text=" Peripheral Connections",fg_bg=cpair(colors.black,colors.purple)}
local peri_list = ListBox{parent=peri_c_1,x=1,y=1,height=12,width=51,scroll_height=1000,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local peri_list = ListBox{parent=peri_c_1,x=1,y=1,height=12,width=49,scroll_height=1000,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
local function peri_revert() local function peri_revert()
tmp_cfg.Peripherals = deep_copy_peri(ini_cfg.Peripherals) tmp_cfg.Peripherals = deep_copy_peri(ini_cfg.Peripherals)
@ -659,7 +659,7 @@ local function config_view(display)
local function peri_apply() local function peri_apply()
settings.set("Peripherals", tmp_cfg.Peripherals) settings.set("Peripherals", tmp_cfg.Peripherals)
if settings.save("rtu.settings") then if settings.save("/rtu.settings") then
load_settings(settings_cfg, true) load_settings(settings_cfg, true)
load_settings(ini_cfg) load_settings(ini_cfg)
peri_pane.set_value(5) peri_pane.set_value(5)
@ -675,7 +675,7 @@ local function config_view(display)
TextBox{parent=peri_c_2,x=1,y=1,height=1,text="Select one of the below devices to use."} TextBox{parent=peri_c_2,x=1,y=1,height=1,text="Select one of the below devices to use."}
tool_ctl.ppm_devs = ListBox{parent=peri_c_2,x=1,y=3,height=10,width=51,scroll_height=1000,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} tool_ctl.ppm_devs = ListBox{parent=peri_c_2,x=1,y=3,height=10,width=49,scroll_height=1000,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
PushButton{parent=peri_c_2,x=1,y=14,text="\x1b Back",callback=function()peri_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=peri_c_2,x=1,y=14,text="\x1b Back",callback=function()peri_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=peri_c_2,x=8,y=14,min_width=10,text="Manual +",callback=function()peri_pane.set_value(3)end,fg_bg=cpair(colors.black,colors.orange),active_fg_bg=btn_act_fg_bg} PushButton{parent=peri_c_2,x=8,y=14,min_width=10,text="Manual +",callback=function()peri_pane.set_value(3)end,fg_bg=cpair(colors.black,colors.orange),active_fg_bg=btn_act_fg_bg}
@ -949,7 +949,7 @@ local function config_view(display)
--#endregion --#endregion
--#region REDSTONE --#region Redstone
local rs_c_1 = Div{parent=rs_cfg,x=2,y=4,width=49} local rs_c_1 = Div{parent=rs_cfg,x=2,y=4,width=49}
local rs_c_2 = Div{parent=rs_cfg,x=2,y=4,width=49} local rs_c_2 = Div{parent=rs_cfg,x=2,y=4,width=49}
@ -963,7 +963,7 @@ local function config_view(display)
TextBox{parent=rs_cfg,x=1,y=2,height=1,text=" Redstone Connections",fg_bg=cpair(colors.black,colors.red)} TextBox{parent=rs_cfg,x=1,y=2,height=1,text=" Redstone Connections",fg_bg=cpair(colors.black,colors.red)}
TextBox{parent=rs_c_1,x=1,y=1,height=1,text=" port side/color unit/facility",fg_bg=g_lg_fg_bg} TextBox{parent=rs_c_1,x=1,y=1,height=1,text=" port side/color unit/facility",fg_bg=g_lg_fg_bg}
local rs_list = ListBox{parent=rs_c_1,x=1,y=2,height=11,width=51,scroll_height=200,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local rs_list = ListBox{parent=rs_c_1,x=1,y=2,height=11,width=49,scroll_height=200,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
local function rs_revert() local function rs_revert()
tmp_cfg.Redstone = deep_copy_rs(ini_cfg.Redstone) tmp_cfg.Redstone = deep_copy_rs(ini_cfg.Redstone)
@ -973,7 +973,7 @@ local function config_view(display)
local function rs_apply() local function rs_apply()
settings.set("Redstone", tmp_cfg.Redstone) settings.set("Redstone", tmp_cfg.Redstone)
if settings.save("rtu.settings") then if settings.save("/rtu.settings") then
load_settings(settings_cfg, true) load_settings(settings_cfg, true)
load_settings(ini_cfg) load_settings(ini_cfg)
rs_pane.set_value(4) rs_pane.set_value(4)
@ -992,7 +992,7 @@ local function config_view(display)
TextBox{parent=rs_c_2,x=1,y=1,height=1,text="Select one of the below ports to use."} TextBox{parent=rs_c_2,x=1,y=1,height=1,text="Select one of the below ports to use."}
local rs_ports = ListBox{parent=rs_c_2,x=1,y=3,height=10,width=51,scroll_height=200,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local rs_ports = ListBox{parent=rs_c_2,x=1,y=3,height=10,width=49,scroll_height=200,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
local function new_rs(port) local function new_rs(port)
if (rsio.get_io_dir(port) == rsio.IO_DIR.IN) then if (rsio.get_io_dir(port) == rsio.IO_DIR.IN) then
@ -1466,7 +1466,7 @@ local function reset_term()
end end
-- run the RTU gateway configurator -- run the RTU gateway configurator
---@param ask_config? boolean indicate if this is being called by the RTU startup app due to an invalid configuration ---@param ask_config? boolean indicate if this is being called by the startup app due to an invalid configuration
function configurator.configure(ask_config) function configurator.configure(ask_config)
tool_ctl.ask_config = ask_config == true tool_ctl.ask_config = ask_config == true

View File

@ -31,7 +31,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.7.12" local RTU_VERSION = "v1.7.13"
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

View File

@ -17,7 +17,7 @@ local max_distance = nil
local comms = {} local comms = {}
-- protocol/data version (protocol/data independent changes tracked by util.lua version) -- protocol/data version (protocol/data independent changes tracked by util.lua version)
comms.version = "2.4.3" comms.version = "2.4.4"
---@enum PROTOCOL ---@enum PROTOCOL
local PROTOCOL = { local PROTOCOL = {

View File

@ -7,7 +7,7 @@ local log = require("scada-common.log")
local util = require("scada-common.util") local util = require("scada-common.util")
local md5 = require("lockbox.digest.md5") local md5 = require("lockbox.digest.md5")
local sha256 = require("lockbox.digest.sha2_256") local sha1 = require("lockbox.digest.sha1")
local pbkdf2 = require("lockbox.kdf.pbkdf2") local pbkdf2 = require("lockbox.kdf.pbkdf2")
local hmac = require("lockbox.mac.hmac") local hmac = require("lockbox.mac.hmac")
local stream = require("lockbox.util.stream") local stream = require("lockbox.util.stream")
@ -31,12 +31,12 @@ function network.init_mac(passkey)
local key_deriv = pbkdf2() local key_deriv = pbkdf2()
-- setup PBKDF2 -- setup PBKDF2
key_deriv.setPassword(passkey) key_deriv.setPRF(hmac().setBlockSize(64).setDigest(sha1))
key_deriv.setBlockLen(20)
key_deriv.setDKeyLen(20)
key_deriv.setIterations(256)
key_deriv.setSalt("pepper") key_deriv.setSalt("pepper")
key_deriv.setIterations(32) key_deriv.setPassword(passkey)
key_deriv.setBlockLen(8)
key_deriv.setDKeyLen(16)
key_deriv.setPRF(hmac().setBlockSize(64).setDigest(sha256))
key_deriv.finish() key_deriv.finish()
c_eng.key = array.fromHex(key_deriv.asHex()) c_eng.key = array.fromHex(key_deriv.asHex())

View File

@ -22,7 +22,7 @@ local t_pack = table.pack
local util = {} local util = {}
-- scada-common version -- scada-common version
util.version = "1.1.13" util.version = "1.1.14"
util.TICK_TIME_S = 0.05 util.TICK_TIME_S = 0.05
util.TICK_TIME_MS = 50 util.TICK_TIME_MS = 50

View File

@ -2,7 +2,7 @@ local util = require("scada-common.util")
local println = util.println local println = util.println
local BOOTLOADER_VERSION = "0.6" local BOOTLOADER_VERSION = "1.0"
println("SCADA BOOTLOADER V" .. BOOTLOADER_VERSION) println("SCADA BOOTLOADER V" .. BOOTLOADER_VERSION)
println("BOOT> SCANNING FOR APPLICATIONS...") println("BOOT> SCANNING FOR APPLICATIONS...")

View File

@ -170,7 +170,7 @@ local function config_view(display)
local main_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes={main_page,svr_cfg,net_cfg,log_cfg,summary,changelog,import_err}} local main_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes={main_page,svr_cfg,net_cfg,log_cfg,summary,changelog,import_err}}
-- MAIN PAGE -- Main Page
local y_start = 5 local y_start = 5
@ -201,7 +201,7 @@ local function config_view(display)
PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg} PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg}
PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(6)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(6)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
-- SUPERVISOR CONFIG --#region Facility
local svr_c_1 = Div{parent=svr_cfg,x=2,y=4,width=49} local svr_c_1 = Div{parent=svr_cfg,x=2,y=4,width=49}
local svr_c_2 = Div{parent=svr_cfg,x=2,y=4,width=49} local svr_c_2 = Div{parent=svr_cfg,x=2,y=4,width=49}
@ -564,7 +564,9 @@ local function config_view(display)
PushButton{parent=svr_c_6,x=1,y=14,text="\x1b Back",callback=function()svr_pane.set_value(5)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=svr_c_6,x=1,y=14,text="\x1b Back",callback=function()svr_pane.set_value(5)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
-- NET CONFIG --#endregion
--#region Network
local net_c_1 = Div{parent=net_cfg,x=2,y=4,width=49} local net_c_1 = Div{parent=net_cfg,x=2,y=4,width=49}
local net_c_2 = Div{parent=net_cfg,x=2,y=4,width=49} local net_c_2 = Div{parent=net_cfg,x=2,y=4,width=49}
@ -692,7 +694,9 @@ local function config_view(display)
PushButton{parent=net_c_4,x=1,y=14,text="\x1b Back",callback=function()net_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=net_c_4,x=1,y=14,text="\x1b Back",callback=function()net_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=net_c_4,x=44,y=14,text="Next \x1a",callback=submit_auth,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=net_c_4,x=44,y=14,text="Next \x1a",callback=submit_auth,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
-- LOG CONFIG --#endregion
--#region Logging
local log_c_1 = Div{parent=log_cfg,x=2,y=4,width=49} local log_c_1 = Div{parent=log_cfg,x=2,y=4,width=49}
@ -728,7 +732,9 @@ local function config_view(display)
PushButton{parent=log_c_1,x=1,y=14,text="\x1b Back",callback=function()main_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=log_c_1,x=1,y=14,text="\x1b Back",callback=function()main_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=log_c_1,x=44,y=14,text="Next \x1a",callback=submit_log,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=log_c_1,x=44,y=14,text="Next \x1a",callback=submit_log,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
-- SUMMARY OF CHANGES --#endregion
--#region Summary and Saving
local sum_c_1 = Div{parent=summary,x=2,y=4,width=49} local sum_c_1 = Div{parent=summary,x=2,y=4,width=49}
local sum_c_2 = Div{parent=summary,x=2,y=4,width=49} local sum_c_2 = Div{parent=summary,x=2,y=4,width=49}
@ -739,7 +745,7 @@ local function config_view(display)
TextBox{parent=summary,x=1,y=2,height=1,text=" Summary",fg_bg=cpair(colors.black,colors.green)} TextBox{parent=summary,x=1,y=2,height=1,text=" Summary",fg_bg=cpair(colors.black,colors.green)}
local setting_list = ListBox{parent=sum_c_1,x=1,y=1,height=12,width=51,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local setting_list = ListBox{parent=sum_c_1,x=1,y=1,height=12,width=49,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
local function back_from_settings() local function back_from_settings()
if tool_ctl.viewing_config or tool_ctl.importing_legacy then if tool_ctl.viewing_config or tool_ctl.importing_legacy then
@ -761,7 +767,7 @@ local function config_view(display)
local function save_and_continue() local function save_and_continue()
for k, v in pairs(tmp_cfg) do settings.set(k, v) end for k, v in pairs(tmp_cfg) do settings.set(k, v) end
if settings.save("supervisor.settings") then if settings.save("/supervisor.settings") then
load_settings(settings_cfg, true) load_settings(settings_cfg, true)
load_settings(ini_cfg) load_settings(ini_cfg)
@ -838,13 +844,15 @@ local function config_view(display)
PushButton{parent=sum_c_4,x=1,y=14,min_width=6,text="Home",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=sum_c_4,x=1,y=14,min_width=6,text="Home",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=sum_c_4,x=44,y=14,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)} PushButton{parent=sum_c_4,x=44,y=14,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)}
-- CONFIG CHANGE LOG --#endregion
-- Config Change Log
local cl = Div{parent=changelog,x=2,y=4,width=49} local cl = Div{parent=changelog,x=2,y=4,width=49}
TextBox{parent=changelog,x=1,y=2,height=1,text=" Config Change Log",fg_bg=bw_fg_bg} TextBox{parent=changelog,x=1,y=2,height=1,text=" Config Change Log",fg_bg=bw_fg_bg}
local c_log = ListBox{parent=cl,x=1,y=1,height=12,width=51,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)} local c_log = ListBox{parent=cl,x=1,y=1,height=12,width=49,scroll_height=100,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
for _, change in ipairs(changes) do for _, change in ipairs(changes) do
TextBox{parent=c_log,text=change[1],height=1,fg_bg=bw_fg_bg} TextBox{parent=c_log,text=change[1],height=1,fg_bg=bw_fg_bg}
@ -857,7 +865,7 @@ local function config_view(display)
PushButton{parent=cl,x=1,y=14,text="\x1b Back",callback=function()main_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=cl,x=1,y=14,text="\x1b Back",callback=function()main_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
-- IMPORT ERROR -- Import Error
local i_err = Div{parent=import_err,x=2,y=4,width=49} local i_err = Div{parent=import_err,x=2,y=4,width=49}
@ -1033,7 +1041,7 @@ local function reset_term()
end end
-- run the supervisor configurator -- run the supervisor configurator
---@param ask_config? boolean indicate if this is being called by the supervisor startup app due to an invalid configuration ---@param ask_config? boolean indicate if this is being called by the startup app due to an invalid configuration
function configurator.configure(ask_config) function configurator.configure(ask_config)
tool_ctl.ask_config = ask_config == true tool_ctl.ask_config = ask_config == true

View File

@ -21,7 +21,7 @@ local supervisor = require("supervisor.supervisor")
local svsessions = require("supervisor.session.svsessions") local svsessions = require("supervisor.session.svsessions")
local SUPERVISOR_VERSION = "v1.2.6" local SUPERVISOR_VERSION = "v1.2.7"
local println = util.println local println = util.println
local println_ts = util.println_ts local println_ts = util.println_ts