#580 reactor PLC wired/wireless configurator updates, RTU gateway and supervisor updates to theirs as well

This commit is contained in:
Mikayla Fischler 2025-10-26 20:31:35 -04:00
parent 2fefe4fbd6
commit 96acb03f73
5 changed files with 240 additions and 79 deletions

View File

@ -1,4 +1,5 @@
local log = require("scada-common.log") local log = require("scada-common.log")
local ppm = require("scada-common.ppm")
local rsio = require("scada-common.rsio") local rsio = require("scada-common.rsio")
local util = require("scada-common.util") local util = require("scada-common.util")
@ -20,6 +21,8 @@ local TextField = require("graphics.elements.form.TextField")
local IndLight = require("graphics.elements.indicators.IndicatorLight") local IndLight = require("graphics.elements.indicators.IndicatorLight")
local tri = util.trinary
local cpair = core.cpair local cpair = core.cpair
local RIGHT = core.ALIGN.RIGHT local RIGHT = core.ALIGN.RIGHT
@ -30,6 +33,8 @@ local self = {
set_networked = nil, ---@type function set_networked = nil, ---@type function
bundled_emcool = nil, ---@type function bundled_emcool = nil, ---@type function
wl_pref = nil, ---@type Checkbox
range = nil, ---@type NumberField
show_auth_key = nil, ---@type function show_auth_key = nil, ---@type function
show_key_btn = nil, ---@type PushButton show_key_btn = nil, ---@type PushButton
auth_key_textbox = nil, ---@type TextBox auth_key_textbox = nil, ---@type TextBox
@ -161,7 +166,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
local function submit_emcool() local function submit_emcool()
tmp_cfg.EmerCoolSide = side_options_map[side.get_value()] tmp_cfg.EmerCoolSide = side_options_map[side.get_value()]
tmp_cfg.EmerCoolColor = util.trinary(bundled.get_value(), color_options_map[color.get_value()], nil) tmp_cfg.EmerCoolColor = tri(bundled.get_value(), color_options_map[color.get_value()], nil)
tmp_cfg.EmerCoolInvert = invert.get_value() tmp_cfg.EmerCoolInvert = invert.get_value()
next_from_plc() next_from_plc()
end end
@ -177,22 +182,77 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
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}
local net_c_3 = Div{parent=net_cfg,x=2,y=4,width=49} local net_c_3 = Div{parent=net_cfg,x=2,y=4,width=49}
local net_c_4 = Div{parent=net_cfg,x=2,y=4,width=49}
local net_pane = MultiPane{parent=net_cfg,x=1,y=4,panes={net_c_1,net_c_2,net_c_3}} 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,text=" Network Configuration",fg_bg=cpair(colors.black,colors.lightBlue)} TextBox{parent=net_cfg,x=1,y=2,text=" Network Configuration",fg_bg=cpair(colors.black,colors.lightBlue)}
TextBox{parent=net_c_1,x=1,y=1,text="Please set the network channels below."} TextBox{parent=net_c_1,x=1,y=1,text="Please select the network interface(s)."}
TextBox{parent=net_c_1,x=1,y=3,height=4,text="Each of the 5 uniquely named channels, including the 2 below, must be the same for each device in this SCADA network. For multiplayer servers, it is recommended to not use the default channels.",fg_bg=g_lg_fg_bg} TextBox{parent=net_c_1,x=41,y=1,text="new!",fg_bg=cpair(colors.red,colors._INHERIT)} ---@todo remove NEW tag on next revision
TextBox{parent=net_c_1,x=1,y=8,text="Supervisor Channel"} local function dis_pref(value)
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} if not value then
TextBox{parent=net_c_1,x=9,y=9,height=4,text="[SVR_CHANNEL]",fg_bg=g_lg_fg_bg} self.wl_pref.set_value(false)
TextBox{parent=net_c_1,x=1,y=11,text="PLC Channel"} self.wl_pref.disable()
local plc_chan = NumberField{parent=net_c_1,x=1,y=12,width=7,default=ini_cfg.PLC_Channel,min=1,max=65535,fg_bg=bw_fg_bg} else self.wl_pref.enable() end
TextBox{parent=net_c_1,x=9,y=12,height=4,text="[PLC_CHANNEL]",fg_bg=g_lg_fg_bg} end
local chan_err = TextBox{parent=net_c_1,x=8,y=14,width=35,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} local function on_wired_change(_) tool_ctl.gen_modem_list() end
local wireless = Checkbox{parent=net_c_1,x=1,y=3,label="Wireless/Ender Modem",default=ini_cfg.WirelessModem,box_fg_bg=cpair(colors.lightBlue,colors.black),callback=dis_pref}
self.wl_pref = Checkbox{parent=net_c_1,x=30,y=3,label="Prefer Wireless",default=ini_cfg.PreferWireless,box_fg_bg=cpair(colors.lightBlue,colors.black),disable_fg_bg=g_lg_fg_bg}
local wired = Checkbox{parent=net_c_1,x=1,y=5,label="Wired Modem",default=ini_cfg.WiredModem~=false,box_fg_bg=cpair(colors.lightBlue,colors.black),callback=on_wired_change}
TextBox{parent=net_c_1,x=3,y=6,text="MUST ONLY connect to SCADA computers",fg_bg=cpair(colors.red,colors._INHERIT)}
TextBox{parent=net_c_1,x=3,y=7,text="connecting to peripherals will cause problems",fg_bg=g_lg_fg_bg}
local modem_list = ListBox{parent=net_c_1,x=1,y=8,height=5,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 modem_err = TextBox{parent=net_c_1,x=8,y=14,width=35,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
dis_pref(ini_cfg.WirelessModem)
local function submit_interfaces()
tmp_cfg.WirelessModem = wireless.get_value()
tmp_cfg.PreferWireless = tmp_cfg.WirelessModem and self.wl_pref.get_value()
if not wired.get_value() then
tmp_cfg.WiredModem = false
tool_ctl.gen_modem_list()
end
if not (wired.get_value() or wireless.get_value()) then
modem_err.set_value("Please select a modem type.")
modem_err.show()
elseif wired.get_value() and type(tmp_cfg.WiredModem) ~= "string" then
modem_err.set_value("Please select a wired modem.")
modem_err.show()
else
if tmp_cfg.WirelessModem then
self.range.enable()
else
self.range.set_value(0)
self.range.disable()
end
net_pane.set_value(2)
modem_err.hide(true)
end
end
PushButton{parent=net_c_1,x=1,y=14,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=net_c_1,x=44,y=14,text="Next \x1a",callback=submit_interfaces,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
TextBox{parent=net_c_2,x=1,y=1,text="Please set the network channels below."}
TextBox{parent=net_c_2,x=1,y=3,height=4,text="Each of the 5 uniquely named channels, including the 2 below, must be the same for each device in this SCADA network. For multiplayer servers, it is recommended to not use the default channels.",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_2,x=1,y=8,text="Supervisor Channel"}
local svr_chan = NumberField{parent=net_c_2,x=1,y=9,width=7,default=ini_cfg.SVR_Channel,min=1,max=65535,fg_bg=bw_fg_bg}
TextBox{parent=net_c_2,x=9,y=9,height=4,text="[SVR_CHANNEL]",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_2,x=1,y=11,text="PLC Channel"}
local plc_chan = NumberField{parent=net_c_2,x=1,y=12,width=7,default=ini_cfg.PLC_Channel,min=1,max=65535,fg_bg=bw_fg_bg}
TextBox{parent=net_c_2,x=9,y=12,height=4,text="[PLC_CHANNEL]",fg_bg=g_lg_fg_bg}
local chan_err = TextBox{parent=net_c_2,x=8,y=14,width=35,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
local function submit_channels() local function submit_channels()
local svr_c = tonumber(svr_chan.get_value()) local svr_c = tonumber(svr_chan.get_value())
@ -200,7 +260,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
if svr_c ~= nil and plc_c ~= nil then if svr_c ~= nil and plc_c ~= nil then
tmp_cfg.SVR_Channel = svr_c tmp_cfg.SVR_Channel = svr_c
tmp_cfg.PLC_Channel = plc_c tmp_cfg.PLC_Channel = plc_c
net_pane.set_value(2) net_pane.set_value(3)
chan_err.hide(true) chan_err.hide(true)
elseif svr_c == nil then elseif svr_c == nil then
chan_err.set_value("Please set the supervisor channel.") chan_err.set_value("Please set the supervisor channel.")
@ -211,54 +271,62 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
end end
end end
PushButton{parent=net_c_1,x=1,y=14,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=net_c_2,x=1,y=14,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_1,x=44,y=14,text="Next \x1a",callback=submit_channels,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=net_c_2,x=44,y=14,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,text="Connection Timeout"} TextBox{parent=net_c_3,x=1,y=1,text="Connection Timeout"}
local timeout = NumberField{parent=net_c_2,x=1,y=2,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} local timeout = NumberField{parent=net_c_3,x=1,y=2,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=2,height=2,text="seconds (default 5)",fg_bg=g_lg_fg_bg} TextBox{parent=net_c_3,x=9,y=2,height=2,text="seconds (default 5)",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_2,x=1,y=3,height=4,text="You generally do not want or need to modify this. On slow servers, you can increase this to make the system wait longer before assuming a disconnection.",fg_bg=g_lg_fg_bg} TextBox{parent=net_c_3,x=1,y=3,height=4,text="You generally do not want or need to modify this. On slow servers, you can 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=8,text="Trusted Range"} TextBox{parent=net_c_3,x=1,y=8,text="Trusted Range (Wireless Only)"}
local range = NumberField{parent=net_c_2,x=1,y=9,width=10,default=ini_cfg.TrustedRange,min=0,max_chars=20,allow_decimal=true,fg_bg=bw_fg_bg} self.range = NumberField{parent=net_c_3,x=1,y=9,width=10,default=ini_cfg.TrustedRange,min=0,max_chars=20,allow_decimal=true,fg_bg=bw_fg_bg,dis_fg_bg=cpair(colors.lightGray,colors.white)}
TextBox{parent=net_c_2,x=1,y=10,height=4,text="Setting this to a value larger than 0 prevents connections with devices that many meters (blocks) away in any direction.",fg_bg=g_lg_fg_bg} TextBox{parent=net_c_3,x=1,y=10,height=4,text="Setting this to a value larger than 0 prevents wireless connections with devices that many meters (blocks) away in any direction.",fg_bg=g_lg_fg_bg}
local p2_err = TextBox{parent=net_c_2,x=8,y=14,width=35,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} local n3_err = TextBox{parent=net_c_3,x=8,y=14,width=35,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
local function submit_ct_tr() local function submit_ct_tr()
local timeout_val = tonumber(timeout.get_value()) local timeout_val = tonumber(timeout.get_value())
local range_val = tonumber(range.get_value()) local range_val = tonumber(self.range.get_value())
if timeout_val ~= nil and range_val ~= nil then
tmp_cfg.ConnTimeout = timeout_val if timeout_val == nil then
tmp_cfg.TrustedRange = range_val n3_err.set_value("Please set the connection timeout.")
net_pane.set_value(3) n3_err.show()
p2_err.hide(true) elseif tmp_cfg.WirelessModem and (range_val == nil) then
elseif timeout_val == nil then n3_err.set_value("Please set the trusted range.")
p2_err.set_value("Please set the connection timeout.") n3_err.show()
p2_err.show()
else else
p2_err.set_value("Please set the trusted range.") tmp_cfg.ConnTimeout = timeout_val
p2_err.show() tmp_cfg.TrustedRange = tri(tmp_cfg.WirelessModem, range_val, 0)
if tmp_cfg.WirelessModem then
net_pane.set_value(4)
else
main_pane.set_value(4)
tmp_cfg.AuthKey = ""
end
n3_err.hide(true)
end end
end end
PushButton{parent=net_c_2,x=1,y=14,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_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_2,x=44,y=14,text="Next \x1a",callback=submit_ct_tr,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_ct_tr,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
TextBox{parent=net_c_3,x=1,y=1,height=2,text="Optionally, set the facility authentication key below. Do NOT use one of your passwords."} TextBox{parent=net_c_4,x=1,y=1,height=2,text="Optionally, set the facility authentication key below. Do NOT use one of your passwords."}
TextBox{parent=net_c_3,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for security on multiplayer servers. All devices on the same network MUST use the same key if any device has a key. This does result in some extra computation (can slow things down).",fg_bg=g_lg_fg_bg} TextBox{parent=net_c_4,x=1,y=4,height=6,text="This enables verifying that messages are authentic, so it is intended for wireless security on multiplayer servers. All devices on the same wireless network MUST use the same key if any device has a key. This does result in some extra computation (can slow things down).",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_3,x=1,y=11,text="Facility Auth Key"} TextBox{parent=net_c_4,x=1,y=11,text="Auth Key (Wireless Only, Not Used for Wired)"}
local key, _ = TextField{parent=net_c_3,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg} local key, _ = TextField{parent=net_c_4,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=bw_fg_bg}
local function censor_key(enable) key.censor(util.trinary(enable, "*", nil)) end local function censor_key(enable) key.censor(tri(enable, "*", nil)) end
local hide_key = Checkbox{parent=net_c_3,x=34,y=12,label="Hide",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key} local hide_key = Checkbox{parent=net_c_4,x=34,y=12,label="Hide",box_fg_bg=cpair(colors.lightBlue,colors.black),callback=censor_key}
hide_key.set_value(true) hide_key.set_value(true)
censor_key(true) censor_key(true)
local key_err = TextBox{parent=net_c_3,x=8,y=14,width=35,text="Key must be at least 8 characters.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} local key_err = TextBox{parent=net_c_4,x=8,y=14,width=35,text="Key must be at least 8 characters.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
local function submit_auth() local function submit_auth()
local v = key.get_value() local v = key.get_value()
@ -269,8 +337,8 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
else key_err.show() end else key_err.show() end
end end
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_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_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_4,x=44,y=14,text="Next \x1a",callback=submit_auth,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
--#endregion --#endregion
@ -368,7 +436,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
PushButton{parent=clr_c_2,x=44,y=14,min_width=6,text="Done",callback=function()clr_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} PushButton{parent=clr_c_2,x=44,y=14,min_width=6,text="Done",callback=function()clr_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
local function back_from_colors() local function back_from_colors()
main_pane.set_value(util.trinary(tool_ctl.jumped_to_color, 1, 4)) main_pane.set_value(tri(tool_ctl.jumped_to_color, 1, 4))
tool_ctl.jumped_to_color = false tool_ctl.jumped_to_color = false
recolor(1) recolor(1)
end end
@ -471,10 +539,13 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
try_set(bundled, ini_cfg.EmerCoolColor ~= nil) try_set(bundled, ini_cfg.EmerCoolColor ~= nil)
if ini_cfg.EmerCoolColor ~= nil then try_set(color, color_to_idx(ini_cfg.EmerCoolColor)) end if ini_cfg.EmerCoolColor ~= nil then try_set(color, color_to_idx(ini_cfg.EmerCoolColor)) end
try_set(invert, ini_cfg.EmerCoolInvert) try_set(invert, ini_cfg.EmerCoolInvert)
try_set(wireless, ini_cfg.WirelessModem)
try_set(wired, ini_cfg.WiredModem ~= false)
try_set(self.wl_pref, ini_cfg.PreferWireless)
try_set(svr_chan, ini_cfg.SVR_Channel) try_set(svr_chan, ini_cfg.SVR_Channel)
try_set(plc_chan, ini_cfg.PLC_Channel) try_set(plc_chan, ini_cfg.PLC_Channel)
try_set(timeout, ini_cfg.ConnTimeout) try_set(timeout, ini_cfg.ConnTimeout)
try_set(range, ini_cfg.TrustedRange) try_set(self.range, ini_cfg.TrustedRange)
try_set(key, ini_cfg.AuthKey) try_set(key, ini_cfg.AuthKey)
try_set(mode, ini_cfg.LogMode) try_set(mode, ini_cfg.LogMode)
try_set(path, ini_cfg.LogPath) try_set(path, ini_cfg.LogPath)
@ -591,7 +662,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
local val = util.strval(raw) local val = util.strval(raw)
if f[1] == "AuthKey" and raw then val = string.rep("*", string.len(val)) if f[1] == "AuthKey" and raw then val = string.rep("*", string.len(val))
elseif f[1] == "LogMode" then val = util.trinary(raw == log.MODE.APPEND, "append", "replace") elseif f[1] == "LogMode" then val = tri(raw == log.MODE.APPEND, "append", "replace")
elseif f[1] == "EmerCoolColor" and raw ~= nil then val = rsio.color_name(raw) elseif f[1] == "EmerCoolColor" and raw ~= nil then val = rsio.color_name(raw)
elseif f[1] == "FrontPanelTheme" then elseif f[1] == "FrontPanelTheme" then
val = util.strval(themes.fp_theme_name(raw)) val = util.strval(themes.fp_theme_name(raw))
@ -601,7 +672,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
if val == "nil" then val = "<not set>" end if val == "nil" then val = "<not set>" end
local c = util.trinary(alternate, g_lg_fg_bg, cpair(colors.gray,colors.white)) local c = tri(alternate, g_lg_fg_bg, cpair(colors.gray,colors.white))
alternate = not alternate alternate = not alternate
if (string.len(val) > val_max_w) or string.find(val, "\n") then if (string.len(val) > val_max_w) or string.find(val, "\n") then
@ -623,6 +694,59 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, style, exit)
end end
end end
-- generate the list of available/assigned wired modems
function tool_ctl.gen_modem_list()
modem_list.remove_all()
local enable = wired.get_value()
local function select(iface)
tmp_cfg.WiredModem = iface
tool_ctl.gen_modem_list()
end
local modems = ppm.get_wired_modem_list()
local missing = { tmp = true, ini = true }
for iface, _ in pairs(modems) do
if ini_cfg.WiredModem == iface then missing.ini = false end
if tmp_cfg.WiredModem == iface then missing.tmp = false end
end
if missing.tmp and tmp_cfg.WiredModem then
local line = Div{parent=modem_list,x=1,y=1,height=1}
TextBox{parent=line,x=1,y=1,width=4,text="Used",fg_bg=cpair(tri(enable,colors.blue,colors.gray),colors.white)}
PushButton{parent=line,x=6,y=1,min_width=8,height=1,text="SELECT",callback=function()end,fg_bg=cpair(colors.black,colors.lightBlue),active_fg_bg=btn_act_fg_bg,dis_fg_bg=g_lg_fg_bg}.disable()
TextBox{parent=line,x=15,y=1,text="[missing]",fg_bg=cpair(colors.red,colors.white)}
TextBox{parent=line,x=25,y=1,text=tmp_cfg.WiredModem}
end
if missing.ini and ini_cfg.WiredModem and (tmp_cfg.WiredModem ~= ini_cfg.WiredModem) then
local line = Div{parent=modem_list,x=1,y=1,height=1}
local used = tmp_cfg.WiredModem == ini_cfg.WiredModem
TextBox{parent=line,x=1,y=1,width=4,text=tri(used,"Used","----"),fg_bg=cpair(tri(used and enable,colors.blue,colors.gray),colors.white)}
local select_btn = PushButton{parent=line,x=6,y=1,min_width=8,height=1,text="SELECT",callback=function()select(ini_cfg.WiredModem)end,fg_bg=cpair(colors.black,colors.lightBlue),active_fg_bg=btn_act_fg_bg,dis_fg_bg=g_lg_fg_bg}
TextBox{parent=line,x=15,y=1,text="[missing]",fg_bg=cpair(colors.red,colors.white)}
TextBox{parent=line,x=25,y=1,text=ini_cfg.WiredModem}
if used or not enable then select_btn.disable() end
end
-- list wired modems
for iface, _ in pairs(modems) do
local line = Div{parent=modem_list,x=1,y=1,height=1}
local used = tmp_cfg.WiredModem == iface
TextBox{parent=line,x=1,y=1,width=4,text=tri(used,"Used","----"),fg_bg=cpair(tri(used and enable,colors.blue,colors.gray),colors.white)}
local select_btn = PushButton{parent=line,x=6,y=1,min_width=8,height=1,text="SELECT",callback=function()select(iface)end,fg_bg=cpair(colors.black,colors.lightBlue),active_fg_bg=btn_act_fg_bg,dis_fg_bg=g_lg_fg_bg}
TextBox{parent=line,x=15,y=1,text=iface}
if used or not enable then select_btn.disable() end
end
end
--#endregion --#endregion
end end

View File

@ -3,6 +3,7 @@
-- --
local log = require("scada-common.log") local log = require("scada-common.log")
local ppm = require("scada-common.ppm")
local tcd = require("scada-common.tcd") local tcd = require("scada-common.tcd")
local util = require("scada-common.util") local util = require("scada-common.util")
@ -33,7 +34,8 @@ local changes = {
{ "v1.6.8", { "ConnTimeout can now have a fractional part" } }, { "v1.6.8", { "ConnTimeout can now have a fractional part" } },
{ "v1.6.15", { "Added front panel UI theme", "Added color accessibility modes" } }, { "v1.6.15", { "Added front panel UI theme", "Added color accessibility modes" } },
{ "v1.7.3", { "Added standard with black off state color mode", "Added blue indicator color modes" } }, { "v1.7.3", { "Added standard with black off state color mode", "Added blue indicator color modes" } },
{ "v1.8.21", { "Added option to invert emergency coolant redstone control" } } { "v1.8.21", { "Added option to invert emergency coolant redstone control" } },
{ "v1.9.1", { "Added support for wired communications modems" } }
} }
---@class plc_configurator ---@class plc_configurator
@ -68,6 +70,8 @@ local tool_ctl = {
gen_summary = nil, ---@type function gen_summary = nil, ---@type function
load_legacy = nil, ---@type function load_legacy = nil, ---@type function
gen_modem_list = function () end
} }
---@class plc_config ---@class plc_config
@ -78,12 +82,12 @@ local tmp_cfg = {
EmerCoolSide = nil, ---@type string|nil EmerCoolSide = nil, ---@type string|nil
EmerCoolColor = nil, ---@type color|nil EmerCoolColor = nil, ---@type color|nil
EmerCoolInvert = false, ---@type boolean EmerCoolInvert = false, ---@type boolean
SVR_Channel = nil, ---@type integer
PLC_Channel = nil, ---@type integer
ConnTimeout = nil, ---@type number
WirelessModem = true, WirelessModem = true,
WiredModem = false, ---@type string|false WiredModem = false, ---@type string|false
PreferWireless = true, PreferWireless = true,
SVR_Channel = nil, ---@type integer
PLC_Channel = nil, ---@type integer
ConnTimeout = nil, ---@type number
TrustedRange = nil, ---@type number TrustedRange = nil, ---@type number
AuthKey = nil, ---@type string|nil AuthKey = nil, ---@type string|nil
LogMode = 0, ---@type LOG_MODE LogMode = 0, ---@type LOG_MODE
@ -106,12 +110,12 @@ local fields = {
{ "EmerCoolSide", "Emergency Coolant Side", nil }, { "EmerCoolSide", "Emergency Coolant Side", nil },
{ "EmerCoolColor", "Emergency Coolant Color", nil }, { "EmerCoolColor", "Emergency Coolant Color", nil },
{ "EmerCoolInvert", "Emergency Coolant Invert", false }, { "EmerCoolInvert", "Emergency Coolant Invert", false },
{ "SVR_Channel", "SVR Channel", 16240 },
{ "PLC_Channel", "PLC Channel", 16241 },
{ "ConnTimeout", "Connection Timeout", 5 },
{ "WirelessModem", "Wireless/Ender Comms Modem", true }, { "WirelessModem", "Wireless/Ender Comms Modem", true },
{ "WiredModem", "Wired Comms Modem", false }, { "WiredModem", "Wired Comms Modem", false },
{ "PreferWireless", "Prefer Wireless Modem", true }, { "PreferWireless", "Prefer Wireless Modem", true },
{ "SVR_Channel", "SVR Channel", 16240 },
{ "PLC_Channel", "PLC Channel", 16241 },
{ "ConnTimeout", "Connection Timeout", 5 },
{ "TrustedRange", "Trusted Range", 0 }, { "TrustedRange", "Trusted Range", 0 },
{ "AuthKey", "Facility Auth Key" , ""}, { "AuthKey", "Facility Auth Key" , ""},
{ "LogMode", "Log Mode", log.MODE.APPEND }, { "LogMode", "Log Mode", log.MODE.APPEND },
@ -267,8 +271,13 @@ function configurator.configure(ask_config)
load_settings(settings_cfg, true) load_settings(settings_cfg, true)
tool_ctl.has_config = load_settings(ini_cfg) tool_ctl.has_config = load_settings(ini_cfg)
-- set tmp_cfg so interface lists are correct
tmp_cfg.WiredModem = ini_cfg.WiredModem
reset_term() reset_term()
ppm.mount_all()
-- set overridden colors -- set overridden colors
for i = 1, #style.colors do for i = 1, #style.colors do
term.setPaletteColor(style.colors[i].c, style.colors[i].hex) term.setPaletteColor(style.colors[i].c, style.colors[i].hex)
@ -278,6 +287,8 @@ function configurator.configure(ask_config)
local display = DisplayBox{window=term.current(),fg_bg=style.root} local display = DisplayBox{window=term.current(),fg_bg=style.root}
config_view(display) config_view(display)
tool_ctl.gen_modem_list()
while true do while true do
local event, param1, param2, param3, param4, param5 = util.pull_event() local event, param1, param2, param3, param4, param5 = util.pull_event()
@ -294,6 +305,14 @@ function configurator.configure(ask_config)
display.handle_paste(param1) display.handle_paste(param1)
elseif event == "modem_message" then elseif event == "modem_message" then
check.receive_sv(param1, param2, param3, param4, param5) check.receive_sv(param1, param2, param3, param4, param5)
elseif event == "peripheral_detach" then
---@diagnostic disable-next-line: discard-returns
ppm.handle_unmount(param1)
tool_ctl.gen_modem_list()
elseif event == "peripheral" then
---@diagnostic disable-next-line: discard-returns
ppm.mount(param1)
tool_ctl.gen_modem_list()
end end
if event == "terminate" then return end if event == "terminate" then return end

View File

@ -31,6 +31,7 @@ local self = {
importing_any_dc = false, importing_any_dc = false,
wl_pref = nil, ---@type Checkbox wl_pref = nil, ---@type Checkbox
range = nil, ---@type NumberField
show_auth_key = nil, ---@type function show_auth_key = nil, ---@type function
show_key_btn = nil, ---@type PushButton show_key_btn = nil, ---@type PushButton
auth_key_textbox = nil, ---@type TextBox auth_key_textbox = nil, ---@type TextBox
@ -107,8 +108,6 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, ext, style)
else self.wl_pref.enable() end else self.wl_pref.enable() end
end end
dis_pref(ini_cfg.WirelessModem)
local function on_wired_change(_) tool_ctl.gen_modem_list() end local function on_wired_change(_) tool_ctl.gen_modem_list() end
local wireless = Checkbox{parent=net_c_1,x=1,y=3,label="Wireless/Ender Modem",default=ini_cfg.WirelessModem,box_fg_bg=cpair(colors.lightBlue,colors.black),callback=dis_pref} local wireless = Checkbox{parent=net_c_1,x=1,y=3,label="Wireless/Ender Modem",default=ini_cfg.WirelessModem,box_fg_bg=cpair(colors.lightBlue,colors.black),callback=dis_pref}
@ -120,9 +119,11 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, ext, style)
local modem_err = TextBox{parent=net_c_1,x=8,y=14,width=35,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} local modem_err = TextBox{parent=net_c_1,x=8,y=14,width=35,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
dis_pref(ini_cfg.WirelessModem)
local function submit_interfaces() local function submit_interfaces()
tmp_cfg.WirelessModem = wireless.get_value() tmp_cfg.WirelessModem = wireless.get_value()
tmp_cfg.PreferWireless = self.wl_pref.get_value() tmp_cfg.PreferWireless = tmp_cfg.WirelessModem and self.wl_pref.get_value()
if not wired.get_value() then if not wired.get_value() then
tmp_cfg.WiredModem = false tmp_cfg.WiredModem = false
@ -136,6 +137,13 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, ext, style)
modem_err.set_value("Please select a wired modem.") modem_err.set_value("Please select a wired modem.")
modem_err.show() modem_err.show()
else else
if tmp_cfg.WirelessModem then
self.range.enable()
else
self.range.set_value(0)
self.range.disable()
end
net_pane.set_value(2) net_pane.set_value(2)
modem_err.hide(true) modem_err.hide(true)
end end
@ -182,25 +190,33 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, ext, style)
TextBox{parent=net_c_3,x=1,y=3,height=4,text="You generally do not want or need to modify this. On slow servers, you can increase this to make the system wait longer before assuming a disconnection.",fg_bg=g_lg_fg_bg} TextBox{parent=net_c_3,x=1,y=3,height=4,text="You generally do not want or need to modify this. On slow servers, you can increase this to make the system wait longer before assuming a disconnection.",fg_bg=g_lg_fg_bg}
TextBox{parent=net_c_3,x=1,y=8,text="Trusted Range (Wireless Only)"} TextBox{parent=net_c_3,x=1,y=8,text="Trusted Range (Wireless Only)"}
local range = NumberField{parent=net_c_3,x=1,y=9,width=10,default=ini_cfg.TrustedRange,min=0,max_chars=20,allow_decimal=true,fg_bg=bw_fg_bg} self.range = NumberField{parent=net_c_3,x=1,y=9,width=10,default=ini_cfg.TrustedRange,min=0,max_chars=20,allow_decimal=true,fg_bg=bw_fg_bg,dis_fg_bg=cpair(colors.lightGray,colors.white)}
TextBox{parent=net_c_3,x=1,y=10,height=4,text="Setting this to a value larger than 0 prevents connections with devices that many meters (blocks) away in any direction.",fg_bg=g_lg_fg_bg} TextBox{parent=net_c_3,x=1,y=10,height=4,text="Setting this to a value larger than 0 prevents wireless connections with devices that many meters (blocks) away in any direction.",fg_bg=g_lg_fg_bg}
local p2_err = TextBox{parent=net_c_3,x=8,y=14,width=35,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true} local n3_err = TextBox{parent=net_c_3,x=8,y=14,width=35,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
local function submit_ct_tr() local function submit_ct_tr()
local timeout_val = tonumber(timeout.get_value()) local timeout_val = tonumber(timeout.get_value())
local range_val = tonumber(range.get_value()) local range_val = tonumber(self.range.get_value())
if timeout_val ~= nil and range_val ~= nil then
tmp_cfg.ConnTimeout = timeout_val if timeout_val == nil then
tmp_cfg.TrustedRange = range_val n3_err.set_value("Please set the connection timeout.")
net_pane.set_value(4) n3_err.show()
p2_err.hide(true) elseif tmp_cfg.WirelessModem and (range_val == nil) then
elseif timeout_val == nil then n3_err.set_value("Please set the trusted range.")
p2_err.set_value("Please set the connection timeout.") n3_err.show()
p2_err.show()
else else
p2_err.set_value("Please set the trusted range.") tmp_cfg.ConnTimeout = timeout_val
p2_err.show() tmp_cfg.TrustedRange = tri(tmp_cfg.WirelessModem, range_val, 0)
if tmp_cfg.WirelessModem then
net_pane.set_value(4)
else
main_pane.set_value(4)
tmp_cfg.AuthKey = ""
end
n3_err.hide(true)
end end
end end
@ -437,7 +453,7 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, ext, style)
try_set(svr_chan, ini_cfg.SVR_Channel) try_set(svr_chan, ini_cfg.SVR_Channel)
try_set(rtu_chan, ini_cfg.RTU_Channel) try_set(rtu_chan, ini_cfg.RTU_Channel)
try_set(timeout, ini_cfg.ConnTimeout) try_set(timeout, ini_cfg.ConnTimeout)
try_set(range, ini_cfg.TrustedRange) try_set(self.range, ini_cfg.TrustedRange)
try_set(key, ini_cfg.AuthKey) try_set(key, ini_cfg.AuthKey)
try_set(mode, ini_cfg.LogMode) try_set(mode, ini_cfg.LogMode)
try_set(path, ini_cfg.LogPath) try_set(path, ini_cfg.LogPath)

View File

@ -90,12 +90,12 @@ local tmp_cfg = {
SpeakerVolume = 1.0, SpeakerVolume = 1.0,
Peripherals = {}, ---@type rtu_peri_definition[] Peripherals = {}, ---@type rtu_peri_definition[]
Redstone = {}, ---@type rtu_rs_definition[] Redstone = {}, ---@type rtu_rs_definition[]
SVR_Channel = nil, ---@type integer
RTU_Channel = nil, ---@type integer
ConnTimeout = nil, ---@type number
WirelessModem = true, WirelessModem = true,
WiredModem = false, ---@type string|false WiredModem = false, ---@type string|false
PreferWireless = true, PreferWireless = true,
SVR_Channel = nil, ---@type integer
RTU_Channel = nil, ---@type integer
ConnTimeout = nil, ---@type number
TrustedRange = nil, ---@type number TrustedRange = nil, ---@type number
AuthKey = nil, ---@type string AuthKey = nil, ---@type string
LogMode = 0, ---@type LOG_MODE LogMode = 0, ---@type LOG_MODE
@ -112,12 +112,12 @@ local settings_cfg = {}
local fields = { local fields = {
{ "SpeakerVolume", "Speaker Volume", 1.0 }, { "SpeakerVolume", "Speaker Volume", 1.0 },
{ "SVR_Channel", "SVR Channel", 16240 },
{ "RTU_Channel", "RTU Channel", 16242 },
{ "ConnTimeout", "Connection Timeout", 5 },
{ "WirelessModem", "Wireless/Ender Comms Modem", true }, { "WirelessModem", "Wireless/Ender Comms Modem", true },
{ "WiredModem", "Wired Comms Modem", false }, { "WiredModem", "Wired Comms Modem", false },
{ "PreferWireless", "Prefer Wireless Modem", true }, { "PreferWireless", "Prefer Wireless Modem", true },
{ "SVR_Channel", "SVR Channel", 16240 },
{ "RTU_Channel", "RTU Channel", 16242 },
{ "ConnTimeout", "Connection Timeout", 5 },
{ "TrustedRange", "Trusted Range", 0 }, { "TrustedRange", "Trusted Range", 0 },
{ "AuthKey", "Facility Auth Key", "" }, { "AuthKey", "Facility Auth Key", "" },
{ "LogMode", "Log Mode", log.MODE.APPEND }, { "LogMode", "Log Mode", log.MODE.APPEND },

View File

@ -242,6 +242,8 @@ function system.create(tool_ctl, main_pane, cfg_sys, divs, fac_pane, style, exit
net_pane.set_value(5) net_pane.set_value(5)
ct_err.hide(true) ct_err.hide(true)
else else
tmp_cfg.TrustedRange = 0
tmp_cfg.AuthKey = ""
main_pane.set_value(4) main_pane.set_value(4)
end end
else ct_err.show() end else ct_err.show() end