From e03eaf298250814ba6e5af13ab85cba5eceafb4e Mon Sep 17 00:00:00 2001 From: Mikayla Date: Sat, 7 Oct 2023 20:57:24 +0000 Subject: [PATCH 01/11] #354 type check functions --- scada-common/util.lua | 129 +++++++++++++++++++++--------------------- 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/scada-common/util.lua b/scada-common/util.lua index 637d92a..b311511 100644 --- a/scada-common/util.lua +++ b/scada-common/util.lua @@ -10,13 +10,10 @@ local util = {} -- scada-common version util.version = "1.1.3" --- ENVIRONMENT CONSTANTS -- - util.TICK_TIME_S = 0.05 util.TICK_TIME_MS = 50 --- OPERATORS -- ---#region +--#region OPERATORS -- trinary operator ---@nodiscard @@ -30,37 +27,27 @@ end --#endregion --- PRINT -- ---#region +--#region PRINT -- print ---@param message any -function util.print(message) - term.write(tostring(message)) -end +function util.print(message) term.write(tostring(message)) end -- print line ---@param message any -function util.println(message) - print(tostring(message)) -end +function util.println(message) print(tostring(message)) end -- timestamped print ---@param message any -function util.print_ts(message) - term.write(os.date("[%H:%M:%S] ") .. tostring(message)) -end +function util.print_ts(message) term.write(os.date("[%H:%M:%S] ") .. tostring(message)) end -- timestamped print line ---@param message any -function util.println_ts(message) - print(os.date("[%H:%M:%S] ") .. tostring(message)) -end +function util.println_ts(message) print(os.date("[%H:%M:%S] ") .. tostring(message)) end --#endregion --- STRING TOOLS -- ---#region +--#region STRING TOOLS -- get a value as a string ---@nodiscard @@ -71,18 +58,14 @@ function util.strval(val) -- 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 return "[" .. tostring(val) .. "]" - else - return tostring(val) - end + else return tostring(val) end end -- repeat a space n times ---@nodiscard ---@param n integer ---@return string -function util.spaces(n) - return string.rep(" ", n) -end +function util.spaces(n) return string.rep(" ", n) end -- pad text to a minimum width ---@nodiscard @@ -113,9 +96,7 @@ function util.strwrap(str, limit) return cc_strings.wrap(str, limit) end ---@diagnostic disable-next-line: unused-vararg function util.concat(...) local str = "" - for _, v in ipairs(arg) do str = str .. util.strval(v) end - return str end @@ -127,9 +108,7 @@ util.c = util.concat ---@param format string ---@vararg any ---@diagnostic disable-next-line: unused-vararg -function util.sprintf(format, ...) - return string.format(format, table.unpack(arg)) -end +function util.sprintf(format, ...) return string.format(format, table.unpack(arg)) end -- luacheck: unused args @@ -158,31 +137,18 @@ end --#endregion --- MATH -- ---#region - --- is a value an integer ----@nodiscard ----@param x any value ----@return boolean is_integer if the number is an integer -function util.is_int(x) - return type(x) == "number" and x == math.floor(x) -end +--#region MATH -- get the sign of a number ---@nodiscard ---@param x number value ---@return integer sign (-1 for < 0, 1 otherwise) -function util.sign(x) - return util.trinary(x < 0, -1, 1) -end +function util.sign(x) return util.trinary(x < 0, -1, 1) end -- round a number to an integer ---@nodiscard ---@return integer rounded -function util.round(x) - return math.floor(x + 0.5) -end +function util.round(x) return math.floor(x + 0.5) end -- get a new moving average object ---@nodiscard @@ -232,7 +198,49 @@ function util.mov_avg(length, default) return public end --- TIME -- +--#endregion + +--#region TYPES + +-- is a value a boolean +---@nodiscard +---@param x any value +---@return boolean is_boolean +function util.is_bool(x) return type(x) == "boolean" end + +-- is a value a number +---@nodiscard +---@param x any value +---@return boolean is_number +function util.is_num(x) return type(x) == "number" end + +-- is a value an integer +---@nodiscard +---@param x any value +---@return boolean is_integer +function util.is_int(x) return type(x) == "number" and x == math.floor(x) end + +-- is a value a string +---@nodiscard +---@param x any value +---@return boolean is_string +function util.is_str(x) return type(x) == "string" end + +-- is a value a table +---@nodiscard +---@param x any value +---@return boolean is_table +function util.is_tbl(x) return type(x) == "table" end + +-- is a value a function +---@nodiscard +---@param x any value +---@return boolean is_function +function util.is_func(x) return type(x) == "function" end + +--#endregion + +--#region TIME -- current time ---@nodiscard @@ -257,8 +265,7 @@ function util.time() return util.time_ms() end --#endregion --- OS -- ---#region +--#region OS -- OS pull event raw wrapper with types ---@nodiscard @@ -299,8 +306,7 @@ end --#endregion --- PARALLELIZATION -- ---#region +--#region PARALLELIZATION -- protected sleep call so we still are in charge of catching termination ---@param t integer seconds @@ -330,8 +336,7 @@ end --#endregion --- TABLE UTILITIES -- ---#region +--#region TABLE UTILITIES -- delete elements from a table if the passed function returns false when passed a table element
-- put briefly: deletes elements that return false, keeps elements that return true @@ -371,8 +376,7 @@ end --#endregion --- MEKANISM POWER -- ---#region +--#region MEKANISM POWER -- convert Joules to FE ---@nodiscard @@ -441,8 +445,7 @@ end --#endregion --- UTILITY CLASSES -- ---#region +--#region UTILITY CLASSES -- WATCHDOG -- @@ -519,11 +522,11 @@ function util.new_validator() ---@class validator local public = {} - function public.assert_type_bool(value) valid = valid and type(value) == "boolean" end - function public.assert_type_num(value) valid = valid and type(value) == "number" end + function public.assert_type_bool(value) valid = valid and util.is_bool(value) end + function public.assert_type_num(value) valid = valid and util.is_num(value) end function public.assert_type_int(value) valid = valid and util.is_int(value) end - function public.assert_type_str(value) valid = valid and type(value) == "string" end - function public.assert_type_table(value) valid = valid and type(value) == "table" end + function public.assert_type_str(value) valid = valid and util.is_str(value) end + function public.assert_type_table(value) valid = valid and util.is_tbl(value) end function public.assert_eq(check, expect) valid = valid and check == expect end function public.assert_min(check, min) valid = valid and check >= min end @@ -533,7 +536,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_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 ---@nodiscard From 686b47898ced88927a5e6caa16798a5014656db5 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sun, 8 Oct 2023 12:47:51 -0400 Subject: [PATCH 02/11] #354 optimizations/minification --- scada-common/util.lua | 106 ++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 56 deletions(-) diff --git a/scada-common/util.lua b/scada-common/util.lua index b311511..97afdfd 100644 --- a/scada-common/util.lua +++ b/scada-common/util.lua @@ -4,6 +4,16 @@ 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 local util = {} @@ -29,6 +39,8 @@ end --#region PRINT +local p_time = "[%H:%M:%S] " + -- print ---@param message any function util.print(message) term.write(tostring(message)) end @@ -39,11 +51,11 @@ function util.println(message) print(tostring(message)) end -- timestamped print ---@param message any -function util.print_ts(message) term.write(os.date("[%H:%M:%S] ") .. tostring(message)) end +function util.print_ts(message) term.write(os.date(p_time) .. tostring(message)) end -- timestamped print line ---@param message any -function util.println_ts(message) print(os.date("[%H:%M:%S] ") .. tostring(message)) end +function util.println_ts(message) print(os.date(p_time) .. tostring(message)) end --#endregion @@ -54,10 +66,9 @@ function util.println_ts(message) print(os.date("[%H:%M:%S] ") .. tostring(messa ---@param val any ---@return string function util.strval(val) - local t = type(val) -- 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 - return "[" .. tostring(val) .. "]" + if (util.is_tbl(val) and (getmetatable(val) == nil or getmetatable(val).__tostring == nil)) or util.is_func(val) then + return table.concat{"[", tostring(val), "]"} else return tostring(val) end end @@ -77,7 +88,7 @@ function util.pad(str, n) local lpad = math.floor((n - len) / 2) local rpad = (n - len) - lpad - return util.spaces(lpad) .. str .. util.spaces(rpad) + return table.concat{util.spaces(lpad), str, util.spaces(rpad)} end -- wrap a string into a table of lines @@ -95,9 +106,9 @@ function util.strwrap(str, limit) return cc_strings.wrap(str, limit) end ---@return string ---@diagnostic disable-next-line: unused-vararg function util.concat(...) - local str = "" - for _, v in ipairs(arg) do str = str .. util.strval(v) end - return str + local strings = {} + for i = 1, #arg do strings[i] = util.strval(arg[i]) end + return table.concat(strings) end -- alias @@ -112,6 +123,9 @@ function util.sprintf(format, ...) return string.format(format, table.unpack(arg -- luacheck: unused args +local gsub_p_a, gsub_r_a = "^(%s-%d+)(%d%d%d)", "%1,%2" +local gsub_p_b, gsub_r_b = " %s-", "" + -- format a number string with commas as the thousands separator
-- subtracts from spaces at the start if present for each comma used ---@nodiscard @@ -123,11 +137,11 @@ function util.comma_format(num) local i = 1 while i > 0 do - formatted, i = formatted:gsub("^(%s-%d+)(%d%d%d)", '%1,%2') + formatted, i = formatted:gsub(gsub_p_a, gsub_r_a) if i > 0 then commas = commas + 1 end end - local _, num_spaces = formatted:gsub(" %s-", "") + local _, num_spaces = formatted:gsub(gsub_p_b, gsub_r_b) local remove = math.min(num_spaces, commas) formatted = string.sub(formatted, remove + 1) @@ -157,7 +171,7 @@ function util.round(x) return math.floor(x + 0.5) end function util.mov_avg(length, default) local data = {} local index = 1 - local last_t = 0 ---@type number|nil + local last_t = 0 ---@type number|nil ---@class moving_average local public = {} @@ -173,9 +187,7 @@ function util.mov_avg(length, default) ---@param x number new value ---@param t number? optional last update time to prevent duplicated entries function public.record(x, t) - if type(t) == "number" and last_t == t then - return - end + if util.is_num(t) and last_t == t then return end data[index] = x last_t = t @@ -202,61 +214,62 @@ end --#region TYPES +-- for speed +local b_str, n_str, s_str, t_str, f_str = "boolean", "number", "string", "table", "function" + -- is a value a boolean ---@nodiscard ---@param x any value ---@return boolean is_boolean -function util.is_bool(x) return type(x) == "boolean" end +function util.is_bool(x) return type(x) == b_str end -- is a value a number ---@nodiscard ---@param x any value ---@return boolean is_number -function util.is_num(x) return type(x) == "number" end +function util.is_num(x) return type(x) == n_str end -- is a value an integer ---@nodiscard ---@param x any value ---@return boolean is_integer -function util.is_int(x) return type(x) == "number" and x == math.floor(x) end +function util.is_int(x) return type(x) == n_str and x == math.floor(x) end -- is a value a string ---@nodiscard ---@param x any value ---@return boolean is_string -function util.is_str(x) return type(x) == "string" end +function util.is_str(x) return type(x) == s_str end -- is a value a table ---@nodiscard ---@param x any value ---@return boolean is_table -function util.is_tbl(x) return type(x) == "table" end +function util.is_tbl(x) return type(x) == t_str end -- is a value a function ---@nodiscard ---@param x any value ---@return boolean is_function -function util.is_func(x) return type(x) == "function" end +function util.is_func(x) return type(x) == f_str end --#endregion --#region TIME +local t_l = "local" + -- current time ---@nodiscard ---@return integer milliseconds -function util.time_ms() ---@diagnostic disable-next-line: undefined-field - return os.epoch('local') -end +function util.time_ms() return os.epoch(t_l) end -- current time ---@nodiscard ---@return number seconds -function util.time_s() ---@diagnostic disable-next-line: undefined-field - return os.epoch('local') / 1000.0 -end +function util.time_s() return os.epoch(t_l) / 1000.0 end -- current time ---@nodiscard @@ -271,10 +284,8 @@ function util.time() return util.time_ms() end ---@nodiscard ---@param target_event? string event to wait for ---@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 - return os.pullEventRaw(target_event) -end +function util.pull_event(target_event) return os.pullEventRaw(target_event) end -- OS queue event raw wrapper with types ---@param event os_event @@ -292,17 +303,13 @@ end ---@nodiscard ---@param t number timer duration in seconds ---@return integer timer ID -function util.start_timer(t) ---@diagnostic disable-next-line: undefined-field - return os.startTimer(t) -end +function util.start_timer(t) return os.startTimer(t) end -- cancel an OS timer ---@param timer integer timer ID -function util.cancel_timer(timer) ---@diagnostic disable-next-line: undefined-field - os.cancelTimer(timer) -end +function util.cancel_timer(timer) os.cancelTimer(timer) end --#endregion @@ -311,10 +318,8 @@ end -- protected sleep call so we still are in charge of catching termination ---@param t integer seconds --- EVENT_CONSUMER: this function consumes events -function util.psleep(t) ---@diagnostic disable-next-line: undefined-field - pcall(os.sleep, t) -end +function util.psleep(t) pcall(os.sleep, t) end -- no-op to provide a brief pause (1 tick) to yield
--- EVENT_CONSUMER: this function consumes events @@ -405,8 +410,7 @@ local function ZFE(fe) return fe / 1000000000000000000000.0 end -- how & why did ---@param format? string format override ---@return string str, string? unit function util.power_format(fe, combine_label, format) - local unit - local value + local unit, value if type(format) ~= "string" then format = "%.2f" end @@ -454,32 +458,25 @@ end ---@nodiscard ---@param timeout number timeout duration function util.new_watchdog(timeout) - local self = { - timeout = timeout, - wd_timer = util.start_timer(timeout) - } + local self = { timeout = timeout, wd_timer = util.start_timer(timeout) } ---@class watchdog local public = {} -- check if a timer is this watchdog ---@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 -- satiate the beast function public.feed() - if self.wd_timer ~= nil then - util.cancel_timer(self.wd_timer) - end + public.cancel() self.wd_timer = util.start_timer(self.timeout) end -- cancel the watchdog function public.cancel() - if self.wd_timer ~= nil then - util.cancel_timer(self.wd_timer) - end + if self.wd_timer ~= nil then util.cancel_timer(self.wd_timer) end end return public @@ -492,10 +489,7 @@ end ---@nodiscard ---@param period number clock period function util.new_clock(period) - local self = { - period = period, - timer = nil - } + local self = { period = period, timer = nil } ---@class clock local public = {} From 841227077266d777149c2d00c976fcbaa72a4408 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Fri, 13 Oct 2023 23:48:30 -0400 Subject: [PATCH 03/11] #354 some reversions --- scada-common/util.lua | 77 ++++++++++--------------------------------- 1 file changed, 18 insertions(+), 59 deletions(-) diff --git a/scada-common/util.lua b/scada-common/util.lua index 97afdfd..76b7ff6 100644 --- a/scada-common/util.lua +++ b/scada-common/util.lua @@ -18,7 +18,7 @@ local type = type local util = {} -- scada-common version -util.version = "1.1.3" +util.version = "1.1.4" util.TICK_TIME_S = 0.05 util.TICK_TIME_MS = 50 @@ -66,8 +66,9 @@ function util.println_ts(message) print(os.date(p_time) .. tostring(message)) en ---@param val any ---@return string function util.strval(val) + if type(val) == "string" then return val end -- this depends on Lua short-circuiting the or check for metatables (note: metatables won't have metatables) - if (util.is_tbl(val) and (getmetatable(val) == nil or getmetatable(val).__tostring == nil)) or util.is_func(val) then + if (type(val) == "table" and (getmetatable(val) == nil or getmetatable(val).__tostring == nil)) or type(val) == "function" then return table.concat{"[", tostring(val), "]"} else return tostring(val) end end @@ -123,9 +124,6 @@ function util.sprintf(format, ...) return string.format(format, table.unpack(arg -- luacheck: unused args -local gsub_p_a, gsub_r_a = "^(%s-%d+)(%d%d%d)", "%1,%2" -local gsub_p_b, gsub_r_b = " %s-", "" - -- format a number string with commas as the thousands separator
-- subtracts from spaces at the start if present for each comma used ---@nodiscard @@ -137,11 +135,11 @@ function util.comma_format(num) local i = 1 while i > 0 do - formatted, i = formatted:gsub(gsub_p_a, gsub_r_a) + formatted, i = formatted:gsub("^(%s-%d+)(%d%d%d)", "%1,%2") if i > 0 then commas = commas + 1 end end - local _, num_spaces = formatted:gsub(gsub_p_b, gsub_r_b) + local _, num_spaces = formatted:gsub(" %s-", "") local remove = math.min(num_spaces, commas) formatted = string.sub(formatted, remove + 1) @@ -153,6 +151,12 @@ end --#region MATH +-- is a value an integer +---@nodiscard +---@param x any value +---@return boolean is_integer +function util.is_int(x) return type(x) == "number" and x == math.floor(x) end + -- get the sign of a number ---@nodiscard ---@param x number value @@ -187,7 +191,7 @@ function util.mov_avg(length, default) ---@param x number new value ---@param t number? optional last update time to prevent duplicated entries function public.record(x, t) - if util.is_num(t) and last_t == t then return end + if type(t) == "number" and last_t == t then return end data[index] = x last_t = t @@ -212,64 +216,19 @@ end --#endregion ---#region TYPES - --- for speed -local b_str, n_str, s_str, t_str, f_str = "boolean", "number", "string", "table", "function" - --- is a value a boolean ----@nodiscard ----@param x any value ----@return boolean is_boolean -function util.is_bool(x) return type(x) == b_str end - --- is a value a number ----@nodiscard ----@param x any value ----@return boolean is_number -function util.is_num(x) return type(x) == n_str end - --- is a value an integer ----@nodiscard ----@param x any value ----@return boolean is_integer -function util.is_int(x) return type(x) == n_str and x == math.floor(x) end - --- is a value a string ----@nodiscard ----@param x any value ----@return boolean is_string -function util.is_str(x) return type(x) == s_str end - --- is a value a table ----@nodiscard ----@param x any value ----@return boolean is_table -function util.is_tbl(x) return type(x) == t_str end - --- is a value a function ----@nodiscard ----@param x any value ----@return boolean is_function -function util.is_func(x) return type(x) == f_str end - ---#endregion - --#region TIME -local t_l = "local" - -- current time ---@nodiscard ---@return integer milliseconds ---@diagnostic disable-next-line: undefined-field -function util.time_ms() return os.epoch(t_l) end +function util.time_ms() return os.epoch("local") end -- current time ---@nodiscard ---@return number seconds ---@diagnostic disable-next-line: undefined-field -function util.time_s() return os.epoch(t_l) / 1000.0 end +function util.time_s() return os.epoch("local") / 1000.0 end -- current time ---@nodiscard @@ -516,11 +475,11 @@ function util.new_validator() ---@class validator local public = {} - function public.assert_type_bool(value) valid = valid and util.is_bool(value) end - function public.assert_type_num(value) valid = valid and util.is_num(value) end + function public.assert_type_bool(value) valid = valid and type(value) == "boolean" end + function public.assert_type_num(value) valid = valid and type(value) == "number" end function public.assert_type_int(value) valid = valid and util.is_int(value) end - function public.assert_type_str(value) valid = valid and util.is_str(value) end - function public.assert_type_table(value) valid = valid and util.is_tbl(value) end + function public.assert_type_str(value) valid = valid and type(value) == "string" end + function public.assert_type_table(value) valid = valid and type(value) == "table" end function public.assert_eq(check, expect) valid = valid and check == expect end function public.assert_min(check, min) valid = valid and check >= min end From 73ceed0f6029f983248ff264997db1b5f9f29c1a Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Fri, 13 Oct 2023 23:53:15 -0400 Subject: [PATCH 04/11] #354 another reversion --- scada-common/util.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scada-common/util.lua b/scada-common/util.lua index 76b7ff6..11dc2a8 100644 --- a/scada-common/util.lua +++ b/scada-common/util.lua @@ -66,9 +66,10 @@ function util.println_ts(message) print(os.date(p_time) .. tostring(message)) en ---@param val any ---@return string function util.strval(val) - if type(val) == "string" then return val end + 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) - if (type(val) == "table" and (getmetatable(val) == nil or getmetatable(val).__tostring == nil)) or type(val) == "function" then + if (t == "table" and (getmetatable(val) == nil or getmetatable(val).__tostring == nil)) or t == "function" then return table.concat{"[", tostring(val), "]"} else return tostring(val) end end From 670ca78a5b7ea3c2353b6e472809da0b64c23c3f Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 14 Oct 2023 00:38:13 -0400 Subject: [PATCH 05/11] #356 fixed extract assert msg --- graphics/core.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphics/core.lua b/graphics/core.lua index 7715f92..a4a45fa 100644 --- a/graphics/core.lua +++ b/graphics/core.lua @@ -7,7 +7,7 @@ local flasher = require("graphics.flasher") local core = {} -core.version = "2.0.0" +core.version = "2.0.1" core.flasher = flasher core.events = events @@ -115,7 +115,7 @@ end -- extract the custom element assert message, dropping the path to the element file 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 -- Interactive Field Manager From 86e8feaabc64398e6923fbd1ea2ad0dd4ff16079 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 14 Oct 2023 10:07:56 -0400 Subject: [PATCH 06/11] #358 fixed non-networked PLC operation --- reactor-plc/plc.lua | 18 +++++++++++------- reactor-plc/startup.lua | 4 ++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/reactor-plc/plc.lua b/reactor-plc/plc.lua index 02d7c3d..a2dfd73 100644 --- a/reactor-plc/plc.lua +++ b/reactor-plc/plc.lua @@ -54,13 +54,17 @@ function plc.load_config() cfv.assert_type_bool(config.Networked) cfv.assert_type_int(config.UnitID) cfv.assert_type_bool(config.EmerCoolEnable) - cfv.assert_channel(config.SVR_Channel) - cfv.assert_channel(config.PLC_Channel) - cfv.assert_type_int(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 config.Networked == true then + cfv.assert_channel(config.SVR_Channel) + cfv.assert_channel(config.PLC_Channel) + cfv.assert_type_int(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) + end + cfv.assert_type_int(config.LogMode) cfv.assert_type_str(config.LogPath) cfv.assert_type_bool(config.LogDebug) diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index 7ad0d27..dde862e 100644 --- a/reactor-plc/startup.lua +++ b/reactor-plc/startup.lua @@ -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.0" +local R_PLC_VERSION = "v1.6.1" local println = util.println local println_ts = util.println_ts @@ -69,7 +69,7 @@ local function main() ppm.mount_all() -- 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) end From 6f1195ddedebbf6bb99a06d61ae1d840f95ebfa9 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 14 Oct 2023 11:40:36 -0400 Subject: [PATCH 07/11] fixed element assertion scope on frame validations --- graphics/core.lua | 2 +- graphics/element.lua | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/graphics/core.lua b/graphics/core.lua index a4a45fa..d6518ba 100644 --- a/graphics/core.lua +++ b/graphics/core.lua @@ -7,7 +7,7 @@ local flasher = require("graphics.flasher") local core = {} -core.version = "2.0.1" +core.version = "2.0.2" core.flasher = flasher core.events = events diff --git a/graphics/element.lua b/graphics/element.lua index 41e4c57..dcdccc4 100644 --- a/graphics/element.lua +++ b/graphics/element.lua @@ -217,10 +217,10 @@ function element.new(args, child_offset_x, child_offset_y) end -- check frame - element.assert(f.x >= 1, "frame x not >= 1", 2) - element.assert(f.y >= 1, "frame y not >= 1", 2) - element.assert(f.w >= 1, "frame width not >= 1", 2) - element.assert(f.h >= 1, "frame height not >= 1", 2) + element.assert(f.x >= 1, "frame x not >= 1", 3) + element.assert(f.y >= 1, "frame y not >= 1", 3) + element.assert(f.w >= 1, "frame width not >= 1", 3) + element.assert(f.h >= 1, "frame height not >= 1", 3) -- create window protected.window = window.create(self.p_window, f.x, f.y, f.w, f.h, args.hidden ~= true) From 41442012c26cd80403b4a324dc3a8c5697b0d158 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 14 Oct 2023 12:02:25 -0400 Subject: [PATCH 08/11] #357 min length of auth key and some cleanup, added config change log --- reactor-plc/configure.lua | 92 +++++++++++++++++++++++++++------------ reactor-plc/plc.lua | 5 +++ reactor-plc/startup.lua | 4 +- 3 files changed, 70 insertions(+), 31 deletions(-) diff --git a/reactor-plc/configure.lua b/reactor-plc/configure.lua index 7ad98a3..4347a7f 100644 --- a/reactor-plc/configure.lua +++ b/reactor-plc/configure.lua @@ -30,6 +30,11 @@ 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 = { + {"v1.6.2", { "AuthKey minimum length is now 8 (if set)" } } +} + ---@class plc_configurator local configurator = {} @@ -37,7 +42,6 @@ local style = {} style.root = cpair(colors.black, colors.lightGray) style.header = cpair(colors.white, colors.gray) -style.label = cpair(colors.gray, colors.lightGray) style.colors = { { c = colors.red, hex = 0xdf4949 }, @@ -55,6 +59,11 @@ style.colors = { { 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 = { ask_config = false, has_config = false, @@ -173,8 +182,6 @@ end -- create the config view ---@param display graphics_element 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 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 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,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 @@ -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."} 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)} - y_start = y_start + 3 + 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 + 5 end 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 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 @@ -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_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)} @@ -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} 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 #"} - 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} @@ -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} 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)} @@ -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"} 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 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_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"} - 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)} - TextBox{parent=net_c_1,x=9,y=9,height=4,text_align=CENTER,text="[SVR_CHANNEL]",fg_bg=cpair(colors.gray,colors.lightGray)} + 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=g_lg_fg_bg} 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)} - TextBox{parent=net_c_1,x=9,y=12,height=4,text_align=CENTER,text="[PLC_CHANNEL]",fg_bg=cpair(colors.gray,colors.lightGray)} + 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=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} @@ -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} 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)} - 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=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)} + 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=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=g_lg_fg_bg} 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)} - 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)} + 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=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} @@ -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} 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"} - 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 @@ -385,9 +394,15 @@ local function config_view(display) hide_key.set_value(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() - tmp_cfg.AuthKey = key.get_value() - main_pane.set_value(4) + 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(4) + key_err.hide(true) + else key_err.show() 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} @@ -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} 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)} - 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} @@ -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)} - 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() 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=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 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 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 if string.len(val) > val_max_w then diff --git a/reactor-plc/plc.lua b/reactor-plc/plc.lua index a2dfd73..9ad9c69 100644 --- a/reactor-plc/plc.lua +++ b/reactor-plc/plc.lua @@ -63,6 +63,11 @@ function plc.load_config() 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_eq(len == 0 or len >= 8, true) + end end cfv.assert_type_int(config.LogMode) diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index dde862e..9f6a8a9 100644 --- a/reactor-plc/startup.lua +++ b/reactor-plc/startup.lua @@ -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.1" +local R_PLC_VERSION = "v1.6.2" local println = util.println local println_ts = util.println_ts @@ -50,7 +50,7 @@ log.info("BOOTING reactor-plc.startup " .. R_PLC_VERSION) log.info("========================================") println(">> Reactor PLC " .. R_PLC_VERSION .. " <<") -crash.set_env("plc", R_PLC_VERSION) +crash.set_env("reactor-plc", R_PLC_VERSION) ---------------------------------------- -- main application From f95ac8be8cd83d6f266be65a0e7e1a8e5be1a239 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 14 Oct 2023 12:17:25 -0400 Subject: [PATCH 09/11] #359 drop packets with nil distances if using trusted range feature --- scada-common/comms.lua | 2 +- scada-common/util.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scada-common/comms.lua b/scada-common/comms.lua index 1e3373f..07abdb8 100644 --- a/scada-common/comms.lua +++ b/scada-common/comms.lua @@ -311,7 +311,7 @@ function comms.authd_packet() self.valid = false 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 -- log.debug("comms.authd_packet.receive(): discarding packet with distance " .. distance .. " (outside trusted range)") else diff --git a/scada-common/util.lua b/scada-common/util.lua index 11dc2a8..eb3fdab 100644 --- a/scada-common/util.lua +++ b/scada-common/util.lua @@ -18,7 +18,7 @@ local type = type local util = {} -- scada-common version -util.version = "1.1.4" +util.version = "1.1.5" util.TICK_TIME_S = 0.05 util.TICK_TIME_MS = 50 From 24c787f47d8c423adf7ae8d48295a15eecd0efea Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 14 Oct 2023 17:57:50 -0400 Subject: [PATCH 10/11] #353 fixed auto lock not restoring on reconnect --- supervisor/session/plc.lua | 3 +++ supervisor/startup.lua | 2 +- supervisor/unit.lua | 11 ++++++----- supervisor/unitlogic.lua | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index 85a6534..9c79434 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.lua @@ -590,6 +590,9 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f end end + -- check if the auto lock is active + function public.is_auto_locked() return self.auto_lock end + -- set the burn rate on behalf of automatic control ---@param rate number burn rate ---@param ramp boolean true to ramp, false to not diff --git a/supervisor/startup.lua b/supervisor/startup.lua index a1327f1..ec27930 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -21,7 +21,7 @@ local supervisor = require("supervisor.supervisor") local svsessions = require("supervisor.session.svsessions") -local SUPERVISOR_VERSION = "v1.0.8" +local SUPERVISOR_VERSION = "v1.0.9" local println = util.println local println_ts = util.println_ts diff --git a/supervisor/unit.lua b/supervisor/unit.lua index e0fe65e..ad6c3b0 100644 --- a/supervisor/unit.lua +++ b/supervisor/unit.lua @@ -498,7 +498,6 @@ function unit.new(reactor_id, num_boilers, num_turbines) self.plc_s = nil self.plc_i = nil self.db.control.br100 = 0 - self.db.control.lim_br100 = 0 end -- unlink RTU unit sessions if they are closed @@ -525,12 +524,14 @@ function unit.new(reactor_id, num_boilers, num_turbines) end end - -- check plc formed/faulted + -- plc instance checks if self.plc_i ~= nil then + -- check if degraded local rps = self.plc_i.get_rps() - if rps.fault or rps.sys_fail then - self.db.control.degraded = true - end + if rps.fault or rps.sys_fail then 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 -- update deltas diff --git a/supervisor/unitlogic.lua b/supervisor/unitlogic.lua index eb7fa27..f16f197 100644 --- a/supervisor/unitlogic.lua +++ b/supervisor/unitlogic.lua @@ -75,7 +75,7 @@ function logic.update_annunciator(self) (next(self.plc_i.get_status()) ~= nil) and (next(self.plc_i.get_struct()) ~= nil) -- 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) end From 43d134d9adb858a0e9b2456f6f1a6c4aa97a6cab Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sat, 14 Oct 2023 18:49:51 -0400 Subject: [PATCH 11/11] comment clarity --- supervisor/session/plc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index 9c79434..5bb097e 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.lua @@ -590,7 +590,7 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f end end - -- check if the auto lock is active + -- 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