mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
Merge pull request #422 from MikaylaFischler/145-graphical-configure-utilities
Pocket Configurator and Other Fixes
This commit is contained in:
commit
940f71aa35
121
ccmsi.lua
121
ccmsi.lua
@ -18,7 +18,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
local function println(message) print(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 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 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 orange() term.setTextColor(colors.orange) end
|
||||
@ -59,17 +59,17 @@ local function ask_y_n(question, default)
|
||||
end
|
||||
|
||||
-- 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
|
||||
local function show_pkg_change(name, v)
|
||||
if v.v_local ~= nil 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
|
||||
pkg_message("[" .. name .. "] reinstalling", v.v_local)
|
||||
pkg_message("["..name.."] reinstalling", v.v_local)
|
||||
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
|
||||
end
|
||||
|
||||
@ -90,7 +90,7 @@ local function get_remote_manifest()
|
||||
local response, error = http.get(install_manifest)
|
||||
if response == nil then
|
||||
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, {}
|
||||
end
|
||||
|
||||
@ -155,13 +155,13 @@ local function _clean_dir(dir, tree)
|
||||
if tree == nil then tree = {} end
|
||||
local ls = fs.list(dir)
|
||||
for _, val in pairs(ls) do
|
||||
local path = dir .. "/" .. val
|
||||
local path = dir.."/"..val
|
||||
if fs.isDir(path) then
|
||||
_clean_dir(path, tree[val])
|
||||
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
|
||||
if #fs.list(path) == 0 then fs.delete(path);println("deleted "..path) end
|
||||
elseif (not _in_array(val, tree)) and (val ~= "config.lua" ) then
|
||||
fs.delete(path)
|
||||
println("deleted " .. path)
|
||||
println("deleted "..path)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -177,13 +177,13 @@ local function clean(manifest)
|
||||
local ls = fs.list("/")
|
||||
for _, val in pairs(ls) do
|
||||
if fs.isDriveRoot(val) then
|
||||
yellow();println("skipped mount '" .. val .. "'")
|
||||
yellow();println("skipped mount '"..val.."'")
|
||||
elseif fs.isDir(val) then
|
||||
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
|
||||
if #fs.list(val) == 0 then fs.delete(val);lgray();println("deleted empty directory '" .. val .. "'") end
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
@ -192,7 +192,7 @@ end
|
||||
|
||||
-- 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
|
||||
println("usage: ccmsi <mode> <app> <branch>")
|
||||
@ -202,8 +202,8 @@ if #opts == 0 or opts[1] == "help" then
|
||||
yellow()
|
||||
println(" ccmsi check <branch> for target")
|
||||
lgray()
|
||||
println(" install - fresh install, overwrites config.lua")
|
||||
println(" update - update files EXCEPT for config.lua")
|
||||
println(" install - fresh install")
|
||||
println(" update - update files")
|
||||
println(" uninstall - delete files INCLUDING config/logs")
|
||||
white();println("<app>");lgray()
|
||||
println(" reactor-plc - reactor PLC firmware")
|
||||
@ -239,8 +239,8 @@ else
|
||||
end
|
||||
|
||||
-- set paths
|
||||
install_manifest = manifest_path .. target .. "/install_manifest.json"
|
||||
repo_path = repo_path .. target .. "/"
|
||||
install_manifest = manifest_path..target.."/install_manifest.json"
|
||||
repo_path = repo_path..target.."/"
|
||||
end
|
||||
|
||||
-- run selected mode
|
||||
@ -260,7 +260,7 @@ if mode == "check" then
|
||||
-- list all versions
|
||||
for key, value in pairs(manifest.versions) do
|
||||
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
|
||||
blue();print(local_manifest.versions[key])
|
||||
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 update_installer or ask_y_n("Would you like to update now") then
|
||||
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
|
||||
red();println("HTTP Error " .. err)
|
||||
red();println("HTTP Error "..err)
|
||||
println("Installer download failed.");white()
|
||||
else
|
||||
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
|
||||
|
||||
green()
|
||||
if mode == "install" then
|
||||
println("Installing " .. app .. " files...")
|
||||
elseif mode == "update" then
|
||||
if app == "pocket" then println("Updating " .. app .. " files... (keeping old config.lua)")
|
||||
else println("Updating " .. app .. " files...") end
|
||||
end
|
||||
white()
|
||||
if mode == "install" then print("Installing ") else print("Updating ") end
|
||||
println(app.." files...");white()
|
||||
|
||||
ver.boot.changed = show_pkg_change("bootldr", ver.boot)
|
||||
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 size_list = manifest.sizes
|
||||
local dependencies = manifest.depends[app]
|
||||
local config_file = app .. "/config.lua"
|
||||
|
||||
table.insert(dependencies, app)
|
||||
|
||||
@ -421,15 +415,15 @@ elseif mode == "install" or mode == "update" then
|
||||
|
||||
local files = file_list[dependency]
|
||||
for _, file in pairs(files) do
|
||||
println("GET " .. file)
|
||||
local dl, err = http.get(repo_path .. file)
|
||||
println("GET "..file)
|
||||
local dl, err = http.get(repo_path..file)
|
||||
|
||||
if dl == nil then
|
||||
red();println("HTTP Error " .. err)
|
||||
red();println("HTTP Error "..err)
|
||||
success = false
|
||||
break
|
||||
else
|
||||
local handle = fs.open(install_dir .. "/" .. file, "w")
|
||||
local handle = fs.open(install_dir.."/"..file, "w")
|
||||
handle.write(dl.readAll())
|
||||
handle.close()
|
||||
end
|
||||
@ -448,11 +442,9 @@ elseif mode == "install" or mode == "update" then
|
||||
|
||||
local files = file_list[dependency]
|
||||
for _, file in pairs(files) do
|
||||
if mode == "install" or file ~= config_file then
|
||||
local temp_file = install_dir .. "/" .. file
|
||||
if fs.exists(file) then fs.delete(file) end
|
||||
fs.move(temp_file, file)
|
||||
end
|
||||
local temp_file = install_dir.."/"..file
|
||||
if fs.exists(file) then fs.delete(file) end
|
||||
fs.move(temp_file, file)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -485,19 +477,17 @@ elseif mode == "install" or mode == "update" then
|
||||
|
||||
local files = file_list[dependency]
|
||||
for _, file in pairs(files) do
|
||||
if mode == "install" or file ~= config_file then
|
||||
println("GET " .. file)
|
||||
local dl, err = http.get(repo_path .. file)
|
||||
println("GET "..file)
|
||||
local dl, err = http.get(repo_path..file)
|
||||
|
||||
if dl == nil then
|
||||
red();println("HTTP Error " .. err)
|
||||
success = false
|
||||
break
|
||||
else
|
||||
local handle = fs.open("/" .. file, "w")
|
||||
handle.write(dl.readAll())
|
||||
handle.close()
|
||||
end
|
||||
if dl == nil then
|
||||
red();println("HTTP Error "..err)
|
||||
success = false
|
||||
break
|
||||
else
|
||||
local handle = fs.open("/"..file, "w")
|
||||
handle.write(dl.readAll())
|
||||
handle.close()
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -527,11 +517,11 @@ elseif mode == "uninstall" then
|
||||
end
|
||||
|
||||
if manifest.versions[app] == nil then
|
||||
red();println("Error: '" .. app .. "' is not installed.")
|
||||
red();println("Error: '"..app.."' is not installed.")
|
||||
return
|
||||
end
|
||||
|
||||
orange();println("Uninstalling all " .. app .. " files...")
|
||||
orange();println("Uninstalling all "..app.." files...")
|
||||
|
||||
-- ask for confirmation
|
||||
if not ask_y_n("Continue", false) then return end
|
||||
@ -546,16 +536,16 @@ elseif mode == "uninstall" then
|
||||
|
||||
-- delete log file
|
||||
local log_deleted = false
|
||||
local settings_file = app .. ".settings"
|
||||
local legacy_config_file = app .. "/config.lua"
|
||||
local settings_file = app..".settings"
|
||||
local legacy_config_file = app.."/config.lua"
|
||||
|
||||
lgray()
|
||||
if fs.exists(legacy_config_file) then
|
||||
log_deleted = pcall(function ()
|
||||
local config = require(app .. ".config")
|
||||
local config = require(app..".config")
|
||||
if fs.exists(config.LOG_PATH) then
|
||||
fs.delete(config.LOG_PATH)
|
||||
println("deleted log file " .. config.LOG_PATH)
|
||||
println("deleted log file "..config.LOG_PATH)
|
||||
end
|
||||
end)
|
||||
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
|
||||
log_deleted = true
|
||||
fs.delete(log)
|
||||
println("deleted log file " .. log)
|
||||
println("deleted log file "..log)
|
||||
end
|
||||
end
|
||||
|
||||
@ -577,7 +567,7 @@ elseif mode == "uninstall" then
|
||||
for _, dependency in pairs(dependencies) do
|
||||
local files = file_list[dependency]
|
||||
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
|
||||
|
||||
local folder = files[1]
|
||||
@ -588,13 +578,16 @@ elseif mode == "uninstall" then
|
||||
|
||||
if fs.isDir(folder) then
|
||||
fs.delete(folder)
|
||||
println("deleted directory " .. folder)
|
||||
println("deleted directory "..folder)
|
||||
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
|
||||
fs.delete(settings_file)
|
||||
println("deleted " .. settings_file)
|
||||
fs.delete(settings_file);println("deleted "..settings_file)
|
||||
end
|
||||
|
||||
fs.delete("install_manifest.json")
|
||||
|
@ -1,15 +1,10 @@
|
||||
print("CONFIGURE> SCANNING FOR CONFIGURATOR...")
|
||||
|
||||
if fs.exists("reactor-plc/configure.lua") then
|
||||
require("reactor-plc.configure").configure()
|
||||
elseif fs.exists("rtu/configure.lua") then
|
||||
require("rtu.configure").configure()
|
||||
elseif fs.exists("supervisor/configure.lua") then
|
||||
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)")
|
||||
if fs.exists("reactor-plc/configure.lua") then require("reactor-plc.configure").configure()
|
||||
elseif fs.exists("rtu/configure.lua") then require("rtu.configure").configure()
|
||||
elseif fs.exists("supervisor/configure.lua") then require("supervisor.configure").configure()
|
||||
elseif fs.exists("coordinator/configure.lua") then require("coordinator.configure").configure()
|
||||
elseif fs.exists("pocket/configure.lua") then require("pocket.configure").configure()
|
||||
else
|
||||
print("CONFIGURE> NO CONFIGURATOR FOUND")
|
||||
print("CONFIGURE> EXIT")
|
||||
|
@ -347,7 +347,7 @@ local function config_view(display)
|
||||
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=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
|
||||
|
||||
@ -453,20 +453,22 @@ local function config_view(display)
|
||||
local function submit_auth()
|
||||
local v = key.get_value()
|
||||
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()
|
||||
main_pane.set_value(3)
|
||||
key_err.hide(true)
|
||||
|
||||
-- init mac for supervisor connection
|
||||
if string.len(v) >= 8 then network.init_mac(tmp_cfg.AuthKey) end
|
||||
|
||||
-- prep supervisor connection screen
|
||||
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()
|
||||
main_pane.set_value(3)
|
||||
|
||||
tcd.dispatch_unique(2, function () tool_ctl.sv_skip.enable() end)
|
||||
else key_err.show() 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."}
|
||||
|
||||
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=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_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()
|
||||
-- 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."}
|
||||
|
||||
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}
|
||||
|
||||
@ -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)}
|
||||
|
||||
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()
|
||||
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()
|
||||
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(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}
|
||||
|
||||
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
|
||||
TextBox{parent=c_log,text=change[1],height=1,fg_bg=bw_fg_bg}
|
||||
|
@ -121,8 +121,11 @@ function coordinator.load_config()
|
||||
monitors.primary = ppm.get_periph(config.MainDisplay)
|
||||
monitors.primary_name = config.MainDisplay
|
||||
|
||||
monitors.primary.setTextScale(0.5)
|
||||
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 util.table_contains(names, config.FlowDisplay) then
|
||||
@ -132,8 +135,11 @@ function coordinator.load_config()
|
||||
monitors.flow = ppm.get_periph(config.FlowDisplay)
|
||||
monitors.flow_name = config.FlowDisplay
|
||||
|
||||
monitors.flow.setTextScale(0.5)
|
||||
w, _ = ppm.monitor_block_size(monitors.flow.getSize())
|
||||
if w ~= 8 then return 2, "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
|
||||
|
||||
for i = 1, config.UnitCount do
|
||||
@ -145,8 +151,11 @@ function coordinator.load_config()
|
||||
monitors.unit_displays[i] = ppm.get_periph(display)
|
||||
monitors.unit_name_map[i] = display
|
||||
|
||||
monitors.unit_displays[i].setTextScale(0.5)
|
||||
w, h = ppm.monitor_block_size(monitors.unit_displays[i].getSize())
|
||||
if w ~= 4 or h ~= 4 then return 2, "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
|
||||
else return 2, "Monitor configuration invalid." end
|
||||
end
|
||||
|
@ -22,7 +22,7 @@ local sounder = require("coordinator.sounder")
|
||||
|
||||
local apisessions = require("coordinator.session.apisessions")
|
||||
|
||||
local COORDINATOR_VERSION = "v1.2.0"
|
||||
local COORDINATOR_VERSION = "v1.2.1"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
@ -79,6 +79,9 @@ local function main()
|
||||
-- system startup
|
||||
----------------------------------------
|
||||
|
||||
-- re-mount devices now that logging is ready
|
||||
ppm.mount_all()
|
||||
|
||||
-- report versions/init fp PSIL
|
||||
iocontrol.init_fp(COORDINATOR_VERSION, comms.version)
|
||||
|
||||
|
@ -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
578
pocket/configure.lua
Normal 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
|
@ -13,17 +13,57 @@ local LINK_STATE = iocontrol.LINK_STATE
|
||||
|
||||
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
|
||||
---@nodiscard
|
||||
---@param version string pocket version
|
||||
---@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 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 = {
|
||||
sv = {
|
||||
linked = false,
|
||||
@ -42,13 +82,13 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
establish_delay_counter = 0
|
||||
}
|
||||
|
||||
comms.set_trusted_range(range)
|
||||
comms.set_trusted_range(config.TrustedRange)
|
||||
|
||||
-- PRIVATE FUNCTIONS --
|
||||
|
||||
-- configure network channels
|
||||
nic.closeAll()
|
||||
nic.open(pkt_channel)
|
||||
nic.open(config.PKT_Channel)
|
||||
|
||||
-- send a management packet to the supervisor
|
||||
---@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)
|
||||
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
|
||||
end
|
||||
|
||||
@ -74,7 +114,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
pkt.make(msg_type, msg)
|
||||
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
|
||||
end
|
||||
|
||||
@ -217,9 +257,9 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
local protocol = packet.scada_frame.protocol()
|
||||
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)
|
||||
elseif r_chan == crd_channel then
|
||||
elseif r_chan == config.CRD_Channel then
|
||||
-- check sequence number
|
||||
if self.api.r_seq_num == nil then
|
||||
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
|
||||
log.debug("illegal packet type " .. protocol .. " from coordinator", true)
|
||||
end
|
||||
elseif r_chan == svr_channel then
|
||||
elseif r_chan == config.SVR_Channel then
|
||||
-- check sequence number
|
||||
if self.sv.r_seq_num == nil then
|
||||
self.sv.r_seq_num = packet.scada_frame.seq_num()
|
||||
|
@ -13,38 +13,37 @@ local util = require("scada-common.util")
|
||||
|
||||
local core = require("graphics.core")
|
||||
|
||||
local config = require("pocket.config")
|
||||
local configure = require("pocket.configure")
|
||||
local iocontrol = require("pocket.iocontrol")
|
||||
local pocket = require("pocket.pocket")
|
||||
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_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)
|
||||
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")
|
||||
local config = pocket.config
|
||||
|
||||
----------------------------------------
|
||||
-- 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("BOOTING pocket.startup " .. POCKET_VERSION)
|
||||
@ -69,8 +68,8 @@ local function main()
|
||||
----------------------------------------
|
||||
|
||||
-- message authentication init
|
||||
if type(config.AUTH_KEY) == "string" then
|
||||
network.init_mac(config.AUTH_KEY)
|
||||
if type(config.AuthKey) == "string" and string.len(config.AuthKey) > 0 then
|
||||
network.init_mac(config.AuthKey)
|
||||
end
|
||||
|
||||
iocontrol.report_link_state(iocontrol.LINK_STATE.UNLINKED)
|
||||
@ -85,8 +84,8 @@ local function main()
|
||||
|
||||
-- create connection watchdogs
|
||||
local conn_wd = {
|
||||
sv = util.new_watchdog(config.COMMS_TIMEOUT),
|
||||
api = util.new_watchdog(config.COMMS_TIMEOUT)
|
||||
sv = util.new_watchdog(config.ConnTimeout),
|
||||
api = util.new_watchdog(config.ConnTimeout)
|
||||
}
|
||||
|
||||
conn_wd.sv.cancel()
|
||||
@ -96,8 +95,7 @@ local function main()
|
||||
|
||||
-- create network interface then setup comms
|
||||
local nic = network.nic(modem)
|
||||
local pocket_comms = pocket.comms(POCKET_VERSION, nic, config.PKT_CHANNEL, config.SVR_CHANNEL,
|
||||
config.CRD_CHANNEL, config.TRUSTED_RANGE, conn_wd.sv, conn_wd.api)
|
||||
local pocket_comms = pocket.comms(POCKET_VERSION, nic, conn_wd.sv, conn_wd.api)
|
||||
log.debug("startup> comms init")
|
||||
|
||||
-- base loop clock (2Hz, 10 ticks)
|
||||
|
@ -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}}
|
||||
|
||||
-- MAIN PAGE
|
||||
-- Main Page
|
||||
|
||||
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=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_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=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_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=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}
|
||||
|
||||
@ -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=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_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)}
|
||||
|
||||
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()
|
||||
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()
|
||||
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(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=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}
|
||||
|
||||
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
|
||||
TextBox{parent=c_log,text=change[1],height=1,fg_bg=bw_fg_bg}
|
||||
@ -646,7 +654,7 @@ local function reset_term()
|
||||
end
|
||||
|
||||
-- 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)
|
||||
tool_ctl.ask_config = ask_config == true
|
||||
|
||||
|
@ -18,7 +18,7 @@ local plc = require("reactor-plc.plc")
|
||||
local renderer = require("reactor-plc.renderer")
|
||||
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_ts = util.println_ts
|
||||
|
@ -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}}
|
||||
|
||||
--#region MAIN PAGE
|
||||
--#region Main Page
|
||||
|
||||
local y_start = 2
|
||||
|
||||
@ -324,7 +324,7 @@ local function config_view(display)
|
||||
|
||||
--#endregion
|
||||
|
||||
--#region SPEAKER CONFIG
|
||||
--#region Speakers
|
||||
|
||||
local spkr_c = Div{parent=spkr_cfg,x=2,y=4,width=49}
|
||||
|
||||
@ -353,7 +353,7 @@ local function config_view(display)
|
||||
|
||||
--#endregion
|
||||
|
||||
--#region NET CONFIG
|
||||
--#region Network
|
||||
|
||||
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}
|
||||
@ -455,7 +455,7 @@ local function config_view(display)
|
||||
|
||||
--#endregion
|
||||
|
||||
--#region LOG CONFIG
|
||||
--#region Logging
|
||||
|
||||
local log_c_1 = Div{parent=log_cfg,x=2,y=4,width=49}
|
||||
|
||||
@ -494,7 +494,7 @@ local function config_view(display)
|
||||
|
||||
--#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_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)}
|
||||
|
||||
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()
|
||||
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("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(ini_cfg)
|
||||
|
||||
@ -578,13 +578,13 @@ local function config_view(display)
|
||||
tool_ctl.settings_confirm.hide()
|
||||
|
||||
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=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:"}
|
||||
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=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
|
||||
|
||||
--#region CONFIG CHANGE LOG
|
||||
--#region Config Change Log
|
||||
|
||||
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}
|
||||
|
||||
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
|
||||
TextBox{parent=c_log,text=change[1],height=1,fg_bg=bw_fg_bg}
|
||||
@ -635,7 +635,7 @@ local function config_view(display)
|
||||
|
||||
--#endregion
|
||||
|
||||
--#region DEVICES
|
||||
--#region Peripherals
|
||||
|
||||
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}
|
||||
@ -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)}
|
||||
|
||||
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()
|
||||
tmp_cfg.Peripherals = deep_copy_peri(ini_cfg.Peripherals)
|
||||
@ -659,7 +659,7 @@ local function config_view(display)
|
||||
local function peri_apply()
|
||||
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(ini_cfg)
|
||||
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."}
|
||||
|
||||
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=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
|
||||
|
||||
--#region REDSTONE
|
||||
--#region Redstone
|
||||
|
||||
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}
|
||||
@ -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_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()
|
||||
tmp_cfg.Redstone = deep_copy_rs(ini_cfg.Redstone)
|
||||
@ -973,7 +973,7 @@ local function config_view(display)
|
||||
local function rs_apply()
|
||||
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(ini_cfg)
|
||||
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."}
|
||||
|
||||
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)
|
||||
if (rsio.get_io_dir(port) == rsio.IO_DIR.IN) then
|
||||
@ -1466,7 +1466,7 @@ local function reset_term()
|
||||
end
|
||||
|
||||
-- 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)
|
||||
tool_ctl.ask_config = ask_config == true
|
||||
|
||||
|
@ -31,7 +31,7 @@ local sna_rtu = require("rtu.dev.sna_rtu")
|
||||
local sps_rtu = require("rtu.dev.sps_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_HW_STATE = databus.RTU_UNIT_HW_STATE
|
||||
|
@ -17,7 +17,7 @@ local max_distance = nil
|
||||
local comms = {}
|
||||
|
||||
-- protocol/data version (protocol/data independent changes tracked by util.lua version)
|
||||
comms.version = "2.4.3"
|
||||
comms.version = "2.4.4"
|
||||
|
||||
---@enum PROTOCOL
|
||||
local PROTOCOL = {
|
||||
|
@ -7,7 +7,7 @@ local log = require("scada-common.log")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
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 hmac = require("lockbox.mac.hmac")
|
||||
local stream = require("lockbox.util.stream")
|
||||
@ -31,12 +31,12 @@ function network.init_mac(passkey)
|
||||
local key_deriv = 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.setIterations(32)
|
||||
key_deriv.setBlockLen(8)
|
||||
key_deriv.setDKeyLen(16)
|
||||
key_deriv.setPRF(hmac().setBlockSize(64).setDigest(sha256))
|
||||
key_deriv.setPassword(passkey)
|
||||
key_deriv.finish()
|
||||
|
||||
c_eng.key = array.fromHex(key_deriv.asHex())
|
||||
|
@ -22,7 +22,7 @@ local t_pack = table.pack
|
||||
local util = {}
|
||||
|
||||
-- scada-common version
|
||||
util.version = "1.1.13"
|
||||
util.version = "1.1.14"
|
||||
|
||||
util.TICK_TIME_S = 0.05
|
||||
util.TICK_TIME_MS = 50
|
||||
|
@ -2,7 +2,7 @@ local util = require("scada-common.util")
|
||||
|
||||
local println = util.println
|
||||
|
||||
local BOOTLOADER_VERSION = "0.6"
|
||||
local BOOTLOADER_VERSION = "1.0"
|
||||
|
||||
println("SCADA BOOTLOADER V" .. BOOTLOADER_VERSION)
|
||||
println("BOOT> SCANNING FOR APPLICATIONS...")
|
||||
|
@ -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}}
|
||||
|
||||
-- MAIN PAGE
|
||||
-- Main Page
|
||||
|
||||
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=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_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}
|
||||
|
||||
-- NET CONFIG
|
||||
--#endregion
|
||||
|
||||
--#region Network
|
||||
|
||||
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}
|
||||
@ -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=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}
|
||||
|
||||
@ -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=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_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)}
|
||||
|
||||
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()
|
||||
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()
|
||||
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(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=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}
|
||||
|
||||
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
|
||||
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}
|
||||
|
||||
-- IMPORT ERROR
|
||||
-- Import Error
|
||||
|
||||
local i_err = Div{parent=import_err,x=2,y=4,width=49}
|
||||
|
||||
@ -1033,7 +1041,7 @@ local function reset_term()
|
||||
end
|
||||
|
||||
-- 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)
|
||||
tool_ctl.ask_config = ask_config == true
|
||||
|
||||
|
@ -21,7 +21,7 @@ local supervisor = require("supervisor.supervisor")
|
||||
|
||||
local svsessions = require("supervisor.session.svsessions")
|
||||
|
||||
local SUPERVISOR_VERSION = "v1.2.6"
|
||||
local SUPERVISOR_VERSION = "v1.2.7"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
Loading…
Reference in New Issue
Block a user