Merge branch 'devel' into 193-pocket-main-application

This commit is contained in:
Mikayla Fischler
2023-04-12 18:06:24 -04:00
37 changed files with 183 additions and 113 deletions

28
.github/workflows/check.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: Lua Checks
on:
workflow_dispatch:
push:
branches:
- main
- latest
- devel
pull_request:
branches:
- main
- latest
- devel
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3.5.1
- name: Luacheck
uses: lunarmodules/luacheck@v1.1.0
with:
# -a = disable warning for unused arguments
# -i 121 = Setting a read-only global variable.
# -u 512 = Loop can be executed at most once.
# -i 542 = An empty if branch.
args: . --no-max-line-length -a -i 121 512 542 --exclude-files ./lockbox/* ./*/config.lua --globals _HOST term fs peripheral rs bit parallel colors textutils shell settings window read periphemu http os

47
.github/workflows/shields.yml vendored Normal file
View File

@ -0,0 +1,47 @@
# Simple workflow for deploying static content to GitHub Pages
name: Deploy Component Versions
on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Setup Python
uses: actions/setup-python@v3.1.3
- run: mkdir shields
- run: python imgen.py shields
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
# Upload shields JSON
path: '.'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2

View File

@ -13,7 +13,6 @@
"window", "window",
"read", "read",
"periphemu", "periphemu",
"mekanismEnergyHelper",
"_HOST", "_HOST",
"http" "http"
], ],

View File

@ -1,6 +1,12 @@
# cc-mek-scada # cc-mek-scada
Configurable ComputerCraft SCADA system for multi-reactor control of Mekanism fission reactors with a GUI, automatic safety features, waste processing control, and more! Configurable ComputerCraft SCADA system for multi-reactor control of Mekanism fission reactors with a GUI, automatic safety features, waste processing control, and more!
![GitHub](https://img.shields.io/github/license/MikaylaFischler/cc-mek-scada)
![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/MikaylaFischler/cc-mek-scada?include_prereleases)
![GitHub Workflow Status (with branch)](https://img.shields.io/github/actions/workflow/status/MikaylaFischler/cc-mek-scada/check.yml?branch=main&label=main)
![GitHub Workflow Status (with branch)](https://img.shields.io/github/actions/workflow/status/MikaylaFischler/cc-mek-scada/check.yml?branch=latest&label=latest)
![GitHub Workflow Status (with branch)](https://img.shields.io/github/actions/workflow/status/MikaylaFischler/cc-mek-scada/check.yml?branch=devel&label=devel)
Mod Requirements: Mod Requirements:
- CC: Tweaked - CC: Tweaked
- Mekanism v10.1+ - Mekanism v10.1+
@ -12,6 +18,25 @@ v10.1+ is required due the complete support of CC:Tweaked added in Mekanism v10.
There was also an apparent bug with boilers disconnecting and reconnecting when active in my test world on 10.0.24, so it may not even have been an option to fully implement this with support for 10.0. There was also an apparent bug with boilers disconnecting and reconnecting when active in my test world on 10.0.24, so it may not even have been an option to fully implement this with support for 10.0.
## Released Component Versions
### Core
![Bootloader](https://img.shields.io/endpoint?url=https%3A%2F%2Fmikaylafischler.github.io%2Fcc-mek-scada%2Fshields%2Fbootloader.json)
![Comms](https://img.shields.io/endpoint?url=https%3A%2F%2Fmikaylafischler.github.io%2Fcc-mek-scada%2Fshields%2Fcomms.json)
### Utilities
![Installer](https://img.shields.io/endpoint?url=https%3A%2F%2Fmikaylafischler.github.io%2Fcc-mek-scada%2Fshields%2Finstaller.json)
### Applications
![Reactor PLC](https://img.shields.io/endpoint?url=https%3A%2F%2Fmikaylafischler.github.io%2Fcc-mek-scada%2Fshields%2Freactor-plc.json)
![RTU](https://img.shields.io/endpoint?url=https%3A%2F%2Fmikaylafischler.github.io%2Fcc-mek-scada%2Fshields%2Frtu.json)
![Supervisor](https://img.shields.io/endpoint?url=https%3A%2F%2Fmikaylafischler.github.io%2Fcc-mek-scada%2Fshields%2Fsupervisor.json)
![Coordinator](https://img.shields.io/endpoint?url=https%3A%2F%2Fmikaylafischler.github.io%2Fcc-mek-scada%2Fshields%2Fcoordinator.json)
![Pocket](https://img.shields.io/endpoint?url=https%3A%2F%2Fmikaylafischler.github.io%2Fcc-mek-scada%2Fshields%2Fpocket.json)
## Installation ## Installation
You can install this on a ComputerCraft computer using either: You can install this on a ComputerCraft computer using either:

View File

@ -1,11 +1,13 @@
local apisessions = {} local apisessions = {}
---@param packet capi_frame ---@param packet capi_frame
---@diagnostic disable-next-line: unused-local
function apisessions.handle_packet(packet) function apisessions.handle_packet(packet)
end end
-- attempt to identify which session's watchdog timer fired -- attempt to identify which session's watchdog timer fired
---@param timer_event number ---@param timer_event number
---@diagnostic disable-next-line: unused-local
function apisessions.check_all_watchdogs(timer_event) function apisessions.check_all_watchdogs(timer_event)
end end

View File

@ -11,7 +11,6 @@ local dialog = require("coordinator.ui.dialog")
local print = util.print local print = util.print
local println = util.println local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts local println_ts = util.println_ts
local PROTOCOL = comms.PROTOCOL local PROTOCOL = comms.PROTOCOL
@ -246,7 +245,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
---@param msg table ---@param msg table
local function _send_sv(protocol, msg_type, msg) local function _send_sv(protocol, msg_type, msg)
local s_pkt = comms.scada_packet() local s_pkt = comms.scada_packet()
local pkt = nil ---@type mgmt_packet|crdn_packet local pkt ---@type mgmt_packet|crdn_packet
if protocol == PROTOCOL.SCADA_MGMT then if protocol == PROTOCOL.SCADA_MGMT then
pkt = comms.mgmt_packet() pkt = comms.mgmt_packet()

View File

@ -657,7 +657,7 @@ function iocontrol.update_unit_statuses(statuses)
if type(rtu_statuses.rad_mon) == "table" then if type(rtu_statuses.rad_mon) == "table" then
if #rtu_statuses.rad_mon > 0 then if #rtu_statuses.rad_mon > 0 then
local rad_mon = rtu_statuses.rad_mon[1] local rad_mon = rtu_statuses.rad_mon[1]
local rtu_faulted = rad_mon[1] ---@type boolean -- local rtu_faulted = rad_mon[1] ---@type boolean
unit.radiation = rad_mon[2] ---@type number unit.radiation = rad_mon[2] ---@type number
unit.unit_ps.publish("radiation", unit.radiation) unit.unit_ps.publish("radiation", unit.radiation)

View File

@ -12,10 +12,11 @@ local ALARM_STATE = types.ALARM_STATE
---@class sounder ---@class sounder
local sounder = {} local sounder = {}
-- note: max samples = 0x20000 (128 * 1024 samples)
local _2_PI = 2 * math.pi -- 2 whole pies, hope you're hungry local _2_PI = 2 * math.pi -- 2 whole pies, hope you're hungry
local _DRATE = 48000 -- 48kHz audio local _DRATE = 48000 -- 48kHz audio
local _MAX_VAL = 127 / 2 -- max signed integer in this 8-bit audio local _MAX_VAL = 127 / 2 -- max signed integer in this 8-bit audio
local _MAX_SAMPLES = 0x20000 -- 128 * 1024 samples
local _05s_SAMPLES = 24000 -- half a second worth of samples local _05s_SAMPLES = 24000 -- half a second worth of samples
local test_alarms = { false, false, false, false, false, false, false, false, false, false, false, false } local test_alarms = { false, false, false, false, false, false, false, false, false, false, false, false }

View File

@ -21,9 +21,7 @@ local sounder = require("coordinator.sounder")
local COORDINATOR_VERSION = "v0.12.6" local COORDINATOR_VERSION = "v0.12.6"
local print = util.print
local println = util.println local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts local println_ts = util.println_ts
local log_graphics = coordinator.log_graphics local log_graphics = coordinator.log_graphics
@ -287,7 +285,7 @@ local function main()
else else
log_sys("wired modem reconnected") log_sys("wired modem reconnected")
end end
elseif type == "monitor" then -- elseif type == "monitor" then
-- not supported, system will exit on loss of in-use monitors -- not supported, system will exit on loss of in-use monitors
elseif type == "speaker" then elseif type == "speaker" then
local msg = "alarm sounder speaker reconnected" local msg = "alarm sounder speaker reconnected"

View File

@ -18,9 +18,8 @@ local border = core.graphics.border
---@param root graphics_element parent ---@param root graphics_element parent
---@param x integer top left x ---@param x integer top left x
---@param y integer top left y ---@param y integer top left y
---@param data reactor_db reactor data
---@param ps psil ps interface ---@param ps psil ps interface
local function new_view(root, x, y, data, ps) local function new_view(root, x, y, ps)
local reactor = Rectangle{parent=root,border=border(1, colors.gray, true),width=30,height=7,x=x,y=y} local reactor = Rectangle{parent=root,border=border(1, colors.gray, true),width=30,height=7,x=x,y=y}
local text_fg_bg = cpair(colors.black, colors.lightGray) local text_fg_bg = cpair(colors.black, colors.lightGray)

View File

@ -24,19 +24,18 @@ local pipe = core.graphics.pipe
---@param y integer top left y ---@param y integer top left y
---@param unit ioctl_unit unit database entry ---@param unit ioctl_unit unit database entry
local function make(parent, x, y, unit) local function make(parent, x, y, unit)
local height = 0
local num_boilers = #unit.boiler_data_tbl local num_boilers = #unit.boiler_data_tbl
local num_turbines = #unit.turbine_data_tbl local num_turbines = #unit.turbine_data_tbl
assert(num_boilers >= 0 and num_boilers <= 2, "minimum 0 boilers, maximum 2 boilers") assert(num_boilers >= 0 and num_boilers <= 2, "minimum 0 boilers, maximum 2 boilers")
assert(num_turbines >= 1 and num_turbines <= 3, "minimum 1 turbine, maximum 3 turbines") assert(num_turbines >= 1 and num_turbines <= 3, "minimum 1 turbine, maximum 3 turbines")
local height = 25
if num_boilers == 0 and num_turbines == 1 then if num_boilers == 0 and num_turbines == 1 then
height = 9 height = 9
elseif num_boilers == 1 and num_turbines <= 2 then elseif num_boilers == 1 and num_turbines <= 2 then
height = 17 height = 17
else
height = 25
end end
assert(parent.height() >= (y + height), "main display not of sufficient vertical resolution (add an additional row of monitors)") assert(parent.height() >= (y + height), "main display not of sufficient vertical resolution (add an additional row of monitors)")
@ -51,7 +50,7 @@ local function make(parent, x, y, unit)
-- REACTOR -- -- REACTOR --
------------- -------------
reactor_view(root, 1, 3, unit.reactor_data, unit.unit_ps) reactor_view(root, 1, 3, unit.unit_ps)
if num_boilers > 0 then if num_boilers > 0 then
local coolant_pipes = {} local coolant_pipes = {}

View File

@ -5,7 +5,6 @@
local util = require("scada-common.util") local util = require("scada-common.util")
local iocontrol = require("coordinator.iocontrol") local iocontrol = require("coordinator.iocontrol")
local sounder = require("coordinator.sounder")
local style = require("coordinator.ui.style") local style = require("coordinator.ui.style")
@ -15,14 +14,9 @@ local unit_overview = require("coordinator.ui.components.unit_overview")
local core = require("graphics.core") local core = require("graphics.core")
local ColorMap = require("graphics.elements.colormap")
local DisplayBox = require("graphics.elements.displaybox") local DisplayBox = require("graphics.elements.displaybox")
local Div = require("graphics.elements.div")
local TextBox = require("graphics.elements.textbox") local TextBox = require("graphics.elements.textbox")
local PushButton = require("graphics.elements.controls.push_button")
local SwitchButton = require("graphics.elements.controls.switch_button")
local DataIndicator = require("graphics.elements.indicators.data") local DataIndicator = require("graphics.elements.indicators.data")
local TEXT_ALIGN = core.graphics.TEXT_ALIGN local TEXT_ALIGN = core.graphics.TEXT_ALIGN

View File

@ -30,8 +30,7 @@ local function spinbox(args)
assert(util.is_int(wn_prec), "graphics.element.controls.spinbox_numeric: whole number precision must be an integer") assert(util.is_int(wn_prec), "graphics.element.controls.spinbox_numeric: whole number precision must be an integer")
assert(util.is_int(fr_prec), "graphics.element.controls.spinbox_numeric: fractional precision must be an integer") assert(util.is_int(fr_prec), "graphics.element.controls.spinbox_numeric: fractional precision must be an integer")
local fmt = "" local fmt, fmt_init ---@type string, string
local fmt_init = ""
if fr_prec > 0 then if fr_prec > 0 then
fmt = "%" .. (wn_prec + fr_prec + 1) .. "." .. fr_prec .. "f" fmt = "%" .. (wn_prec + fr_prec + 1) .. "." .. fr_prec .. "f"

View File

@ -73,7 +73,7 @@ local function core_map(args)
local function draw_core(t) local function draw_core(t)
local i = 1 local i = 1
local back_c = "F" local back_c = "F"
local text_c = "8" local text_c ---@type string
-- determine fuel assembly coloring -- determine fuel assembly coloring
if t <= 300 then if t <= 300 then

View File

@ -1,5 +1,6 @@
import json import json
import os import os
import sys
# list files in a directory # list files in a directory
def list_files(path): def list_files(path):
@ -100,7 +101,30 @@ f.close()
manifest_size = os.path.getsize("install_manifest.json") manifest_size = os.path.getsize("install_manifest.json")
final_manifest = make_manifest(manifest_size)
# calculate file size then regenerate with embedded size # calculate file size then regenerate with embedded size
f = open("install_manifest.json", "w") f = open("install_manifest.json", "w")
json.dump(make_manifest(manifest_size), f) json.dump(final_manifest, f)
f.close() f.close()
if sys.argv[1] == "shields":
# write all the JSON files for shields.io
for key, version in final_manifest["versions"].items():
f = open("./shields/" + key + ".json", "w")
if version.find("alpha") >= 0:
color = "yellow"
elif version.find("beta") >= 0:
color = "orange"
else:
color = "blue"
json.dump({
"schemaVersion": 1,
"label": key,
"message": "" + version,
"color": color
}, f)
f.close()

File diff suppressed because one or more lines are too long

View File

@ -18,9 +18,9 @@ local renderer = require("pocket.renderer")
local POCKET_VERSION = "alpha-v0.1.0" local POCKET_VERSION = "alpha-v0.1.0"
local print = util.print -- local print = util.print
local println = util.println local println = util.println
local print_ts = util.print_ts -- local print_ts = util.print_ts
local println_ts = util.println_ts local println_ts = util.println_ts
---------------------------------------- ----------------------------------------

View File

@ -68,11 +68,6 @@ function plc.rps_init(reactor, is_formed, emer_cool)
end end
end end
-- clear reactor access fault flag
local function _clear_fault()
self.state[state_keys.fault] = false
end
-- set emergency coolant control (if configured) -- set emergency coolant control (if configured)
---@param state boolean true to enable emergency coolant, false to disable ---@param state boolean true to enable emergency coolant, false to disable
local function _set_emer_cool(state) local function _set_emer_cool(state)
@ -779,7 +774,6 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
---@param setpoints setpoints setpoint control table ---@param setpoints setpoints setpoint control table
function public.handle_packet(packet, plc_state, setpoints) function public.handle_packet(packet, plc_state, setpoints)
-- print a log message to the terminal as long as the UI isn't running -- print a log message to the terminal as long as the UI isn't running
local function println(message) if not plc_state.fp_ok then util.println(message) end end
local function println_ts(message) if not plc_state.fp_ok then util.println_ts(message) end end local function println_ts(message) if not plc_state.fp_ok then util.println_ts(message) end end
-- handle packets now that we have prints setup -- handle packets now that we have prints setup

View File

@ -20,9 +20,7 @@ local threads = require("reactor-plc.threads")
local R_PLC_VERSION = "v1.1.5" local R_PLC_VERSION = "v1.1.5"
local print = util.print
local println = util.println local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts local println_ts = util.println_ts
---------------------------------------- ----------------------------------------
@ -176,8 +174,9 @@ local function main()
-- front panel time! -- front panel time!
if not renderer.ui_ready() then if not renderer.ui_ready() then
local message = nil local message
plc_state.fp_ok, message = pcall(renderer.start_ui) plc_state.fp_ok, message = pcall(renderer.start_ui)
if not plc_state.fp_ok then if not plc_state.fp_ok then
renderer.close_ui() renderer.close_ui()
println_ts(util.c("UI error: ", message)) println_ts(util.c("UI error: ", message))

View File

@ -34,7 +34,6 @@ local MQ__COMM_CMD = {
---@param init function ---@param init function
function threads.thread__main(smem, init) function threads.thread__main(smem, init)
-- print a log message to the terminal as long as the UI isn't running -- print a log message to the terminal as long as the UI isn't running
local function println(message) if not smem.plc_state.fp_ok then util.println(message) end end
local function println_ts(message) if not smem.plc_state.fp_ok then util.println_ts(message) end end local function println_ts(message) if not smem.plc_state.fp_ok then util.println_ts(message) end end
---@class parallel_thread ---@class parallel_thread
@ -307,7 +306,6 @@ end
---@param smem plc_shared_memory ---@param smem plc_shared_memory
function threads.thread__rps(smem) function threads.thread__rps(smem)
-- print a log message to the terminal as long as the UI isn't running -- print a log message to the terminal as long as the UI isn't running
local function println(message) if not smem.plc_state.fp_ok then util.println(message) end end
local function println_ts(message) if not smem.plc_state.fp_ok then util.println_ts(message) end end local function println_ts(message) if not smem.plc_state.fp_ok then util.println_ts(message) end end
---@class parallel_thread ---@class parallel_thread
@ -682,7 +680,7 @@ function threads.thread__setpoint_control(smem)
-- we yielded, check enable again -- we yielded, check enable again
if setpoints.burn_rate_en and (type(current_burn_rate) == "number") and (current_burn_rate ~= setpoints.burn_rate) then if setpoints.burn_rate_en and (type(current_burn_rate) == "number") and (current_burn_rate ~= setpoints.burn_rate) then
-- calculate new burn rate -- calculate new burn rate
local new_burn_rate = current_burn_rate local new_burn_rate ---@type number
if setpoints.burn_rate > current_burn_rate then if setpoints.burn_rate > current_burn_rate then
-- need to ramp up -- need to ramp up

View File

@ -34,7 +34,7 @@ function redstone_rtu.new()
---@param side string ---@param side string
---@param color integer ---@param color integer
function public.link_di(side, color) function public.link_di(side, color)
local f_read = nil local f_read ---@type function
if color then if color then
f_read = function () f_read = function ()
@ -53,8 +53,8 @@ function redstone_rtu.new()
---@param side string ---@param side string
---@param color integer ---@param color integer
function public.link_do(side, color) function public.link_do(side, color)
local f_read = nil local f_read ---@type function
local f_write = nil local f_write ---@type function
if color then if color then
f_read = function () f_read = function ()

View File

@ -347,11 +347,9 @@ function modbus.new(rtu_dev, use_parallel_read)
response = { MODBUS_EXCODE.NEG_ACKNOWLEDGE } response = { MODBUS_EXCODE.NEG_ACKNOWLEDGE }
end end
-- default is to echo back -- default is to echo back<br>
local func_code = packet.func_code -- but here we echo back with error flag, on success the "error" will be acknowledgement
local func_code = bit.bor(packet.func_code, MODBUS_FCODE.ERROR_FLAG)
-- echo back with error flag, on success the "error" will be acknowledgement
func_code = bit.bor(packet.func_code, MODBUS_FCODE.ERROR_FLAG)
-- create reply -- create reply
local reply = comms.modbus_packet() local reply = comms.modbus_packet()
@ -365,8 +363,8 @@ function modbus.new(rtu_dev, use_parallel_read)
---@param packet modbus_frame ---@param packet modbus_frame
---@return boolean return_code, modbus_packet reply ---@return boolean return_code, modbus_packet reply
function public.handle_packet(packet) function public.handle_packet(packet)
local return_code = true local return_code ---@type boolean
local response = nil local response ---@type table|MODBUS_EXCODE
if packet.length >= 2 then if packet.length >= 2 then
-- handle by function code -- handle by function code

View File

@ -14,9 +14,6 @@ local ESTABLISH_ACK = comms.ESTABLISH_ACK
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
local print = util.print
local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts local println_ts = util.println_ts
-- create a new RTU unit -- create a new RTU unit
@ -347,8 +344,8 @@ function rtu.comms(version, modem, local_port, server_port, range, conn_watchdog
if protocol == PROTOCOL.MODBUS_TCP then if protocol == PROTOCOL.MODBUS_TCP then
---@cast packet modbus_frame ---@cast packet modbus_frame
if rtu_state.linked then if rtu_state.linked then
local return_code = false local return_code ---@type boolean
local reply = modbus.reply__neg_ack(packet) local reply ---@type modbus_packet
-- handle MODBUS instruction -- handle MODBUS instruction
if packet.unit_id <= #units then if packet.unit_id <= #units then

View File

@ -25,13 +25,11 @@ local sna_rtu = require("rtu.dev.sna_rtu")
local sps_rtu = require("rtu.dev.sps_rtu") local sps_rtu = require("rtu.dev.sps_rtu")
local turbinev_rtu = require("rtu.dev.turbinev_rtu") local turbinev_rtu = require("rtu.dev.turbinev_rtu")
local RTU_VERSION = "v0.13.2" local RTU_VERSION = "v0.13.3"
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
local print = util.print
local println = util.println local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts local println_ts = util.println_ts
---------------------------------------- ----------------------------------------
@ -287,9 +285,9 @@ local function main()
local device = ppm.get_periph(name) local device = ppm.get_periph(name)
local type = nil ---@type string|nil local type ---@type string|nil
local rtu_iface = nil ---@type rtu_device local rtu_iface ---@type rtu_device
local rtu_type = nil ---@type RTU_UNIT_TYPE local rtu_type ---@type RTU_UNIT_TYPE
local is_multiblock = false ---@type boolean local is_multiblock = false ---@type boolean
local formed = nil ---@type boolean|nil local formed = nil ---@type boolean|nil
local faulted = nil ---@type boolean|nil local faulted = nil ---@type boolean|nil
@ -356,11 +354,11 @@ local function main()
elseif type == "solarNeutronActivator" then elseif type == "solarNeutronActivator" then
-- SNA -- SNA
rtu_type = RTU_UNIT_TYPE.SNA rtu_type = RTU_UNIT_TYPE.SNA
rtu_iface, _ = sna_rtu.new(device) rtu_iface, faulted = sna_rtu.new(device)
elseif type == "environmentDetector" then elseif type == "environmentDetector" then
-- advanced peripherals environment detector -- advanced peripherals environment detector
rtu_type = RTU_UNIT_TYPE.ENV_DETECTOR rtu_type = RTU_UNIT_TYPE.ENV_DETECTOR
rtu_iface, _ = envd_rtu.new(device) rtu_iface, faulted = envd_rtu.new(device)
elseif type == ppm.VIRTUAL_DEVICE_TYPE then elseif type == ppm.VIRTUAL_DEVICE_TYPE then
-- placeholder device -- placeholder device
rtu_type = RTU_UNIT_TYPE.VIRTUAL rtu_type = RTU_UNIT_TYPE.VIRTUAL

View File

@ -17,9 +17,6 @@ local threads = {}
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
local print = util.print
local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts local println_ts = util.println_ts
local MAIN_CLOCK = 2 -- (2Hz, 40 ticks) local MAIN_CLOCK = 2 -- (2Hz, 40 ticks)

View File

@ -5,7 +5,6 @@
local aes128 = require("lockbox.cipher.aes128") local aes128 = require("lockbox.cipher.aes128")
local ctr_mode = require("lockbox.cipher.mode.ctr") local ctr_mode = require("lockbox.cipher.mode.ctr")
local sha1 = require("lockbox.digest.sha1") local sha1 = require("lockbox.digest.sha1")
local sha2_224 = require("lockbox.digest.sha2_224")
local sha2_256 = require("lockbox.digest.sha2_256") local sha2_256 = 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")
@ -157,10 +156,6 @@ end
-- wrap a modem as a secure modem to send encrypted traffic -- wrap a modem as a secure modem to send encrypted traffic
---@param modem table modem to wrap ---@param modem table modem to wrap
function crypto.secure_modem(modem) function crypto.secure_modem(modem)
local self = {
modem = modem
}
---@class secure_modem ---@class secure_modem
---@field open function ---@field open function
---@field isOpen function ---@field isOpen function
@ -177,17 +172,17 @@ function crypto.secure_modem(modem)
local public = {} local public = {}
-- wrap a modem -- wrap a modem
---@param modem table ---@param reconnected_modem table
---@diagnostic disable-next-line: redefined-local ---@diagnostic disable-next-line: redefined-local
function public.wrap(modem) function public.wrap(reconnected_modem)
self.modem = modem modem = reconnected_modem
for key, func in pairs(self.modem) do for key, func in pairs(modem) do
public[key] = func public[key] = func
end end
end end
-- wrap modem functions, then we replace transmit -- wrap modem functions, then we replace transmit
public.wrap(self.modem) public.wrap(modem)
-- send a packet with encryption -- send a packet with encryption
---@param channel integer ---@param channel integer
@ -198,9 +193,9 @@ function crypto.secure_modem(modem)
local iv, ciphertext = crypto.encrypt(plaintext) local iv, ciphertext = crypto.encrypt(plaintext)
---@diagnostic disable-next-line: redefined-local ---@diagnostic disable-next-line: redefined-local
local hmac = crypto.hmac(iv .. ciphertext) local computed_hmac = crypto.hmac(iv .. ciphertext)
self.modem.transmit(channel, reply_channel, { hmac, iv, ciphertext }) modem.transmit(channel, reply_channel, { computed_hmac, iv, ciphertext })
end end
-- parse in a modem message as a network packet -- parse in a modem message as a network packet
@ -217,13 +212,13 @@ function crypto.secure_modem(modem)
if type(message) == "table" then if type(message) == "table" then
if #message == 3 then if #message == 3 then
---@diagnostic disable-next-line: redefined-local ---@diagnostic disable-next-line: redefined-local
local hmac = message[1] local rx_hmac = message[1]
local iv = message[2] local iv = message[2]
local ciphertext = message[3] local ciphertext = message[3]
local computed_hmac = crypto.hmac(iv .. ciphertext) local computed_hmac = crypto.hmac(iv .. ciphertext)
if hmac == computed_hmac then if rx_hmac == computed_hmac then
-- message intact -- message intact
local plaintext = crypto.decrypt(iv, ciphertext) local plaintext = crypto.decrypt(iv, ciphertext)
body = textutils.unserialize(plaintext) body = textutils.unserialize(plaintext)

View File

@ -7,7 +7,7 @@ local println_ts = util.println_ts
println("SCADA BOOTLOADER V" .. BOOTLOADER_VERSION) println("SCADA BOOTLOADER V" .. BOOTLOADER_VERSION)
local exit_code = false local exit_code ---@type boolean
println_ts("BOOT> SCANNING FOR APPLICATIONS...") println_ts("BOOT> SCANNING FOR APPLICATIONS...")

View File

@ -16,16 +16,12 @@ local FAC_COMMAND = comms.FAC_COMMAND
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
local SV_Q_CMDS = svqtypes.SV_Q_CMDS
local SV_Q_DATA = svqtypes.SV_Q_DATA local SV_Q_DATA = svqtypes.SV_Q_DATA
local print = util.print
local println = util.println local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts
-- retry time constants in ms -- retry time constants in ms
local INITIAL_WAIT = 1500 -- local INITIAL_WAIT = 1500
local RETRY_PERIOD = 1000 local RETRY_PERIOD = 1000
local PARTIAL_RETRY_PERIOD = 2000 local PARTIAL_RETRY_PERIOD = 2000
@ -198,7 +194,7 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
-- keep alive reply -- keep alive reply
if pkt.length == 2 then if pkt.length == 2 then
local srv_start = pkt.data[1] local srv_start = pkt.data[1]
local coord_send = pkt.data[2] -- local coord_send = pkt.data[2]
local srv_now = util.time() local srv_now = util.time()
self.last_rtt = srv_now - srv_start self.last_rtt = srv_now - srv_start

View File

@ -14,10 +14,7 @@ local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
local PLC_AUTO_ACK = comms.PLC_AUTO_ACK local PLC_AUTO_ACK = comms.PLC_AUTO_ACK
local UNIT_COMMAND = comms.UNIT_COMMAND local UNIT_COMMAND = comms.UNIT_COMMAND
local print = util.print
local println = util.println local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts
-- retry time constants in ms -- retry time constants in ms
local INITIAL_WAIT = 1500 local INITIAL_WAIT = 1500
@ -476,7 +473,7 @@ function plc.new_session(id, reactor_id, in_queue, out_queue, timeout)
-- keep alive reply -- keep alive reply
if pkt.length == 2 then if pkt.length == 2 then
local srv_start = pkt.data[1] local srv_start = pkt.data[1]
local plc_send = pkt.data[2] -- local plc_send = pkt.data[2]
local srv_now = util.time() local srv_now = util.time()
self.last_rtt = srv_now - srv_start self.last_rtt = srv_now - srv_start

View File

@ -22,10 +22,7 @@ local PROTOCOL = comms.PROTOCOL
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
local print = util.print
local println = util.println local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts
local PERIODICS = { local PERIODICS = {
KEEP_ALIVE = 2000 KEEP_ALIVE = 2000
@ -79,8 +76,6 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
for i = 1, #self.advert do for i = 1, #self.advert do
local unit = nil ---@type unit_session|nil local unit = nil ---@type unit_session|nil
local rs_in_q = nil ---@type mqueue|nil
local tbv_in_q = nil ---@type mqueue|nil
---@type rtu_advertisement ---@type rtu_advertisement
local unit_advert = { local unit_advert = {
@ -242,7 +237,7 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
-- keep alive reply -- keep alive reply
if pkt.length == 2 then if pkt.length == 2 then
local srv_start = pkt.data[1] local srv_start = pkt.data[1]
local rtu_send = pkt.data[2] -- local rtu_send = pkt.data[2]
local srv_now = util.time() local srv_now = util.time()
self.last_rtt = srv_now - srv_start self.last_rtt = srv_now - srv_start

View File

@ -12,7 +12,6 @@ local MODBUS_FCODE = types.MODBUS_FCODE
local IO_PORT = rsio.IO local IO_PORT = rsio.IO
local IO_LVL = rsio.IO_LVL local IO_LVL = rsio.IO_LVL
local IO_DIR = rsio.IO_DIR
local IO_MODE = rsio.IO_MODE local IO_MODE = rsio.IO_MODE
local TXN_READY = -1 local TXN_READY = -1

View File

@ -13,12 +13,10 @@ local rtu = require("supervisor.session.rtu")
-- Supervisor Sessions Handler -- Supervisor Sessions Handler
local SV_Q_CMDS = svqtypes.SV_Q_CMDS
local SV_Q_DATA = svqtypes.SV_Q_DATA local SV_Q_DATA = svqtypes.SV_Q_DATA
local PLC_S_CMDS = plc.PLC_S_CMDS local PLC_S_CMDS = plc.PLC_S_CMDS
local PLC_S_DATA = plc.PLC_S_DATA local PLC_S_DATA = plc.PLC_S_DATA
local CRD_S_CMDS = coordinator.CRD_S_CMDS
local CRD_S_DATA = coordinator.CRD_S_DATA local CRD_S_DATA = coordinator.CRD_S_DATA
local svsessions = {} local svsessions = {}

View File

@ -14,11 +14,9 @@ local svsessions = require("supervisor.session.svsessions")
local config = require("supervisor.config") local config = require("supervisor.config")
local supervisor = require("supervisor.supervisor") local supervisor = require("supervisor.supervisor")
local SUPERVISOR_VERSION = "v0.14.3" local SUPERVISOR_VERSION = "v0.14.4"
local print = util.print
local println = util.println local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts local println_ts = util.println_ts
---------------------------------------- ----------------------------------------

View File

@ -11,10 +11,7 @@ local DEVICE_TYPE = comms.DEVICE_TYPE
local ESTABLISH_ACK = comms.ESTABLISH_ACK local ESTABLISH_ACK = comms.ESTABLISH_ACK
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
local print = util.print
local println = util.println local println = util.println
local print_ts = util.print_ts
local println_ts = util.println_ts
-- supervisory controller communications -- supervisory controller communications
---@nodiscard ---@nodiscard

View File

@ -4,14 +4,14 @@ local pbkdf2 = require("lockbox.kdf.pbkdf2")
local AES128Cipher = require("lockbox.cipher.aes128") local AES128Cipher = require("lockbox.cipher.aes128")
local HMAC = require("lockbox.mac.hmac") local HMAC = require("lockbox.mac.hmac")
local SHA1 = require("lockbox.digest.sha1") local SHA1 = require("lockbox.digest.sha1")
local SHA2_224 = require("lockbox.digest.sha2_224") -- local SHA2_224 = require("lockbox.digest.sha2_224")
local SHA2_256 = require("lockbox.digest.sha2_256") local SHA2_256 = require("lockbox.digest.sha2_256")
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 CBCMode = require("lockbox.cipher.mode.cbc") -- local CBCMode = require("lockbox.cipher.mode.cbc")
local CFBMode = require("lockbox.cipher.mode.cfb") -- local CFBMode = require("lockbox.cipher.mode.cfb")
local OFBMode = require("lockbox.cipher.mode.ofb") -- local OFBMode = require("lockbox.cipher.mode.ofb")
local CTRMode = require("lockbox.cipher.mode.ctr") local CTRMode = require("lockbox.cipher.mode.ctr")
local ZeroPadding = require("lockbox.padding.zero") local ZeroPadding = require("lockbox.padding.zero")
@ -35,6 +35,7 @@ util.println("pbkdf2: took " .. (util.time() - start) .. "ms")
util.println(keyd.asHex()) util.println(keyd.asHex())
local pkt = comms.modbus_packet() local pkt = comms.modbus_packet()
---@diagnostic disable-next-line: param-type-mismatch
pkt.make(1, 2, 7, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) pkt.make(1, 2, 7, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
local spkt = comms.scada_packet() local spkt = comms.scada_packet()
spkt.make(1, 1, pkt.raw_sendable()) spkt.make(1, 1, pkt.raw_sendable())

View File

@ -10,7 +10,6 @@ local println = util.println
local IO = rsio.IO local IO = rsio.IO
local IO_LVL = rsio.IO_LVL local IO_LVL = rsio.IO_LVL
local IO_DIR = rsio.IO_DIR
local IO_MODE = rsio.IO_MODE local IO_MODE = rsio.IO_MODE
println("starting RSIO tester") println("starting RSIO tester")