Merge pull request #302 from MikaylaFischler/common-cleanup

Common Cleanup
This commit is contained in:
Mikayla
2023-07-30 21:38:18 -04:00
committed by GitHub
13 changed files with 97 additions and 120 deletions

View File

@ -20,7 +20,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local function println(message) print(tostring(message)) end local function println(message) print(tostring(message)) end
local function print(message) term.write(tostring(message)) end local function print(message) term.write(tostring(message)) end
local CCMSI_VERSION = "v1.7d" local CCMSI_VERSION = "v1.8"
local install_dir = "/.install-cache" local install_dir = "/.install-cache"
local manifest_path = "https://mikaylafischler.github.io/cc-mek-scada/manifests/" local manifest_path = "https://mikaylafischler.github.io/cc-mek-scada/manifests/"
@ -63,16 +63,15 @@ end
local function pkg_message(message, package) white();print(message .. " ");blue();println(package);white() end local function pkg_message(message, package) white();print(message .. " ");blue();println(package);white() end
-- indicate actions to be taken based on package differences for installs/updates -- indicate actions to be taken based on package differences for installs/updates
local function show_pkg_change(name, v_local, v_remote) local function show_pkg_change(name, v)
if v_local ~= nil then if v.v_local ~= nil then
if v_local ~= v_remote then if v.v_local ~= v.v_remote then
print("[" .. name .. "] updating ");blue();print(v_local);white();print(" \xbb ");blue();println(v_remote);white() print("[" .. name .. "] updating ");blue();print(v.v_local);white();print(" \xbb ");blue();println(v.v_remote);white()
elseif mode == "install" then elseif mode == "install" then
pkg_message("[" .. name .. "] reinstalling", v_local) pkg_message("[" .. name .. "] reinstalling", v.v_local)
end end
else else pkg_message("[" .. name .. "] new install of", v.v_remote) end
pkg_message("[" .. name .. "] new install of", v_remote) return v.v_local ~= v.v_remote
end
end end
-- read the local manifest file -- read the local manifest file
@ -284,6 +283,7 @@ elseif mode == "install" or mode == "update" then
app = { v_local = nil, v_remote = nil, changed = false }, app = { v_local = nil, v_remote = nil, changed = false },
boot = { v_local = nil, v_remote = nil, changed = false }, boot = { v_local = nil, v_remote = nil, changed = false },
comms = { v_local = nil, v_remote = nil, changed = false }, comms = { v_local = nil, v_remote = nil, changed = false },
common = { v_local = nil, v_remote = nil, changed = false },
graphics = { v_local = nil, v_remote = nil, changed = false }, graphics = { v_local = nil, v_remote = nil, changed = false },
lockbox = { v_local = nil, v_remote = nil, changed = false } lockbox = { v_local = nil, v_remote = nil, changed = false }
} }
@ -299,6 +299,7 @@ elseif mode == "install" or mode == "update" then
ver.boot.v_local = local_manifest.versions.bootloader ver.boot.v_local = local_manifest.versions.bootloader
ver.app.v_local = local_manifest.versions[app] ver.app.v_local = local_manifest.versions[app]
ver.comms.v_local = local_manifest.versions.comms ver.comms.v_local = local_manifest.versions.comms
ver.common.v_local = local_manifest.versions.common
ver.graphics.v_local = local_manifest.versions.graphics ver.graphics.v_local = local_manifest.versions.graphics
ver.lockbox.v_local = local_manifest.versions.lockbox ver.lockbox.v_local = local_manifest.versions.lockbox
@ -316,6 +317,7 @@ elseif mode == "install" or mode == "update" then
ver.boot.v_remote = manifest.versions.bootloader ver.boot.v_remote = manifest.versions.bootloader
ver.app.v_remote = manifest.versions[app] ver.app.v_remote = manifest.versions[app]
ver.comms.v_remote = manifest.versions.comms ver.comms.v_remote = manifest.versions.comms
ver.common.v_remote = manifest.versions.common
ver.graphics.v_remote = manifest.versions.graphics ver.graphics.v_remote = manifest.versions.graphics
ver.lockbox.v_remote = manifest.versions.lockbox ver.lockbox.v_remote = manifest.versions.lockbox
@ -327,28 +329,15 @@ elseif mode == "install" or mode == "update" then
end end
white() white()
-- display bootloader version change information ver.boot.changed = show_pkg_change("bootldr", ver.boot)
show_pkg_change("bootldr", ver.boot.v_local, ver.boot.v_remote) ver.common.changed = show_pkg_change("common", ver.common)
ver.boot.changed = ver.boot.v_local ~= ver.boot.v_remote ver.comms.changed = show_pkg_change("comms", ver.comms)
-- display app version change information
show_pkg_change(app, ver.app.v_local, ver.app.v_remote)
ver.app.changed = ver.app.v_local ~= ver.app.v_remote
-- display comms version change information
show_pkg_change("comms", ver.comms.v_local, ver.comms.v_remote)
ver.comms.changed = ver.comms.v_local ~= ver.comms.v_remote
if ver.comms.changed and ver.comms.v_local ~= nil then if ver.comms.changed and ver.comms.v_local ~= nil then
print("[comms] ");yellow();println("other devices on the network will require an update");white() print("[comms] ");yellow();println("other devices on the network will require an update");white()
end end
ver.app.changed = show_pkg_change(app, ver.app)
-- display graphics version change information ver.graphics.changed = show_pkg_change("graphics", ver.graphics)
show_pkg_change("graphics", ver.graphics.v_local, ver.graphics.v_remote) ver.lockbox.changed = show_pkg_change("lockbox", ver.lockbox)
ver.graphics.changed = ver.graphics.v_local ~= ver.graphics.v_remote
-- display lockbox version change information
show_pkg_change("lockbox", ver.lockbox.v_local, ver.lockbox.v_remote)
ver.lockbox.changed = ver.lockbox.v_local ~= ver.lockbox.v_remote
-- ask for confirmation -- ask for confirmation
if not ask_y_n("Continue", false) then return end if not ask_y_n("Continue", false) then return end
@ -392,16 +381,13 @@ elseif mode == "install" or mode == "update" then
if dependency == "system" then return not ver.boot.changed if dependency == "system" then return not ver.boot.changed
elseif dependency == "graphics" then return not ver.graphics.changed elseif dependency == "graphics" then return not ver.graphics.changed
elseif dependency == "lockbox" then return not ver.lockbox.changed elseif dependency == "lockbox" then return not ver.lockbox.changed
elseif dependency == "common" then return not (ver.app.changed or ver.comms.changed) elseif dependency == "common" then return not (ver.common.changed or ver.comms.changed)
elseif dependency == app then return not ver.app.changed elseif dependency == app then return not ver.app.changed
else return true end else return true end
end end
if not single_file_mode then if not single_file_mode then
if fs.exists(install_dir) then if fs.exists(install_dir) then fs.delete(install_dir);fs.makeDir(install_dir) end
fs.delete(install_dir)
fs.makeDir(install_dir)
end
-- download all dependencies -- download all dependencies
for _, dependency in pairs(dependencies) do for _, dependency in pairs(dependencies) do

View File

@ -48,6 +48,7 @@ def make_manifest(size):
"versions" : { "versions" : {
"installer" : get_version("./ccmsi.lua"), "installer" : get_version("./ccmsi.lua"),
"bootloader" : get_version("./startup.lua"), "bootloader" : get_version("./startup.lua"),
"common" : get_version("./scada-common/util.lua", True),
"comms" : get_version("./scada-common/comms.lua", True), "comms" : get_version("./scada-common/comms.lua", True),
"graphics" : get_version("./graphics/core.lua", True), "graphics" : get_version("./graphics/core.lua", True),
"lockbox" : get_version("./lockbox/init.lua", True), "lockbox" : get_version("./lockbox/init.lua", True),

File diff suppressed because one or more lines are too long

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

@ -7,6 +7,9 @@ local cc_strings = require("cc.strings")
---@class util ---@class util
local util = {} local util = {}
-- scada-common version
util.version = "1.0.0"
-- ENVIRONMENT CONSTANTS -- -- ENVIRONMENT CONSTANTS --
util.TICK_TIME_S = 0.05 util.TICK_TIME_S = 0.05
@ -80,9 +83,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 +126,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 +327,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 +405,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