From 9ce75eb4bde08b58d8c80b9b27d6adf325a4c75d Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Sun, 30 Jul 2023 12:24:54 -0400 Subject: [PATCH] #283 common cleanup, added lockbox version to crash dump, changed crash handler to pcall requires for graphics/lockbox --- scada-common/constants.lua | 4 ++++ scada-common/crash.lua | 7 +++++-- scada-common/log.lua | 7 ++----- scada-common/mqueue.lua | 42 +++++++++++++++----------------------- scada-common/network.lua | 10 +++++---- scada-common/ppm.lua | 34 +++++++++++------------------- scada-common/psil.lua | 38 ++++++++++++++++------------------ scada-common/rsio.lua | 2 +- scada-common/tcd.lua | 2 +- scada-common/util.lua | 13 +++++++----- 10 files changed, 73 insertions(+), 86 deletions(-) diff --git a/scada-common/constants.lua b/scada-common/constants.lua index 7c661ee..eaf6dd3 100644 --- a/scada-common/constants.lua +++ b/scada-common/constants.lua @@ -2,10 +2,12 @@ -- System and Safety Constants -- +---@class scada_constants local constants = {} --#region Reactor Protection System (on the PLC) Limits +---@class _rps_constants local rps = {} rps.MAX_DAMAGE_PERCENT = 90 -- damage >= 90% @@ -21,6 +23,7 @@ constants.RPS_LIMITS = rps --#region Annunciator Limits +---@class _annunciator_constants local annunc = {} annunc.RCSFlowLow_H2O = -3.2 -- flow < -3.2 mB/s @@ -44,6 +47,7 @@ constants.ANNUNCIATOR_LIMITS = annunc --#region Supervisor Alarm Limits +---@class _alarm_constants local alarms = {} -- unit alarms diff --git a/scada-common/crash.lua b/scada-common/crash.lua index 45a3874..1942a8d 100644 --- a/scada-common/crash.lua +++ b/scada-common/crash.lua @@ -6,8 +6,10 @@ local comms = require("scada-common.comms") local log = require("scada-common.log") local util = require("scada-common.util") -local core = require("graphics.core") +local has_graphics, core = pcall(require, "graphics.core") +local has_lockbox, lockbox = pcall(require, "lockbox") +---@class crash_handler local crash = {} local app = "unknown" @@ -34,7 +36,8 @@ function crash.handler(error) log.info(util.c("APPLICATION: ", app)) log.info(util.c("FIRMWARE VERSION: ", ver)) log.info(util.c("COMMS VERSION: ", comms.version)) - log.info(util.c("GRAPHICS VERSION: ", core.version)) + if has_graphics then log.info(util.c("GRAPHICS VERSION: ", core.version)) end + if has_lockbox then log.info(util.c("LOCKBOX VERSION: ", lockbox.version)) end log.info("----------------------------------") log.info(debug.traceback("--- begin debug trace ---", 1)) log.info("--- end debug trace ---") diff --git a/scada-common/log.lua b/scada-common/log.lua index 51b5373..2c266bb 100644 --- a/scada-common/log.lua +++ b/scada-common/log.lua @@ -4,14 +4,11 @@ local util = require("scada-common.util") ----@class log +---@class logger local log = {} ---@alias MODE integer -local MODE = { - APPEND = 0, - NEW = 1 -} +local MODE = { APPEND = 0, NEW = 1 } log.MODE = MODE diff --git a/scada-common/mqueue.lua b/scada-common/mqueue.lua index b48e4ad..fc60a1e 100644 --- a/scada-common/mqueue.lua +++ b/scada-common/mqueue.lua @@ -4,6 +4,14 @@ local mqueue = {} +---@class queue_item +---@field qtype MQ_TYPE +---@field message any + +---@class queue_data +---@field key any +---@field val any + ---@enum MQ_TYPE local TYPE = { COMMAND = 0, @@ -13,22 +21,14 @@ local TYPE = { mqueue.TYPE = TYPE +local insert = table.insert +local remove = table.remove + -- create a new message queue ---@nodiscard function mqueue.new() local queue = {} - local insert = table.insert - local remove = table.remove - - ---@class queue_item - ---@field qtype MQ_TYPE - ---@field message any - - ---@class queue_data - ---@field key any - ---@field val any - ---@class mqueue local public = {} @@ -48,28 +48,20 @@ function mqueue.new() -- push a new item onto the queue ---@param qtype MQ_TYPE ---@param message any - local function _push(qtype, message) - insert(queue, { qtype = qtype, message = message }) - end + local function _push(qtype, message) insert(queue, { qtype = qtype, message = message }) end -- push a command onto the queue ---@param message any - function public.push_command(message) - _push(TYPE.COMMAND, message) - end + function public.push_command(message) _push(TYPE.COMMAND, message) end -- push data onto the queue ---@param key any ---@param value any - function public.push_data(key, value) - _push(TYPE.DATA, { key = key, val = value }) - end + function public.push_data(key, value) _push(TYPE.DATA, { key = key, val = value }) end -- push a packet onto the queue ---@param packet packet|frame - function public.push_packet(packet) - _push(TYPE.PACKET, packet) - end + function public.push_packet(packet) _push(TYPE.PACKET, packet) end -- get an item off the queue ---@nodiscard @@ -77,9 +69,7 @@ function mqueue.new() function public.pop() if #queue > 0 then return remove(queue, 1) - else - return nil - end + else return nil end end return public diff --git a/scada-common/network.lua b/scada-common/network.lua index f8275bc..d9fa83f 100644 --- a/scada-common/network.lua +++ b/scada-common/network.lua @@ -2,19 +2,21 @@ -- Network Communications -- +local comms = require("scada-common.comms") +local log = require("scada-common.log") +local util = require("scada-common.util") + local md5 = require("lockbox.digest.md5") local sha256 = require("lockbox.digest.sha2_256") local pbkdf2 = require("lockbox.kdf.pbkdf2") local hmac = require("lockbox.mac.hmac") local stream = require("lockbox.util.stream") local array = require("lockbox.util.array") -local comms = require("scada-common.comms") - -local log = require("scada-common.log") -local util = require("scada-common.util") +---@class scada_net_interface local network = {} +-- cryptography engine local c_eng = { key = nil, hmac = nil diff --git a/scada-common/ppm.lua b/scada-common/ppm.lua index 90f0b17..6af4e2f 100644 --- a/scada-common/ppm.lua +++ b/scada-common/ppm.lua @@ -8,15 +8,13 @@ local util = require("scada-common.util") ---@class ppm local ppm = {} -local ACCESS_FAULT = nil ---@type nil - -local UNDEFINED_FIELD = "undefined field" - +local ACCESS_FAULT = nil ---@type nil +local UNDEFINED_FIELD = "undefined field" local VIRTUAL_DEVICE_TYPE = "ppm_vdev" -ppm.ACCESS_FAULT = ACCESS_FAULT -ppm.UNDEFINED_FIELD = UNDEFINED_FIELD -ppm.VIRTUAL_DEVICE_TYPE = VIRTUAL_DEVICE_TYPE +ppm.ACCESS_FAULT = ACCESS_FAULT +ppm.UNDEFINED_FIELD = UNDEFINED_FIELD +ppm.VIRTUAL_DEVICE_TYPE = VIRTUAL_DEVICE_TYPE ---------------------------- -- PRIVATE DATA/FUNCTIONS -- @@ -34,9 +32,9 @@ local ppm_sys = { mute = false } --- wrap peripheral calls with lua protected call as we don't want a disconnect to crash a program
--- also provides peripheral-specific fault checks (auto-clear fault defaults to true)
--- assumes iface is a valid peripheral +-- Wrap peripheral calls with lua protected call as we don't want a disconnect to crash a program. +-- Additionally provides peripheral-specific fault checks (auto-clear fault defaults to true).
+-- Note: assumes iface is a valid peripheral. ---@param iface string CC peripheral interface local function peri_init(iface) local self = { @@ -307,16 +305,12 @@ end -- list all available peripherals ---@nodiscard ---@return table names -function ppm.list_avail() - return peripheral.getNames() -end +function ppm.list_avail() return peripheral.getNames() end -- list mounted peripherals ---@nodiscard ---@return table mounts -function ppm.list_mounts() - return ppm_sys.mounts -end +function ppm.list_mounts() return ppm_sys.mounts end -- get a mounted peripheral side/interface by device table ---@nodiscard @@ -390,9 +384,7 @@ end -- get the fission reactor (if multiple, returns the first) ---@nodiscard ---@return table|nil reactor function table -function ppm.get_fission_reactor() - return ppm.get_device("fissionReactorLogicAdapter") -end +function ppm.get_fission_reactor() return ppm.get_device("fissionReactorLogicAdapter") end -- get the wireless modem (if multiple, returns the first)
-- if this is in a CraftOS emulated environment, wired modems will be used instead @@ -419,9 +411,7 @@ function ppm.get_monitor_list() local list = {} for iface, device in pairs(ppm_sys.mounts) do - if device.type == "monitor" then - list[iface] = device - end + if device.type == "monitor" then list[iface] = device end end return list diff --git a/scada-common/psil.lua b/scada-common/psil.lua index 13dcaa5..09686bf 100644 --- a/scada-common/psil.lua +++ b/scada-common/psil.lua @@ -9,14 +9,12 @@ local psil = {} -- instantiate a new PSI layer ---@nodiscard function psil.create() - local self = { - ic = {} - } + local ic = {} -- allocate a new interconnect field ---@key string data key local function alloc(key) - self.ic[key] = { subscribers = {}, value = nil } + ic[key] = { subscribers = {}, value = nil } end ---@class psil @@ -28,22 +26,22 @@ function psil.create() ---@param func function function to call on change function public.subscribe(key, func) -- allocate new key if not found or notify if value is found - if self.ic[key] == nil then + if ic[key] == nil then alloc(key) - elseif self.ic[key].value ~= nil then - func(self.ic[key].value) + elseif ic[key].value ~= nil then + func(ic[key].value) end -- subscribe to key - table.insert(self.ic[key].subscribers, { notify = func }) + table.insert(ic[key].subscribers, { notify = func }) end -- unsubscribe a function from a given key ---@param key string data key ---@param func function function to unsubscribe function public.unsubscribe(key, func) - if self.ic[key] ~= nil then - util.filter_table(self.ic[key].subscribers, function (s) return s.notify ~= func end) + if ic[key] ~= nil then + util.filter_table(ic[key].subscribers, function (s) return s.notify ~= func end) end end @@ -51,32 +49,32 @@ function psil.create() ---@param key string data key ---@param value any data value function public.publish(key, value) - if self.ic[key] == nil then alloc(key) end + if ic[key] == nil then alloc(key) end - if self.ic[key].value ~= value then - for i = 1, #self.ic[key].subscribers do - self.ic[key].subscribers[i].notify(value) + if ic[key].value ~= value then + for i = 1, #ic[key].subscribers do + ic[key].subscribers[i].notify(value) end end - self.ic[key].value = value + ic[key].value = value end -- publish a toggled boolean value to a given key, passing it to all subscribers if it has changed
-- this is intended to be used to toggle boolean indicators such as heartbeats without extra state variables ---@param key string data key function public.toggle(key) - if self.ic[key] == nil then alloc(key) end + if ic[key] == nil then alloc(key) end - self.ic[key].value = self.ic[key].value == false + ic[key].value = ic[key].value == false - for i = 1, #self.ic[key].subscribers do - self.ic[key].subscribers[i].notify(self.ic[key].value) + for i = 1, #ic[key].subscribers do + ic[key].subscribers[i].notify(ic[key].value) end end -- clear the contents of the interconnect - function public.purge() self.ic = nil end + function public.purge() ic = {} end return public end diff --git a/scada-common/rsio.lua b/scada-common/rsio.lua index 29acfd2..13a6d6a 100644 --- a/scada-common/rsio.lua +++ b/scada-common/rsio.lua @@ -123,7 +123,7 @@ function rsio.to_string(port) if util.is_int(port) and port > 0 and port <= #names then return names[port] else - return "" + return "UNKNOWN" end end diff --git a/scada-common/tcd.lua b/scada-common/tcd.lua index f5ff0e5..a3c920f 100644 --- a/scada-common/tcd.lua +++ b/scada-common/tcd.lua @@ -68,7 +68,7 @@ function tcd.handle(event) end end --- identify any overdo callbacks
+-- identify any overdue callbacks
-- prints to log debug output function tcd.diagnostics() for timer, entry in pairs(registry) do diff --git a/scada-common/util.lua b/scada-common/util.lua index 99f62a6..2d32eae 100644 --- a/scada-common/util.lua +++ b/scada-common/util.lua @@ -80,9 +80,9 @@ end ---@return string function util.strrep(str, n) local repeated = "" - for _ = 1, n do - repeated = repeated .. str - end + + for _ = 1, n do repeated = repeated .. str end + return repeated end @@ -123,7 +123,9 @@ 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 @@ -322,7 +324,8 @@ end --- EVENT_CONSUMER: this function consumes events function util.nop() util.psleep(0.05) end --- attempt to maintain a minimum loop timing (duration of execution) +-- attempt to maintain a minimum loop timing (duration of execution)
+-- note: will not yield for time periods less than 50ms ---@nodiscard ---@param target_timing integer minimum amount of milliseconds to wait for ---@param last_update integer millisecond time of last update @@ -399,7 +402,7 @@ local function GFE(fe) return fe / 1000000000.0 end local function TFE(fe) return fe / 1000000000000.0 end local function PFE(fe) return fe / 1000000000000000.0 end local function EFE(fe) return fe / 1000000000000000000.0 end -- if you accomplish this please touch grass -local function ZFE(fe) return fe / 1000000000000000000000.0 end -- please stop +local function ZFE(fe) return fe / 1000000000000000000000.0 end -- how & why did you do this? -- format a power value into XXX.XX UNIT format (FE, kFE, MFE, GFE, TFE, PFE, EFE, ZFE) ---@nodiscard