#283 common cleanup, added lockbox version to crash dump, changed crash handler to pcall requires for graphics/lockbox

This commit is contained in:
Mikayla Fischler 2023-07-30 12:24:54 -04:00
parent 451f804f87
commit 9ce75eb4bd
10 changed files with 73 additions and 86 deletions

View File

@ -2,10 +2,12 @@
-- System and Safety Constants -- System and Safety Constants
-- --
---@class scada_constants
local constants = {} local constants = {}
--#region Reactor Protection System (on the PLC) Limits --#region Reactor Protection System (on the PLC) Limits
---@class _rps_constants
local rps = {} local rps = {}
rps.MAX_DAMAGE_PERCENT = 90 -- damage >= 90% rps.MAX_DAMAGE_PERCENT = 90 -- damage >= 90%
@ -21,6 +23,7 @@ constants.RPS_LIMITS = rps
--#region Annunciator Limits --#region Annunciator Limits
---@class _annunciator_constants
local annunc = {} local annunc = {}
annunc.RCSFlowLow_H2O = -3.2 -- flow < -3.2 mB/s annunc.RCSFlowLow_H2O = -3.2 -- flow < -3.2 mB/s
@ -44,6 +47,7 @@ constants.ANNUNCIATOR_LIMITS = annunc
--#region Supervisor Alarm Limits --#region Supervisor Alarm Limits
---@class _alarm_constants
local alarms = {} local alarms = {}
-- unit alarms -- unit alarms

View File

@ -6,8 +6,10 @@ local comms = require("scada-common.comms")
local log = require("scada-common.log") local log = require("scada-common.log")
local util = require("scada-common.util") 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 crash = {}
local app = "unknown" local app = "unknown"
@ -34,7 +36,8 @@ function crash.handler(error)
log.info(util.c("APPLICATION: ", app)) log.info(util.c("APPLICATION: ", app))
log.info(util.c("FIRMWARE VERSION: ", ver)) log.info(util.c("FIRMWARE VERSION: ", ver))
log.info(util.c("COMMS VERSION: ", comms.version)) 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("----------------------------------")
log.info(debug.traceback("--- begin debug trace ---", 1)) log.info(debug.traceback("--- begin debug trace ---", 1))
log.info("--- end debug trace ---") log.info("--- end debug trace ---")

View File

@ -4,14 +4,11 @@
local util = require("scada-common.util") local util = require("scada-common.util")
---@class log ---@class logger
local log = {} local log = {}
---@alias MODE integer ---@alias MODE integer
local MODE = { local MODE = { APPEND = 0, NEW = 1 }
APPEND = 0,
NEW = 1
}
log.MODE = MODE log.MODE = MODE

View File

@ -4,6 +4,14 @@
local mqueue = {} local mqueue = {}
---@class queue_item
---@field qtype MQ_TYPE
---@field message any
---@class queue_data
---@field key any
---@field val any
---@enum MQ_TYPE ---@enum MQ_TYPE
local TYPE = { local TYPE = {
COMMAND = 0, COMMAND = 0,
@ -13,22 +21,14 @@ local TYPE = {
mqueue.TYPE = TYPE mqueue.TYPE = TYPE
local insert = table.insert
local remove = table.remove
-- create a new message queue -- create a new message queue
---@nodiscard ---@nodiscard
function mqueue.new() function mqueue.new()
local queue = {} 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 ---@class mqueue
local public = {} local public = {}
@ -48,28 +48,20 @@ function mqueue.new()
-- push a new item onto the queue -- push a new item onto the queue
---@param qtype MQ_TYPE ---@param qtype MQ_TYPE
---@param message any ---@param message any
local function _push(qtype, message) local function _push(qtype, message) insert(queue, { qtype = qtype, message = message }) end
insert(queue, { qtype = qtype, message = message })
end
-- push a command onto the queue -- push a command onto the queue
---@param message any ---@param message any
function public.push_command(message) function public.push_command(message) _push(TYPE.COMMAND, message) end
_push(TYPE.COMMAND, message)
end
-- push data onto the queue -- push data onto the queue
---@param key any ---@param key any
---@param value any ---@param value any
function public.push_data(key, value) function public.push_data(key, value) _push(TYPE.DATA, { key = key, val = value }) end
_push(TYPE.DATA, { key = key, val = value })
end
-- push a packet onto the queue -- push a packet onto the queue
---@param packet packet|frame ---@param packet packet|frame
function public.push_packet(packet) function public.push_packet(packet) _push(TYPE.PACKET, packet) end
_push(TYPE.PACKET, packet)
end
-- get an item off the queue -- get an item off the queue
---@nodiscard ---@nodiscard
@ -77,9 +69,7 @@ function mqueue.new()
function public.pop() function public.pop()
if #queue > 0 then if #queue > 0 then
return remove(queue, 1) return remove(queue, 1)
else else return nil end
return nil
end
end end
return public return public

View File

@ -2,19 +2,21 @@
-- Network Communications -- 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 md5 = require("lockbox.digest.md5")
local sha256 = require("lockbox.digest.sha2_256") local sha256 = require("lockbox.digest.sha2_256")
local pbkdf2 = require("lockbox.kdf.pbkdf2") local pbkdf2 = require("lockbox.kdf.pbkdf2")
local hmac = require("lockbox.mac.hmac") local hmac = require("lockbox.mac.hmac")
local stream = require("lockbox.util.stream") local stream = require("lockbox.util.stream")
local array = require("lockbox.util.array") 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 = {} local network = {}
-- cryptography engine
local c_eng = { local c_eng = {
key = nil, key = nil,
hmac = nil hmac = nil

View File

@ -8,15 +8,13 @@ local util = require("scada-common.util")
---@class ppm ---@class ppm
local ppm = {} local ppm = {}
local ACCESS_FAULT = nil ---@type nil local ACCESS_FAULT = nil ---@type nil
local UNDEFINED_FIELD = "undefined field"
local UNDEFINED_FIELD = "undefined field"
local VIRTUAL_DEVICE_TYPE = "ppm_vdev" local VIRTUAL_DEVICE_TYPE = "ppm_vdev"
ppm.ACCESS_FAULT = ACCESS_FAULT ppm.ACCESS_FAULT = ACCESS_FAULT
ppm.UNDEFINED_FIELD = UNDEFINED_FIELD ppm.UNDEFINED_FIELD = UNDEFINED_FIELD
ppm.VIRTUAL_DEVICE_TYPE = VIRTUAL_DEVICE_TYPE ppm.VIRTUAL_DEVICE_TYPE = VIRTUAL_DEVICE_TYPE
---------------------------- ----------------------------
-- PRIVATE DATA/FUNCTIONS -- -- PRIVATE DATA/FUNCTIONS --
@ -34,9 +32,9 @@ local ppm_sys = {
mute = false mute = false
} }
-- wrap peripheral calls with lua protected call as we don't want a disconnect to crash a program<br> -- 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)<br> -- Additionally provides peripheral-specific fault checks (auto-clear fault defaults to true).<br>
-- assumes iface is a valid peripheral -- Note: assumes iface is a valid peripheral.
---@param iface string CC peripheral interface ---@param iface string CC peripheral interface
local function peri_init(iface) local function peri_init(iface)
local self = { local self = {
@ -307,16 +305,12 @@ end
-- list all available peripherals -- list all available peripherals
---@nodiscard ---@nodiscard
---@return table names ---@return table names
function ppm.list_avail() function ppm.list_avail() return peripheral.getNames() end
return peripheral.getNames()
end
-- list mounted peripherals -- list mounted peripherals
---@nodiscard ---@nodiscard
---@return table mounts ---@return table mounts
function ppm.list_mounts() function ppm.list_mounts() return ppm_sys.mounts end
return ppm_sys.mounts
end
-- get a mounted peripheral side/interface by device table -- get a mounted peripheral side/interface by device table
---@nodiscard ---@nodiscard
@ -390,9 +384,7 @@ end
-- get the fission reactor (if multiple, returns the first) -- get the fission reactor (if multiple, returns the first)
---@nodiscard ---@nodiscard
---@return table|nil reactor function table ---@return table|nil reactor function table
function ppm.get_fission_reactor() function ppm.get_fission_reactor() return ppm.get_device("fissionReactorLogicAdapter") end
return ppm.get_device("fissionReactorLogicAdapter")
end
-- get the wireless modem (if multiple, returns the first)<br> -- get the wireless modem (if multiple, returns the first)<br>
-- if this is in a CraftOS emulated environment, wired modems will be used instead -- 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 = {} local list = {}
for iface, device in pairs(ppm_sys.mounts) do for iface, device in pairs(ppm_sys.mounts) do
if device.type == "monitor" then if device.type == "monitor" then list[iface] = device end
list[iface] = device
end
end end
return list return list

View File

@ -9,14 +9,12 @@ local psil = {}
-- instantiate a new PSI layer -- instantiate a new PSI layer
---@nodiscard ---@nodiscard
function psil.create() function psil.create()
local self = { local ic = {}
ic = {}
}
-- allocate a new interconnect field -- allocate a new interconnect field
---@key string data key ---@key string data key
local function alloc(key) local function alloc(key)
self.ic[key] = { subscribers = {}, value = nil } ic[key] = { subscribers = {}, value = nil }
end end
---@class psil ---@class psil
@ -28,22 +26,22 @@ function psil.create()
---@param func function function to call on change ---@param func function function to call on change
function public.subscribe(key, func) function public.subscribe(key, func)
-- allocate new key if not found or notify if value is found -- 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) alloc(key)
elseif self.ic[key].value ~= nil then elseif ic[key].value ~= nil then
func(self.ic[key].value) func(ic[key].value)
end end
-- subscribe to key -- subscribe to key
table.insert(self.ic[key].subscribers, { notify = func }) table.insert(ic[key].subscribers, { notify = func })
end end
-- unsubscribe a function from a given key -- unsubscribe a function from a given key
---@param key string data key ---@param key string data key
---@param func function function to unsubscribe ---@param func function function to unsubscribe
function public.unsubscribe(key, func) function public.unsubscribe(key, func)
if self.ic[key] ~= nil then if ic[key] ~= nil then
util.filter_table(self.ic[key].subscribers, function (s) return s.notify ~= func end) util.filter_table(ic[key].subscribers, function (s) return s.notify ~= func end)
end end
end end
@ -51,32 +49,32 @@ function psil.create()
---@param key string data key ---@param key string data key
---@param value any data value ---@param value any data value
function public.publish(key, 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 if ic[key].value ~= value then
for i = 1, #self.ic[key].subscribers do for i = 1, #ic[key].subscribers do
self.ic[key].subscribers[i].notify(value) ic[key].subscribers[i].notify(value)
end end
end end
self.ic[key].value = value ic[key].value = value
end end
-- publish a toggled boolean value to a given key, passing it to all subscribers if it has changed<br> -- publish a toggled boolean value to a given key, passing it to all subscribers if it has changed<br>
-- this is intended to be used to toggle boolean indicators such as heartbeats without extra state variables -- this is intended to be used to toggle boolean indicators such as heartbeats without extra state variables
---@param key string data key ---@param key string data key
function public.toggle(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 for i = 1, #ic[key].subscribers do
self.ic[key].subscribers[i].notify(self.ic[key].value) ic[key].subscribers[i].notify(ic[key].value)
end end
end end
-- clear the contents of the interconnect -- clear the contents of the interconnect
function public.purge() self.ic = nil end function public.purge() ic = {} end
return public return public
end end

View File

@ -123,7 +123,7 @@ function rsio.to_string(port)
if util.is_int(port) and port > 0 and port <= #names then if util.is_int(port) and port > 0 and port <= #names then
return names[port] return names[port]
else else
return "" return "UNKNOWN"
end end
end end

View File

@ -68,7 +68,7 @@ function tcd.handle(event)
end end
end end
-- identify any overdo callbacks<br> -- identify any overdue callbacks<br>
-- prints to log debug output -- prints to log debug output
function tcd.diagnostics() function tcd.diagnostics()
for timer, entry in pairs(registry) do for timer, entry in pairs(registry) do

View File

@ -80,9 +80,9 @@ end
---@return string ---@return string
function util.strrep(str, n) function util.strrep(str, n)
local repeated = "" local repeated = ""
for _ = 1, n do
repeated = repeated .. str for _ = 1, n do repeated = repeated .. str end
end
return repeated return repeated
end end
@ -123,7 +123,9 @@ function util.strwrap(str, limit) return cc_strings.wrap(str, limit) end
---@diagnostic disable-next-line: unused-vararg ---@diagnostic disable-next-line: unused-vararg
function util.concat(...) function util.concat(...)
local str = "" local str = ""
for _, v in ipairs(arg) do str = str .. util.strval(v) end for _, v in ipairs(arg) do str = str .. util.strval(v) end
return str return str
end end
@ -322,7 +324,8 @@ end
--- EVENT_CONSUMER: this function consumes events --- EVENT_CONSUMER: this function consumes events
function util.nop() util.psleep(0.05) end 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)<br>
-- note: will not yield for time periods less than 50ms
---@nodiscard ---@nodiscard
---@param target_timing integer minimum amount of milliseconds to wait for ---@param target_timing integer minimum amount of milliseconds to wait for
---@param last_update integer millisecond time of last update ---@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 TFE(fe) return fe / 1000000000000.0 end
local function PFE(fe) return fe / 1000000000000000.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 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) -- format a power value into XXX.XX UNIT format (FE, kFE, MFE, GFE, TFE, PFE, EFE, ZFE)
---@nodiscard ---@nodiscard