mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
@ -7,7 +7,7 @@ local flasher = require("graphics.flasher")
|
|||||||
|
|
||||||
local core = {}
|
local core = {}
|
||||||
|
|
||||||
core.version = "2.0.0"
|
core.version = "2.0.2"
|
||||||
|
|
||||||
core.flasher = flasher
|
core.flasher = flasher
|
||||||
core.events = events
|
core.events = events
|
||||||
@ -115,7 +115,7 @@ end
|
|||||||
|
|
||||||
-- extract the custom element assert message, dropping the path to the element file
|
-- extract the custom element assert message, dropping the path to the element file
|
||||||
function core.extract_assert_msg(msg)
|
function core.extract_assert_msg(msg)
|
||||||
return string.sub(msg, (string.find(msg, "@") + 1) or 1)
|
return string.sub(msg, (string.find(msg, "@") or 0) + 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Interactive Field Manager
|
-- Interactive Field Manager
|
||||||
|
@ -217,10 +217,10 @@ function element.new(args, child_offset_x, child_offset_y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- check frame
|
-- check frame
|
||||||
element.assert(f.x >= 1, "frame x not >= 1", 2)
|
element.assert(f.x >= 1, "frame x not >= 1", 3)
|
||||||
element.assert(f.y >= 1, "frame y not >= 1", 2)
|
element.assert(f.y >= 1, "frame y not >= 1", 3)
|
||||||
element.assert(f.w >= 1, "frame width not >= 1", 2)
|
element.assert(f.w >= 1, "frame width not >= 1", 3)
|
||||||
element.assert(f.h >= 1, "frame height not >= 1", 2)
|
element.assert(f.h >= 1, "frame height not >= 1", 3)
|
||||||
|
|
||||||
-- create window
|
-- create window
|
||||||
protected.window = window.create(self.p_window, f.x, f.y, f.w, f.h, args.hidden ~= true)
|
protected.window = window.create(self.p_window, f.x, f.y, f.w, f.h, args.hidden ~= true)
|
||||||
|
@ -30,6 +30,11 @@ local LEFT = core.ALIGN.LEFT
|
|||||||
local CENTER = core.ALIGN.CENTER
|
local CENTER = core.ALIGN.CENTER
|
||||||
local RIGHT = core.ALIGN.RIGHT
|
local RIGHT = core.ALIGN.RIGHT
|
||||||
|
|
||||||
|
-- changes to the config data/format to let the user know
|
||||||
|
local changes = {
|
||||||
|
{"v1.6.2", { "AuthKey minimum length is now 8 (if set)" } }
|
||||||
|
}
|
||||||
|
|
||||||
---@class plc_configurator
|
---@class plc_configurator
|
||||||
local configurator = {}
|
local configurator = {}
|
||||||
|
|
||||||
@ -37,7 +42,6 @@ local style = {}
|
|||||||
|
|
||||||
style.root = cpair(colors.black, colors.lightGray)
|
style.root = cpair(colors.black, colors.lightGray)
|
||||||
style.header = cpair(colors.white, colors.gray)
|
style.header = cpair(colors.white, colors.gray)
|
||||||
style.label = cpair(colors.gray, colors.lightGray)
|
|
||||||
|
|
||||||
style.colors = {
|
style.colors = {
|
||||||
{ c = colors.red, hex = 0xdf4949 },
|
{ c = colors.red, hex = 0xdf4949 },
|
||||||
@ -55,6 +59,11 @@ style.colors = {
|
|||||||
{ c = colors.gray, hex = 0x575757 }
|
{ 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 tool_ctl = {
|
local tool_ctl = {
|
||||||
ask_config = false,
|
ask_config = false,
|
||||||
has_config = false,
|
has_config = false,
|
||||||
@ -173,8 +182,6 @@ end
|
|||||||
-- create the config view
|
-- create the config view
|
||||||
---@param display graphics_element
|
---@param display graphics_element
|
||||||
local function config_view(display)
|
local function config_view(display)
|
||||||
local nav_fg_bg = cpair(colors.black,colors.white)
|
|
||||||
local btn_act_fg_bg = cpair(colors.white,colors.gray)
|
|
||||||
|
|
||||||
---@diagnostic disable-next-line: undefined-field
|
---@diagnostic disable-next-line: undefined-field
|
||||||
local function exit() os.queueEvent("terminate") end
|
local function exit() os.queueEvent("terminate") end
|
||||||
@ -188,8 +195,9 @@ local function config_view(display)
|
|||||||
local net_cfg = 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 log_cfg = Div{parent=root_pane_div,x=1,y=1}
|
||||||
local summary = 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,plc_cfg,net_cfg,log_cfg,summary}}
|
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
|
||||||
|
|
||||||
@ -198,8 +206,8 @@ local function config_view(display)
|
|||||||
TextBox{parent=main_page,x=2,y=2,height=2,text_align=CENTER,text="Welcome to the Reactor PLC configurator! Please select one of the following options."}
|
TextBox{parent=main_page,x=2,y=2,height=2,text_align=CENTER,text="Welcome to the Reactor PLC configurator! Please select one of the following options."}
|
||||||
|
|
||||||
if tool_ctl.ask_config then
|
if tool_ctl.ask_config then
|
||||||
TextBox{parent=main_page,x=2,y=y_start,height=2,text_align=CENTER,text="Notice: This device has no valid config. The configurator has been automatically started.",fg_bg=cpair(colors.red,colors.lightGray)}
|
TextBox{parent=main_page,x=2,y=y_start,height=4,width=49,text_align=CENTER,text="Notice: This device has no valid config so the configurator has been automatically started. If you previously had a valid config, you may want to check the Change Log to see what changed.",fg_bg=cpair(colors.red,colors.lightGray)}
|
||||||
y_start = y_start + 3
|
y_start = y_start + 5
|
||||||
end
|
end
|
||||||
|
|
||||||
local function view_config()
|
local function view_config()
|
||||||
@ -220,6 +228,7 @@ local function config_view(display)
|
|||||||
if not tool_ctl.has_config then tool_ctl.view_cfg.disable() end
|
if not tool_ctl.has_config then tool_ctl.view_cfg.disable() end
|
||||||
|
|
||||||
PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg}
|
PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg}
|
||||||
|
PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(6)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||||
|
|
||||||
-- PLC CONFIG
|
-- PLC CONFIG
|
||||||
|
|
||||||
@ -233,7 +242,7 @@ local function config_view(display)
|
|||||||
TextBox{parent=plc_cfg,x=1,y=2,height=1,text_align=CENTER,text=" PLC Configuration",fg_bg=cpair(colors.black,colors.orange)}
|
TextBox{parent=plc_cfg,x=1,y=2,height=1,text_align=CENTER,text=" PLC Configuration",fg_bg=cpair(colors.black,colors.orange)}
|
||||||
|
|
||||||
TextBox{parent=plc_c_1,x=1,y=1,height=1,text_align=CENTER,text="Would you like to set this PLC as networked?"}
|
TextBox{parent=plc_c_1,x=1,y=1,height=1,text_align=CENTER,text="Would you like to set this PLC as networked?"}
|
||||||
TextBox{parent=plc_c_1,x=1,y=3,height=4,text_align=CENTER,text="If you have a supervisor, select the box. You will later be prompted to select the network configuration. If you instead want to use this as a standalone safety system, don't select the box.",fg_bg=cpair(colors.gray,colors.lightGray)}
|
TextBox{parent=plc_c_1,x=1,y=3,height=4,text_align=CENTER,text="If you have a supervisor, select the box. You will later be prompted to select the network configuration. If you instead want to use this as a standalone safety system, don't select the box.",fg_bg=g_lg_fg_bg}
|
||||||
|
|
||||||
local networked = CheckBox{parent=plc_c_1,x=1,y=8,label="Networked",default=ini_cfg.Networked,box_fg_bg=cpair(colors.orange,colors.black)}
|
local networked = CheckBox{parent=plc_c_1,x=1,y=8,label="Networked",default=ini_cfg.Networked,box_fg_bg=cpair(colors.orange,colors.black)}
|
||||||
|
|
||||||
@ -246,10 +255,10 @@ local function config_view(display)
|
|||||||
PushButton{parent=plc_c_1,x=44,y=14,min_width=6,text="Next \x1a",callback=submit_networked,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
PushButton{parent=plc_c_1,x=44,y=14,min_width=6,text="Next \x1a",callback=submit_networked,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||||
|
|
||||||
TextBox{parent=plc_c_2,x=1,y=1,height=1,text_align=CENTER,text="Please enter the reactor unit ID for this PLC."}
|
TextBox{parent=plc_c_2,x=1,y=1,height=1,text_align=CENTER,text="Please enter the reactor unit ID for this PLC."}
|
||||||
TextBox{parent=plc_c_2,x=1,y=3,height=3,text_align=CENTER,text="If this is a networked PLC, currently only IDs 1 through 4 are acceptable.",fg_bg=cpair(colors.gray,colors.lightGray)}
|
TextBox{parent=plc_c_2,x=1,y=3,height=3,text_align=CENTER,text="If this is a networked PLC, currently only IDs 1 through 4 are acceptable.",fg_bg=g_lg_fg_bg}
|
||||||
|
|
||||||
TextBox{parent=plc_c_2,x=1,y=6,height=1,text_align=CENTER,text="Unit #"}
|
TextBox{parent=plc_c_2,x=1,y=6,height=1,text_align=CENTER,text="Unit #"}
|
||||||
local u_id = NumberField{parent=plc_c_2,x=7,y=6,width=5,max_digits=3,default=ini_cfg.UnitID,min=1,fg_bg=cpair(colors.black,colors.white)}
|
local u_id = NumberField{parent=plc_c_2,x=7,y=6,width=5,max_digits=3,default=ini_cfg.UnitID,min=1,fg_bg=bw_fg_bg}
|
||||||
|
|
||||||
local u_id_err = TextBox{parent=plc_c_2,x=8,y=14,height=1,width=35,text_align=LEFT,text="Please set a unit ID.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
|
local u_id_err = TextBox{parent=plc_c_2,x=8,y=14,height=1,width=35,text_align=LEFT,text="Please set a unit ID.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
|
||||||
|
|
||||||
@ -266,7 +275,7 @@ local function config_view(display)
|
|||||||
PushButton{parent=plc_c_2,x=44,y=14,min_width=6,text="Next \x1a",callback=submit_id,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
PushButton{parent=plc_c_2,x=44,y=14,min_width=6,text="Next \x1a",callback=submit_id,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||||
|
|
||||||
TextBox{parent=plc_c_3,x=1,y=1,height=4,text_align=CENTER,text="When networked, the supervisor takes care of emergency coolant via RTUs. However, you can configure independent emergency coolant via the PLC. "}
|
TextBox{parent=plc_c_3,x=1,y=1,height=4,text_align=CENTER,text="When networked, the supervisor takes care of emergency coolant via RTUs. However, you can configure independent emergency coolant via the PLC. "}
|
||||||
TextBox{parent=plc_c_3,x=1,y=6,height=5,text_align=CENTER,text="This independent control can be used with or without a supervisor. To configure, you would next select the interface of the redstone output connected to one or more mekanism pipes.",fg_bg=cpair(colors.gray,colors.lightGray)}
|
TextBox{parent=plc_c_3,x=1,y=6,height=5,text_align=CENTER,text="This independent control can be used with or without a supervisor. To configure, you would next select the interface of the redstone output connected to one or more mekanism pipes.",fg_bg=g_lg_fg_bg}
|
||||||
|
|
||||||
local en_em_cool = CheckBox{parent=plc_c_3,x=1,y=11,label="Enable PLC Emergency Coolant Control",default=ini_cfg.EmerCoolEnable,box_fg_bg=cpair(colors.orange,colors.black)}
|
local en_em_cool = CheckBox{parent=plc_c_3,x=1,y=11,label="Enable PLC Emergency Coolant Control",default=ini_cfg.EmerCoolEnable,box_fg_bg=cpair(colors.orange,colors.black)}
|
||||||
|
|
||||||
@ -287,7 +296,7 @@ local function config_view(display)
|
|||||||
|
|
||||||
TextBox{parent=plc_c_4,x=1,y=5,height=1,text_align=CENTER,text="Bundled Redstone Configuration"}
|
TextBox{parent=plc_c_4,x=1,y=5,height=1,text_align=CENTER,text="Bundled Redstone Configuration"}
|
||||||
local bundled = CheckBox{parent=plc_c_4,x=1,y=6,label="Is Bundled?",default=ini_cfg.EmerCoolColor~=nil,box_fg_bg=cpair(colors.orange,colors.black),callback=function(v)tool_ctl.bundled_emcool(v)end}
|
local bundled = CheckBox{parent=plc_c_4,x=1,y=6,label="Is Bundled?",default=ini_cfg.EmerCoolColor~=nil,box_fg_bg=cpair(colors.orange,colors.black),callback=function(v)tool_ctl.bundled_emcool(v)end}
|
||||||
local color = Radio2D{parent=plc_c_4,x=1,y=8,rows=4,columns=4,default=color_to_idx(ini_cfg.EmerCoolColor),options=color_options,radio_colors=cpair(colors.lightGray,colors.black),color_map=color_options_map,disable_color=colors.gray,disable_fg_bg=cpair(colors.gray,colors.lightGray)}
|
local color = Radio2D{parent=plc_c_4,x=1,y=8,rows=4,columns=4,default=color_to_idx(ini_cfg.EmerCoolColor),options=color_options,radio_colors=cpair(colors.lightGray,colors.black),color_map=color_options_map,disable_color=colors.gray,disable_fg_bg=g_lg_fg_bg}
|
||||||
if ini_cfg.EmerCoolColor == nil then color.disable() end
|
if ini_cfg.EmerCoolColor == nil then color.disable() end
|
||||||
|
|
||||||
local function submit_emcool()
|
local function submit_emcool()
|
||||||
@ -310,14 +319,14 @@ local function config_view(display)
|
|||||||
TextBox{parent=net_cfg,x=1,y=2,height=1,text_align=CENTER,text=" Network Configuration",fg_bg=cpair(colors.black,colors.lightBlue)}
|
TextBox{parent=net_cfg,x=1,y=2,height=1,text_align=CENTER,text=" Network Configuration",fg_bg=cpair(colors.black,colors.lightBlue)}
|
||||||
|
|
||||||
TextBox{parent=net_c_1,x=1,y=1,height=1,text_align=CENTER,text="Please set the network channels below."}
|
TextBox{parent=net_c_1,x=1,y=1,height=1,text_align=CENTER,text="Please set the network channels below."}
|
||||||
TextBox{parent=net_c_1,x=1,y=3,height=4,text_align=CENTER,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=cpair(colors.gray,colors.lightGray)}
|
TextBox{parent=net_c_1,x=1,y=3,height=4,text_align=CENTER,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=1,y=8,height=1,text_align=CENTER,text="Supervisor Channel"}
|
TextBox{parent=net_c_1,x=1,y=8,height=1,text_align=CENTER,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=cpair(colors.black,colors.white)}
|
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_align=CENTER,text="[SVR_CHANNEL]",fg_bg=cpair(colors.gray,colors.lightGray)}
|
TextBox{parent=net_c_1,x=9,y=9,height=4,text_align=CENTER,text="[SVR_CHANNEL]",fg_bg=g_lg_fg_bg}
|
||||||
TextBox{parent=net_c_1,x=1,y=11,height=1,text_align=CENTER,text="PLC Channel"}
|
TextBox{parent=net_c_1,x=1,y=11,height=1,text_align=CENTER,text="PLC Channel"}
|
||||||
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=cpair(colors.black,colors.white)}
|
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}
|
||||||
TextBox{parent=net_c_1,x=9,y=12,height=4,text_align=CENTER,text="[PLC_CHANNEL]",fg_bg=cpair(colors.gray,colors.lightGray)}
|
TextBox{parent=net_c_1,x=9,y=12,height=4,text_align=CENTER,text="[PLC_CHANNEL]",fg_bg=g_lg_fg_bg}
|
||||||
|
|
||||||
local chan_err = TextBox{parent=net_c_1,x=8,y=14,height=1,width=35,text_align=LEFT,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
|
local chan_err = TextBox{parent=net_c_1,x=8,y=14,height=1,width=35,text_align=LEFT,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
|
||||||
|
|
||||||
@ -342,13 +351,13 @@ local function config_view(display)
|
|||||||
PushButton{parent=net_c_1,x=44,y=14,min_width=6,text="Next \x1a",callback=submit_channels,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
PushButton{parent=net_c_1,x=44,y=14,min_width=6,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_align=CENTER,text="Connection Timeout"}
|
TextBox{parent=net_c_2,x=1,y=1,height=1,text_align=CENTER,text="Connection Timeout"}
|
||||||
local timeout = NumberField{parent=net_c_2,x=1,y=2,width=7,default=ini_cfg.ConnTimeout,min=2,max=25,fg_bg=cpair(colors.black,colors.white)}
|
local timeout = NumberField{parent=net_c_2,x=1,y=2,width=7,default=ini_cfg.ConnTimeout,min=2,max=25,fg_bg=bw_fg_bg}
|
||||||
TextBox{parent=net_c_2,x=9,y=2,height=2,text_align=CENTER,text="seconds (default 5)",fg_bg=cpair(colors.gray,colors.lightGray)}
|
TextBox{parent=net_c_2,x=9,y=2,height=2,text_align=CENTER,text="seconds (default 5)",fg_bg=g_lg_fg_bg}
|
||||||
TextBox{parent=net_c_2,x=1,y=3,height=4,text_align=CENTER,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=cpair(colors.gray,colors.lightGray)}
|
TextBox{parent=net_c_2,x=1,y=3,height=4,text_align=CENTER,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,height=1,text_align=CENTER,text="Trusted Range"}
|
TextBox{parent=net_c_2,x=1,y=8,height=1,text_align=CENTER,text="Trusted Range"}
|
||||||
local range = NumberField{parent=net_c_2,x=1,y=9,width=10,default=ini_cfg.TrustedRange,min=0,max_digits=20,allow_decimal=true,fg_bg=cpair(colors.black,colors.white)}
|
local range = NumberField{parent=net_c_2,x=1,y=9,width=10,default=ini_cfg.TrustedRange,min=0,max_digits=20,allow_decimal=true,fg_bg=bw_fg_bg}
|
||||||
TextBox{parent=net_c_2,x=1,y=10,height=4,text_align=CENTER,text="Setting this to a value larger than 0 prevents connections with devices that many meters (blocks) away in any direction.",fg_bg=cpair(colors.gray,colors.lightGray)}
|
TextBox{parent=net_c_2,x=1,y=10,height=4,text_align=CENTER,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}
|
||||||
|
|
||||||
local p2_err = TextBox{parent=net_c_2,x=8,y=14,height=1,width=35,text_align=LEFT,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
|
local p2_err = TextBox{parent=net_c_2,x=8,y=14,height=1,width=35,text_align=LEFT,text="",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
|
||||||
|
|
||||||
@ -373,10 +382,10 @@ local function config_view(display)
|
|||||||
PushButton{parent=net_c_2,x=44,y=14,min_width=6,text="Next \x1a",callback=submit_ct_tr,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
PushButton{parent=net_c_2,x=44,y=14,min_width=6,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_align=CENTER,text="Optionally, set the facility authentication key below. Do NOT use one of your passwords."}
|
TextBox{parent=net_c_3,x=1,y=1,height=2,text_align=CENTER,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_align=CENTER,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 compution (can slow things down).",fg_bg=cpair(colors.gray,colors.lightGray)}
|
TextBox{parent=net_c_3,x=1,y=4,height=6,text_align=CENTER,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 compution (can slow things down).",fg_bg=g_lg_fg_bg}
|
||||||
|
|
||||||
TextBox{parent=net_c_3,x=1,y=11,height=1,text_align=CENTER,text="Facility Auth Key"}
|
TextBox{parent=net_c_3,x=1,y=11,height=1,text_align=CENTER,text="Facility Auth Key"}
|
||||||
local key, _, censor = TextField{parent=net_c_3,x=1,y=12,max_len=64,value=ini_cfg.AuthKey,width=32,height=1,fg_bg=cpair(colors.black,colors.white)}
|
local key, _, censor = 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 function censor_key(enable) censor(util.trinary(enable, "*", nil)) end
|
local function censor_key(enable) censor(util.trinary(enable, "*", nil)) end
|
||||||
|
|
||||||
@ -385,9 +394,15 @@ local function config_view(display)
|
|||||||
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,height=1,width=35,text_align=LEFT,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()
|
||||||
|
if string.len(v) == 0 or string.len(v) >= 8 then
|
||||||
tmp_cfg.AuthKey = key.get_value()
|
tmp_cfg.AuthKey = key.get_value()
|
||||||
main_pane.set_value(4)
|
main_pane.set_value(4)
|
||||||
|
key_err.hide(true)
|
||||||
|
else key_err.show() end
|
||||||
end
|
end
|
||||||
|
|
||||||
PushButton{parent=net_c_3,x=1,y=14,min_width=6,text="\x1b Back",callback=function()net_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
PushButton{parent=net_c_3,x=1,y=14,min_width=6,text="\x1b Back",callback=function()net_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||||
@ -405,10 +420,10 @@ local function config_view(display)
|
|||||||
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}
|
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_align=CENTER,text="Log File Path"}
|
TextBox{parent=log_c_1,x=1,y=7,height=1,text_align=CENTER,text="Log File Path"}
|
||||||
local path = TextField{parent=log_c_1,x=1,y=8,width=49,height=1,value=ini_cfg.LogPath,max_len=128,fg_bg=cpair(colors.black,colors.white)}
|
local path = TextField{parent=log_c_1,x=1,y=8,width=49,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 Logging Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)}
|
local en_dbg = CheckBox{parent=log_c_1,x=1,y=10,default=ini_cfg.LogDebug,label="Enable Logging Debug Messages",box_fg_bg=cpair(colors.pink,colors.black)}
|
||||||
TextBox{parent=log_c_1,x=3,y=11,height=2,text_align=CENTER,text="This results in much larger log files. It is best to only use this when there is a problem.",fg_bg=cpair(colors.gray,colors.lightGray)}
|
TextBox{parent=log_c_1,x=3,y=11,height=2,text_align=CENTER,text="This results in much larger log files. It is best to only use this when there is a problem.",fg_bg=g_lg_fg_bg}
|
||||||
|
|
||||||
local path_err = TextBox{parent=log_c_1,x=8,y=14,height=1,width=35,text_align=LEFT,text="Please provide a log file path.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
|
local path_err = TextBox{parent=log_c_1,x=8,y=14,height=1,width=35,text_align=LEFT,text="Please provide a log file path.",fg_bg=cpair(colors.red,colors.lightGray),hidden=true}
|
||||||
|
|
||||||
@ -444,7 +459,7 @@ local function config_view(display)
|
|||||||
|
|
||||||
TextBox{parent=summary,x=1,y=2,height=1,text_align=CENTER,text=" Summary",fg_bg=cpair(colors.black,colors.green)}
|
TextBox{parent=summary,x=1,y=2,height=1,text_align=CENTER,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=cpair(colors.black,colors.white),nav_fg_bg=cpair(colors.gray,colors.lightGray),nav_active=cpair(colors.black,colors.gray)}
|
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 function back_from_settings()
|
local function back_from_settings()
|
||||||
if tool_ctl.viewing_config or tool_ctl.importing_legacy then
|
if tool_ctl.viewing_config or tool_ctl.importing_legacy then
|
||||||
@ -526,6 +541,25 @@ local function config_view(display)
|
|||||||
PushButton{parent=sum_c_4,x=1,y=14,min_width=6,text="Home",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
PushButton{parent=sum_c_4,x=1,y=14,min_width=6,text="Home",callback=go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||||
PushButton{parent=sum_c_4,x=44,y=14,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)}
|
PushButton{parent=sum_c_4,x=44,y=14,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)}
|
||||||
|
|
||||||
|
-- CONFIG CHANGE LOG
|
||||||
|
|
||||||
|
local cl = Div{parent=changelog,x=2,y=4,width=49}
|
||||||
|
|
||||||
|
TextBox{parent=changelog,x=1,y=2,height=1,text_align=CENTER,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)}
|
||||||
|
|
||||||
|
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,46)}
|
||||||
|
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=14,min_width=6,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
|
-- set tool functions now that we have the elements
|
||||||
|
|
||||||
function tool_ctl.set_networked(enable)
|
function tool_ctl.set_networked(enable)
|
||||||
@ -596,7 +630,7 @@ local function config_view(display)
|
|||||||
if f[1] == "EmerCoolColor" and raw ~= nil then val = color_name_map[raw] end
|
if f[1] == "EmerCoolColor" and raw ~= nil then val = color_name_map[raw] end
|
||||||
if val == "nil" then val = "n/a" end
|
if val == "nil" then val = "n/a" end
|
||||||
|
|
||||||
local c = util.trinary(alternate, cpair(colors.gray,colors.lightGray), cpair(colors.gray,colors.white))
|
local c = util.trinary(alternate, g_lg_fg_bg, cpair(colors.gray,colors.white))
|
||||||
alternate = not alternate
|
alternate = not alternate
|
||||||
|
|
||||||
if string.len(val) > val_max_w then
|
if string.len(val) > val_max_w then
|
||||||
|
@ -54,6 +54,8 @@ function plc.load_config()
|
|||||||
cfv.assert_type_bool(config.Networked)
|
cfv.assert_type_bool(config.Networked)
|
||||||
cfv.assert_type_int(config.UnitID)
|
cfv.assert_type_int(config.UnitID)
|
||||||
cfv.assert_type_bool(config.EmerCoolEnable)
|
cfv.assert_type_bool(config.EmerCoolEnable)
|
||||||
|
|
||||||
|
if config.Networked == true then
|
||||||
cfv.assert_channel(config.SVR_Channel)
|
cfv.assert_channel(config.SVR_Channel)
|
||||||
cfv.assert_channel(config.PLC_Channel)
|
cfv.assert_channel(config.PLC_Channel)
|
||||||
cfv.assert_type_int(config.ConnTimeout)
|
cfv.assert_type_int(config.ConnTimeout)
|
||||||
@ -61,6 +63,13 @@ function plc.load_config()
|
|||||||
cfv.assert_type_num(config.TrustedRange)
|
cfv.assert_type_num(config.TrustedRange)
|
||||||
cfv.assert_min(config.TrustedRange, 0)
|
cfv.assert_min(config.TrustedRange, 0)
|
||||||
cfv.assert_type_str(config.AuthKey)
|
cfv.assert_type_str(config.AuthKey)
|
||||||
|
|
||||||
|
if type(config.AuthKey) == "string" then
|
||||||
|
local len = string.len(config.AuthKey)
|
||||||
|
cfv.assert_eq(len == 0 or len >= 8, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
cfv.assert_type_int(config.LogMode)
|
cfv.assert_type_int(config.LogMode)
|
||||||
cfv.assert_type_str(config.LogPath)
|
cfv.assert_type_str(config.LogPath)
|
||||||
cfv.assert_type_bool(config.LogDebug)
|
cfv.assert_type_bool(config.LogDebug)
|
||||||
|
@ -18,7 +18,7 @@ local plc = require("reactor-plc.plc")
|
|||||||
local renderer = require("reactor-plc.renderer")
|
local renderer = require("reactor-plc.renderer")
|
||||||
local threads = require("reactor-plc.threads")
|
local threads = require("reactor-plc.threads")
|
||||||
|
|
||||||
local R_PLC_VERSION = "v1.6.0"
|
local R_PLC_VERSION = "v1.6.2"
|
||||||
|
|
||||||
local println = util.println
|
local println = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
@ -50,7 +50,7 @@ log.info("BOOTING reactor-plc.startup " .. R_PLC_VERSION)
|
|||||||
log.info("========================================")
|
log.info("========================================")
|
||||||
println(">> Reactor PLC " .. R_PLC_VERSION .. " <<")
|
println(">> Reactor PLC " .. R_PLC_VERSION .. " <<")
|
||||||
|
|
||||||
crash.set_env("plc", R_PLC_VERSION)
|
crash.set_env("reactor-plc", R_PLC_VERSION)
|
||||||
|
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
-- main application
|
-- main application
|
||||||
@ -69,7 +69,7 @@ local function main()
|
|||||||
ppm.mount_all()
|
ppm.mount_all()
|
||||||
|
|
||||||
-- message authentication init
|
-- message authentication init
|
||||||
if string.len(config.AuthKey) > 0 then
|
if type(config.AuthKey) == "string" and string.len(config.AuthKey) > 0 then
|
||||||
network.init_mac(config.AuthKey)
|
network.init_mac(config.AuthKey)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ function comms.authd_packet()
|
|||||||
self.valid = false
|
self.valid = false
|
||||||
self.raw = self.modem_msg_in.msg
|
self.raw = self.modem_msg_in.msg
|
||||||
|
|
||||||
if (type(max_distance) == "number") and (type(distance) == "number") and (distance > max_distance) then
|
if (type(max_distance) == "number") and ((type(distance) ~= "number") or (distance > max_distance)) then
|
||||||
-- outside of maximum allowable transmission distance
|
-- outside of maximum allowable transmission distance
|
||||||
-- log.debug("comms.authd_packet.receive(): discarding packet with distance " .. distance .. " (outside trusted range)")
|
-- log.debug("comms.authd_packet.receive(): discarding packet with distance " .. distance .. " (outside trusted range)")
|
||||||
else
|
else
|
||||||
|
@ -4,19 +4,26 @@
|
|||||||
|
|
||||||
local cc_strings = require("cc.strings")
|
local cc_strings = require("cc.strings")
|
||||||
|
|
||||||
|
local math = math
|
||||||
|
local string = string
|
||||||
|
local table = table
|
||||||
|
local os = os
|
||||||
|
|
||||||
|
local getmetatable = getmetatable
|
||||||
|
local print = print
|
||||||
|
local tostring = tostring
|
||||||
|
local type = type
|
||||||
|
|
||||||
---@class util
|
---@class util
|
||||||
local util = {}
|
local util = {}
|
||||||
|
|
||||||
-- scada-common version
|
-- scada-common version
|
||||||
util.version = "1.1.3"
|
util.version = "1.1.5"
|
||||||
|
|
||||||
-- ENVIRONMENT CONSTANTS --
|
|
||||||
|
|
||||||
util.TICK_TIME_S = 0.05
|
util.TICK_TIME_S = 0.05
|
||||||
util.TICK_TIME_MS = 50
|
util.TICK_TIME_MS = 50
|
||||||
|
|
||||||
-- OPERATORS --
|
--#region OPERATORS
|
||||||
--#region
|
|
||||||
|
|
||||||
-- trinary operator
|
-- trinary operator
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
@ -30,37 +37,29 @@ end
|
|||||||
|
|
||||||
--#endregion
|
--#endregion
|
||||||
|
|
||||||
-- PRINT --
|
--#region PRINT
|
||||||
--#region
|
|
||||||
|
local p_time = "[%H:%M:%S] "
|
||||||
|
|
||||||
-- print
|
-- print
|
||||||
---@param message any
|
---@param message any
|
||||||
function util.print(message)
|
function util.print(message) term.write(tostring(message)) end
|
||||||
term.write(tostring(message))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- print line
|
-- print line
|
||||||
---@param message any
|
---@param message any
|
||||||
function util.println(message)
|
function util.println(message) print(tostring(message)) end
|
||||||
print(tostring(message))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- timestamped print
|
-- timestamped print
|
||||||
---@param message any
|
---@param message any
|
||||||
function util.print_ts(message)
|
function util.print_ts(message) term.write(os.date(p_time) .. tostring(message)) end
|
||||||
term.write(os.date("[%H:%M:%S] ") .. tostring(message))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- timestamped print line
|
-- timestamped print line
|
||||||
---@param message any
|
---@param message any
|
||||||
function util.println_ts(message)
|
function util.println_ts(message) print(os.date(p_time) .. tostring(message)) end
|
||||||
print(os.date("[%H:%M:%S] ") .. tostring(message))
|
|
||||||
end
|
|
||||||
|
|
||||||
--#endregion
|
--#endregion
|
||||||
|
|
||||||
-- STRING TOOLS --
|
--#region STRING TOOLS
|
||||||
--#region
|
|
||||||
|
|
||||||
-- get a value as a string
|
-- get a value as a string
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
@ -68,21 +67,18 @@ end
|
|||||||
---@return string
|
---@return string
|
||||||
function util.strval(val)
|
function util.strval(val)
|
||||||
local t = type(val)
|
local t = type(val)
|
||||||
|
if t == "string" then return val end
|
||||||
-- this depends on Lua short-circuiting the or check for metatables (note: metatables won't have metatables)
|
-- this depends on Lua short-circuiting the or check for metatables (note: metatables won't have metatables)
|
||||||
if (t == "table" and (getmetatable(val) == nil or getmetatable(val).__tostring == nil)) or t == "function" then
|
if (t == "table" and (getmetatable(val) == nil or getmetatable(val).__tostring == nil)) or t == "function" then
|
||||||
return "[" .. tostring(val) .. "]"
|
return table.concat{"[", tostring(val), "]"}
|
||||||
else
|
else return tostring(val) end
|
||||||
return tostring(val)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- repeat a space n times
|
-- repeat a space n times
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param n integer
|
---@param n integer
|
||||||
---@return string
|
---@return string
|
||||||
function util.spaces(n)
|
function util.spaces(n) return string.rep(" ", n) end
|
||||||
return string.rep(" ", n)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- pad text to a minimum width
|
-- pad text to a minimum width
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
@ -94,7 +90,7 @@ function util.pad(str, n)
|
|||||||
local lpad = math.floor((n - len) / 2)
|
local lpad = math.floor((n - len) / 2)
|
||||||
local rpad = (n - len) - lpad
|
local rpad = (n - len) - lpad
|
||||||
|
|
||||||
return util.spaces(lpad) .. str .. util.spaces(rpad)
|
return table.concat{util.spaces(lpad), str, util.spaces(rpad)}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- wrap a string into a table of lines
|
-- wrap a string into a table of lines
|
||||||
@ -112,11 +108,9 @@ function util.strwrap(str, limit) return cc_strings.wrap(str, limit) end
|
|||||||
---@return string
|
---@return string
|
||||||
---@diagnostic disable-next-line: unused-vararg
|
---@diagnostic disable-next-line: unused-vararg
|
||||||
function util.concat(...)
|
function util.concat(...)
|
||||||
local str = ""
|
local strings = {}
|
||||||
|
for i = 1, #arg do strings[i] = util.strval(arg[i]) end
|
||||||
for _, v in ipairs(arg) do str = str .. util.strval(v) end
|
return table.concat(strings)
|
||||||
|
|
||||||
return str
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- alias
|
-- alias
|
||||||
@ -127,9 +121,7 @@ util.c = util.concat
|
|||||||
---@param format string
|
---@param format string
|
||||||
---@vararg any
|
---@vararg any
|
||||||
---@diagnostic disable-next-line: unused-vararg
|
---@diagnostic disable-next-line: unused-vararg
|
||||||
function util.sprintf(format, ...)
|
function util.sprintf(format, ...) return string.format(format, table.unpack(arg)) end
|
||||||
return string.format(format, table.unpack(arg))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- luacheck: unused args
|
-- luacheck: unused args
|
||||||
|
|
||||||
@ -144,7 +136,7 @@ function util.comma_format(num)
|
|||||||
local i = 1
|
local i = 1
|
||||||
|
|
||||||
while i > 0 do
|
while i > 0 do
|
||||||
formatted, i = formatted:gsub("^(%s-%d+)(%d%d%d)", '%1,%2')
|
formatted, i = formatted:gsub("^(%s-%d+)(%d%d%d)", "%1,%2")
|
||||||
if i > 0 then commas = commas + 1 end
|
if i > 0 then commas = commas + 1 end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -158,31 +150,24 @@ end
|
|||||||
|
|
||||||
--#endregion
|
--#endregion
|
||||||
|
|
||||||
-- MATH --
|
--#region MATH
|
||||||
--#region
|
|
||||||
|
|
||||||
-- is a value an integer
|
-- is a value an integer
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param x any value
|
---@param x any value
|
||||||
---@return boolean is_integer if the number is an integer
|
---@return boolean is_integer
|
||||||
function util.is_int(x)
|
function util.is_int(x) return type(x) == "number" and x == math.floor(x) end
|
||||||
return type(x) == "number" and x == math.floor(x)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- get the sign of a number
|
-- get the sign of a number
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param x number value
|
---@param x number value
|
||||||
---@return integer sign (-1 for < 0, 1 otherwise)
|
---@return integer sign (-1 for < 0, 1 otherwise)
|
||||||
function util.sign(x)
|
function util.sign(x) return util.trinary(x < 0, -1, 1) end
|
||||||
return util.trinary(x < 0, -1, 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- round a number to an integer
|
-- round a number to an integer
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@return integer rounded
|
---@return integer rounded
|
||||||
function util.round(x)
|
function util.round(x) return math.floor(x + 0.5) end
|
||||||
return math.floor(x + 0.5)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- get a new moving average object
|
-- get a new moving average object
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
@ -207,9 +192,7 @@ function util.mov_avg(length, default)
|
|||||||
---@param x number new value
|
---@param x number new value
|
||||||
---@param t number? optional last update time to prevent duplicated entries
|
---@param t number? optional last update time to prevent duplicated entries
|
||||||
function public.record(x, t)
|
function public.record(x, t)
|
||||||
if type(t) == "number" and last_t == t then
|
if type(t) == "number" and last_t == t then return end
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
data[index] = x
|
data[index] = x
|
||||||
last_t = t
|
last_t = t
|
||||||
@ -232,23 +215,21 @@ function util.mov_avg(length, default)
|
|||||||
return public
|
return public
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TIME --
|
--#endregion
|
||||||
|
|
||||||
|
--#region TIME
|
||||||
|
|
||||||
-- current time
|
-- current time
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@return integer milliseconds
|
---@return integer milliseconds
|
||||||
function util.time_ms()
|
|
||||||
---@diagnostic disable-next-line: undefined-field
|
---@diagnostic disable-next-line: undefined-field
|
||||||
return os.epoch('local')
|
function util.time_ms() return os.epoch("local") end
|
||||||
end
|
|
||||||
|
|
||||||
-- current time
|
-- current time
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@return number seconds
|
---@return number seconds
|
||||||
function util.time_s()
|
|
||||||
---@diagnostic disable-next-line: undefined-field
|
---@diagnostic disable-next-line: undefined-field
|
||||||
return os.epoch('local') / 1000.0
|
function util.time_s() return os.epoch("local") / 1000.0 end
|
||||||
end
|
|
||||||
|
|
||||||
-- current time
|
-- current time
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
@ -257,17 +238,14 @@ function util.time() return util.time_ms() end
|
|||||||
|
|
||||||
--#endregion
|
--#endregion
|
||||||
|
|
||||||
-- OS --
|
--#region OS
|
||||||
--#region
|
|
||||||
|
|
||||||
-- OS pull event raw wrapper with types
|
-- OS pull event raw wrapper with types
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param target_event? string event to wait for
|
---@param target_event? string event to wait for
|
||||||
---@return os_event event, any param1, any param2, any param3, any param4, any param5
|
---@return os_event event, any param1, any param2, any param3, any param4, any param5
|
||||||
function util.pull_event(target_event)
|
|
||||||
---@diagnostic disable-next-line: undefined-field
|
---@diagnostic disable-next-line: undefined-field
|
||||||
return os.pullEventRaw(target_event)
|
function util.pull_event(target_event) return os.pullEventRaw(target_event) end
|
||||||
end
|
|
||||||
|
|
||||||
-- OS queue event raw wrapper with types
|
-- OS queue event raw wrapper with types
|
||||||
---@param event os_event
|
---@param event os_event
|
||||||
@ -285,30 +263,23 @@ end
|
|||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param t number timer duration in seconds
|
---@param t number timer duration in seconds
|
||||||
---@return integer timer ID
|
---@return integer timer ID
|
||||||
function util.start_timer(t)
|
|
||||||
---@diagnostic disable-next-line: undefined-field
|
---@diagnostic disable-next-line: undefined-field
|
||||||
return os.startTimer(t)
|
function util.start_timer(t) return os.startTimer(t) end
|
||||||
end
|
|
||||||
|
|
||||||
-- cancel an OS timer
|
-- cancel an OS timer
|
||||||
---@param timer integer timer ID
|
---@param timer integer timer ID
|
||||||
function util.cancel_timer(timer)
|
|
||||||
---@diagnostic disable-next-line: undefined-field
|
---@diagnostic disable-next-line: undefined-field
|
||||||
os.cancelTimer(timer)
|
function util.cancel_timer(timer) os.cancelTimer(timer) end
|
||||||
end
|
|
||||||
|
|
||||||
--#endregion
|
--#endregion
|
||||||
|
|
||||||
-- PARALLELIZATION --
|
--#region PARALLELIZATION
|
||||||
--#region
|
|
||||||
|
|
||||||
-- protected sleep call so we still are in charge of catching termination
|
-- protected sleep call so we still are in charge of catching termination
|
||||||
---@param t integer seconds
|
---@param t integer seconds
|
||||||
--- EVENT_CONSUMER: this function consumes events
|
--- EVENT_CONSUMER: this function consumes events
|
||||||
function util.psleep(t)
|
|
||||||
---@diagnostic disable-next-line: undefined-field
|
---@diagnostic disable-next-line: undefined-field
|
||||||
pcall(os.sleep, t)
|
function util.psleep(t) pcall(os.sleep, t) end
|
||||||
end
|
|
||||||
|
|
||||||
-- no-op to provide a brief pause (1 tick) to yield<br>
|
-- no-op to provide a brief pause (1 tick) to yield<br>
|
||||||
--- EVENT_CONSUMER: this function consumes events
|
--- EVENT_CONSUMER: this function consumes events
|
||||||
@ -330,8 +301,7 @@ end
|
|||||||
|
|
||||||
--#endregion
|
--#endregion
|
||||||
|
|
||||||
-- TABLE UTILITIES --
|
--#region TABLE UTILITIES
|
||||||
--#region
|
|
||||||
|
|
||||||
-- delete elements from a table if the passed function returns false when passed a table element<br>
|
-- delete elements from a table if the passed function returns false when passed a table element<br>
|
||||||
-- put briefly: deletes elements that return false, keeps elements that return true
|
-- put briefly: deletes elements that return false, keeps elements that return true
|
||||||
@ -371,8 +341,7 @@ end
|
|||||||
|
|
||||||
--#endregion
|
--#endregion
|
||||||
|
|
||||||
-- MEKANISM POWER --
|
--#region MEKANISM POWER
|
||||||
--#region
|
|
||||||
|
|
||||||
-- convert Joules to FE
|
-- convert Joules to FE
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
@ -401,8 +370,7 @@ local function ZFE(fe) return fe / 1000000000000000000000.0 end -- how & why did
|
|||||||
---@param format? string format override
|
---@param format? string format override
|
||||||
---@return string str, string? unit
|
---@return string str, string? unit
|
||||||
function util.power_format(fe, combine_label, format)
|
function util.power_format(fe, combine_label, format)
|
||||||
local unit
|
local unit, value
|
||||||
local value
|
|
||||||
|
|
||||||
if type(format) ~= "string" then format = "%.2f" end
|
if type(format) ~= "string" then format = "%.2f" end
|
||||||
|
|
||||||
@ -441,8 +409,7 @@ end
|
|||||||
|
|
||||||
--#endregion
|
--#endregion
|
||||||
|
|
||||||
-- UTILITY CLASSES --
|
--#region UTILITY CLASSES
|
||||||
--#region
|
|
||||||
|
|
||||||
-- WATCHDOG --
|
-- WATCHDOG --
|
||||||
|
|
||||||
@ -451,32 +418,25 @@ end
|
|||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param timeout number timeout duration
|
---@param timeout number timeout duration
|
||||||
function util.new_watchdog(timeout)
|
function util.new_watchdog(timeout)
|
||||||
local self = {
|
local self = { timeout = timeout, wd_timer = util.start_timer(timeout) }
|
||||||
timeout = timeout,
|
|
||||||
wd_timer = util.start_timer(timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
---@class watchdog
|
---@class watchdog
|
||||||
local public = {}
|
local public = {}
|
||||||
|
|
||||||
-- check if a timer is this watchdog
|
-- check if a timer is this watchdog
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param timer number timer event timer ID
|
---@param timer number event timer ID
|
||||||
function public.is_timer(timer) return self.wd_timer == timer end
|
function public.is_timer(timer) return self.wd_timer == timer end
|
||||||
|
|
||||||
-- satiate the beast
|
-- satiate the beast
|
||||||
function public.feed()
|
function public.feed()
|
||||||
if self.wd_timer ~= nil then
|
public.cancel()
|
||||||
util.cancel_timer(self.wd_timer)
|
|
||||||
end
|
|
||||||
self.wd_timer = util.start_timer(self.timeout)
|
self.wd_timer = util.start_timer(self.timeout)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- cancel the watchdog
|
-- cancel the watchdog
|
||||||
function public.cancel()
|
function public.cancel()
|
||||||
if self.wd_timer ~= nil then
|
if self.wd_timer ~= nil then util.cancel_timer(self.wd_timer) end
|
||||||
util.cancel_timer(self.wd_timer)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return public
|
return public
|
||||||
@ -489,10 +449,7 @@ end
|
|||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param period number clock period
|
---@param period number clock period
|
||||||
function util.new_clock(period)
|
function util.new_clock(period)
|
||||||
local self = {
|
local self = { period = period, timer = nil }
|
||||||
period = period,
|
|
||||||
timer = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
---@class clock
|
---@class clock
|
||||||
local public = {}
|
local public = {}
|
||||||
@ -533,7 +490,7 @@ function util.new_validator()
|
|||||||
function public.assert_range(check, min, max) valid = valid and check >= min and check <= max end
|
function public.assert_range(check, min, max) valid = valid and check >= min and check <= max end
|
||||||
function public.assert_range_ex(check, min, max) valid = valid and check > min and check < max end
|
function public.assert_range_ex(check, min, max) valid = valid and check > min and check < max end
|
||||||
|
|
||||||
function public.assert_channel(channel) valid = valid and type(channel) == "number" and channel >= 0 and channel <= 65535 end
|
function public.assert_channel(channel) valid = valid and util.is_int(channel) and channel >= 0 and channel <= 65535 end
|
||||||
|
|
||||||
-- check if all assertions passed successfully
|
-- check if all assertions passed successfully
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
|
@ -590,6 +590,9 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- check if the manual lockout for automatic control is active
|
||||||
|
function public.is_auto_locked() return self.auto_lock end
|
||||||
|
|
||||||
-- set the burn rate on behalf of automatic control
|
-- set the burn rate on behalf of automatic control
|
||||||
---@param rate number burn rate
|
---@param rate number burn rate
|
||||||
---@param ramp boolean true to ramp, false to not
|
---@param ramp boolean true to ramp, false to not
|
||||||
|
@ -21,7 +21,7 @@ local supervisor = require("supervisor.supervisor")
|
|||||||
|
|
||||||
local svsessions = require("supervisor.session.svsessions")
|
local svsessions = require("supervisor.session.svsessions")
|
||||||
|
|
||||||
local SUPERVISOR_VERSION = "v1.0.8"
|
local SUPERVISOR_VERSION = "v1.0.9"
|
||||||
|
|
||||||
local println = util.println
|
local println = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
|
@ -498,7 +498,6 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
|||||||
self.plc_s = nil
|
self.plc_s = nil
|
||||||
self.plc_i = nil
|
self.plc_i = nil
|
||||||
self.db.control.br100 = 0
|
self.db.control.br100 = 0
|
||||||
self.db.control.lim_br100 = 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- unlink RTU unit sessions if they are closed
|
-- unlink RTU unit sessions if they are closed
|
||||||
@ -525,12 +524,14 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check plc formed/faulted
|
-- plc instance checks
|
||||||
if self.plc_i ~= nil then
|
if self.plc_i ~= nil then
|
||||||
|
-- check if degraded
|
||||||
local rps = self.plc_i.get_rps()
|
local rps = self.plc_i.get_rps()
|
||||||
if rps.fault or rps.sys_fail then
|
if rps.fault or rps.sys_fail then self.db.control.degraded = true end
|
||||||
self.db.control.degraded = true
|
|
||||||
end
|
-- re-engage auto lock if it reconnected without it
|
||||||
|
if self.auto_engaged and not self.plc_i.is_auto_locked() then self.plc_i.auto_lock(true) end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- update deltas
|
-- update deltas
|
||||||
|
@ -75,7 +75,7 @@ function logic.update_annunciator(self)
|
|||||||
(next(self.plc_i.get_status()) ~= nil) and (next(self.plc_i.get_struct()) ~= nil)
|
(next(self.plc_i.get_status()) ~= nil) and (next(self.plc_i.get_struct()) ~= nil)
|
||||||
|
|
||||||
-- update auto control limit
|
-- update auto control limit
|
||||||
if (self.db.control.lim_br100 == 0) or ((self.db.control.lim_br100 / 100) > plc_db.mek_struct.max_burn) then
|
if (plc_db.mek_struct.max_burn > 0) and ((self.db.control.lim_br100 / 100) > plc_db.mek_struct.max_burn) then
|
||||||
self.db.control.lim_br100 = math.floor(plc_db.mek_struct.max_burn * 100)
|
self.db.control.lim_br100 = math.floor(plc_db.mek_struct.max_burn * 100)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user