mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
#118 cleanup started of scada-common
This commit is contained in:
parent
e2d2a0f1dc
commit
34cac6a8b8
@ -173,7 +173,6 @@ local function main()
|
|||||||
log.debug("init> running without networking")
|
log.debug("init> running without networking")
|
||||||
end
|
end
|
||||||
|
|
||||||
---@diagnostic disable-next-line: param-type-mismatch
|
|
||||||
util.push_event("clock_start")
|
util.push_event("clock_start")
|
||||||
|
|
||||||
println("boot> completed")
|
println("boot> completed")
|
||||||
|
@ -266,7 +266,6 @@ function threads.thread__main(smem, init)
|
|||||||
-- this thread cannot be slept because it will miss events (namely "terminate" otherwise)
|
-- this thread cannot be slept because it will miss events (namely "terminate" otherwise)
|
||||||
if not plc_state.shutdown then
|
if not plc_state.shutdown then
|
||||||
log.info("main thread restarting now...")
|
log.info("main thread restarting now...")
|
||||||
---@diagnostic disable-next-line: param-type-mismatch
|
|
||||||
util.push_event("clock_start")
|
util.push_event("clock_start")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -16,7 +16,7 @@ local max_distance = nil
|
|||||||
|
|
||||||
comms.version = "1.4.0"
|
comms.version = "1.4.0"
|
||||||
|
|
||||||
---@alias PROTOCOLS integer
|
---@enum PROTOCOLS
|
||||||
local PROTOCOLS = {
|
local PROTOCOLS = {
|
||||||
MODBUS_TCP = 0, -- our "MODBUS TCP"-esque protocol
|
MODBUS_TCP = 0, -- our "MODBUS TCP"-esque protocol
|
||||||
RPLC = 1, -- reactor PLC protocol
|
RPLC = 1, -- reactor PLC protocol
|
||||||
@ -25,7 +25,7 @@ local PROTOCOLS = {
|
|||||||
COORD_API = 4 -- data/control packets for pocket computers to/from coordinators
|
COORD_API = 4 -- data/control packets for pocket computers to/from coordinators
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias RPLC_TYPES integer
|
---@enum RPLC_TYPES
|
||||||
local RPLC_TYPES = {
|
local RPLC_TYPES = {
|
||||||
STATUS = 0, -- reactor/system status
|
STATUS = 0, -- reactor/system status
|
||||||
MEK_STRUCT = 1, -- mekanism build structure
|
MEK_STRUCT = 1, -- mekanism build structure
|
||||||
@ -40,7 +40,7 @@ local RPLC_TYPES = {
|
|||||||
AUTO_BURN_RATE = 10 -- set an automatic burn rate, PLC will respond with status, enable toggle speed limited
|
AUTO_BURN_RATE = 10 -- set an automatic burn rate, PLC will respond with status, enable toggle speed limited
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias SCADA_MGMT_TYPES integer
|
---@enum SCADA_MGMT_TYPES
|
||||||
local SCADA_MGMT_TYPES = {
|
local SCADA_MGMT_TYPES = {
|
||||||
ESTABLISH = 0, -- establish new connection
|
ESTABLISH = 0, -- establish new connection
|
||||||
KEEP_ALIVE = 1, -- keep alive packet w/ RTT
|
KEEP_ALIVE = 1, -- keep alive packet w/ RTT
|
||||||
@ -49,7 +49,7 @@ local SCADA_MGMT_TYPES = {
|
|||||||
RTU_DEV_REMOUNT = 4 -- RTU multiblock possbily changed (formed, unformed) due to PPM remount
|
RTU_DEV_REMOUNT = 4 -- RTU multiblock possbily changed (formed, unformed) due to PPM remount
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias SCADA_CRDN_TYPES integer
|
---@enum SCADA_CRDN_TYPES
|
||||||
local SCADA_CRDN_TYPES = {
|
local SCADA_CRDN_TYPES = {
|
||||||
INITIAL_BUILDS = 0, -- initial, complete builds packet to the coordinator
|
INITIAL_BUILDS = 0, -- initial, complete builds packet to the coordinator
|
||||||
FAC_BUILDS = 1, -- facility RTU builds
|
FAC_BUILDS = 1, -- facility RTU builds
|
||||||
@ -60,12 +60,11 @@ local SCADA_CRDN_TYPES = {
|
|||||||
UNIT_CMD = 6 -- command a reactor unit
|
UNIT_CMD = 6 -- command a reactor unit
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias CAPI_TYPES integer
|
---@enum CAPI_TYPES
|
||||||
local CAPI_TYPES = {
|
local CAPI_TYPES = {
|
||||||
ESTABLISH = 0 -- initial greeting
|
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias ESTABLISH_ACK integer
|
---@enum ESTABLISH_ACK
|
||||||
local ESTABLISH_ACK = {
|
local ESTABLISH_ACK = {
|
||||||
ALLOW = 0, -- link approved
|
ALLOW = 0, -- link approved
|
||||||
DENY = 1, -- link denied
|
DENY = 1, -- link denied
|
||||||
@ -73,7 +72,7 @@ local ESTABLISH_ACK = {
|
|||||||
BAD_VERSION = 3 -- link denied due to comms version mismatch
|
BAD_VERSION = 3 -- link denied due to comms version mismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias DEVICE_TYPES integer
|
---@enum DEVICE_TYPES
|
||||||
local DEVICE_TYPES = {
|
local DEVICE_TYPES = {
|
||||||
PLC = 0, -- PLC device type for establish
|
PLC = 0, -- PLC device type for establish
|
||||||
RTU = 1, -- RTU device type for establish
|
RTU = 1, -- RTU device type for establish
|
||||||
@ -81,7 +80,7 @@ local DEVICE_TYPES = {
|
|||||||
CRDN = 3 -- coordinator device type for establish
|
CRDN = 3 -- coordinator device type for establish
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias RTU_UNIT_TYPES integer
|
---@enum RTU_UNIT_TYPES
|
||||||
local RTU_UNIT_TYPES = {
|
local RTU_UNIT_TYPES = {
|
||||||
REDSTONE = 0, -- redstone I/O
|
REDSTONE = 0, -- redstone I/O
|
||||||
BOILER_VALVE = 1, -- boiler mekanism 10.1+
|
BOILER_VALVE = 1, -- boiler mekanism 10.1+
|
||||||
@ -92,7 +91,7 @@ local RTU_UNIT_TYPES = {
|
|||||||
ENV_DETECTOR = 6 -- environment detector
|
ENV_DETECTOR = 6 -- environment detector
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias PLC_AUTO_ACK integer
|
---@enum PLC_AUTO_ACK
|
||||||
local PLC_AUTO_ACK = {
|
local PLC_AUTO_ACK = {
|
||||||
FAIL = 0, -- failed to set burn rate/burn rate invalid
|
FAIL = 0, -- failed to set burn rate/burn rate invalid
|
||||||
DIRECT_SET_OK = 1, -- successfully set burn rate
|
DIRECT_SET_OK = 1, -- successfully set burn rate
|
||||||
@ -100,7 +99,7 @@ local PLC_AUTO_ACK = {
|
|||||||
ZERO_DIS_OK = 3 -- successfully disabled reactor with < 0.01 burn rate
|
ZERO_DIS_OK = 3 -- successfully disabled reactor with < 0.01 burn rate
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias FAC_COMMANDS integer
|
---@enum FAC_COMMANDS
|
||||||
local FAC_COMMANDS = {
|
local FAC_COMMANDS = {
|
||||||
SCRAM_ALL = 0, -- SCRAM all reactors
|
SCRAM_ALL = 0, -- SCRAM all reactors
|
||||||
STOP = 1, -- stop automatic control
|
STOP = 1, -- stop automatic control
|
||||||
@ -108,7 +107,7 @@ local FAC_COMMANDS = {
|
|||||||
ACK_ALL_ALARMS = 3 -- acknowledge all alarms on all units
|
ACK_ALL_ALARMS = 3 -- acknowledge all alarms on all units
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias UNIT_COMMANDS integer
|
---@enum UNIT_COMMANDS
|
||||||
local UNIT_COMMANDS = {
|
local UNIT_COMMANDS = {
|
||||||
SCRAM = 0, -- SCRAM the reactor
|
SCRAM = 0, -- SCRAM the reactor
|
||||||
START = 1, -- start the reactor
|
START = 1, -- start the reactor
|
||||||
@ -152,6 +151,7 @@ function comms.set_trusted_range(distance)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- generic SCADA packet object
|
-- generic SCADA packet object
|
||||||
|
---@nodiscard
|
||||||
function comms.scada_packet()
|
function comms.scada_packet()
|
||||||
local self = {
|
local self = {
|
||||||
modem_msg_in = nil,
|
modem_msg_in = nil,
|
||||||
@ -180,11 +180,12 @@ function comms.scada_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- parse in a modem message as a SCADA packet
|
-- parse in a modem message as a SCADA packet
|
||||||
---@param side string
|
---@param side string modem side
|
||||||
---@param sender integer
|
---@param sender integer sender port
|
||||||
---@param reply_to integer
|
---@param reply_to integer reply port
|
||||||
---@param message any
|
---@param message any message body
|
||||||
---@param distance integer
|
---@param distance integer transmission distance
|
||||||
|
---@return boolean valid valid message received
|
||||||
function public.receive(side, sender, reply_to, message, distance)
|
function public.receive(side, sender, reply_to, message, distance)
|
||||||
self.modem_msg_in = {
|
self.modem_msg_in = {
|
||||||
iface = side,
|
iface = side,
|
||||||
@ -223,24 +224,34 @@ function comms.scada_packet()
|
|||||||
|
|
||||||
-- public accessors --
|
-- public accessors --
|
||||||
|
|
||||||
|
---@nodiscard
|
||||||
function public.modem_event() return self.modem_msg_in end
|
function public.modem_event() return self.modem_msg_in end
|
||||||
|
---@nodiscard
|
||||||
function public.raw_sendable() return self.raw end
|
function public.raw_sendable() return self.raw end
|
||||||
|
|
||||||
|
---@nodiscard
|
||||||
function public.local_port() return self.modem_msg_in.s_port end
|
function public.local_port() return self.modem_msg_in.s_port end
|
||||||
|
---@nodiscard
|
||||||
function public.remote_port() return self.modem_msg_in.r_port end
|
function public.remote_port() return self.modem_msg_in.r_port end
|
||||||
|
|
||||||
|
---@nodiscard
|
||||||
function public.is_valid() return self.valid end
|
function public.is_valid() return self.valid end
|
||||||
|
|
||||||
|
---@nodiscard
|
||||||
function public.seq_num() return self.seq_num end
|
function public.seq_num() return self.seq_num end
|
||||||
|
---@nodiscard
|
||||||
function public.protocol() return self.protocol end
|
function public.protocol() return self.protocol end
|
||||||
|
---@nodiscard
|
||||||
function public.length() return self.length end
|
function public.length() return self.length end
|
||||||
|
---@nodiscard
|
||||||
function public.data() return self.payload end
|
function public.data() return self.payload end
|
||||||
|
|
||||||
return public
|
return public
|
||||||
end
|
end
|
||||||
|
|
||||||
-- MODBUS packet
|
-- MODBUS packet<br>
|
||||||
-- modeled after MODBUS TCP packet
|
-- modeled after MODBUS TCP packet
|
||||||
|
---@nodiscard
|
||||||
function comms.modbus_packet()
|
function comms.modbus_packet()
|
||||||
local self = {
|
local self = {
|
||||||
frame = nil,
|
frame = nil,
|
||||||
@ -309,9 +320,11 @@ function comms.modbus_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- get raw to send
|
-- get raw to send
|
||||||
|
---@nodiscard
|
||||||
function public.raw_sendable() return self.raw end
|
function public.raw_sendable() return self.raw end
|
||||||
|
|
||||||
-- get this packet as a frame with an immutable relation to this object
|
-- get this packet as a frame with an immutable relation to this object
|
||||||
|
---@nodiscard
|
||||||
function public.get()
|
function public.get()
|
||||||
---@class modbus_frame
|
---@class modbus_frame
|
||||||
local frame = {
|
local frame = {
|
||||||
@ -330,6 +343,7 @@ function comms.modbus_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- reactor PLC packet
|
-- reactor PLC packet
|
||||||
|
---@nodiscard
|
||||||
function comms.rplc_packet()
|
function comms.rplc_packet()
|
||||||
local self = {
|
local self = {
|
||||||
frame = nil,
|
frame = nil,
|
||||||
@ -410,9 +424,11 @@ function comms.rplc_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- get raw to send
|
-- get raw to send
|
||||||
|
---@nodiscard
|
||||||
function public.raw_sendable() return self.raw end
|
function public.raw_sendable() return self.raw end
|
||||||
|
|
||||||
-- get this packet as a frame with an immutable relation to this object
|
-- get this packet as a frame with an immutable relation to this object
|
||||||
|
---@nodiscard
|
||||||
function public.get()
|
function public.get()
|
||||||
---@class rplc_frame
|
---@class rplc_frame
|
||||||
local frame = {
|
local frame = {
|
||||||
@ -430,6 +446,7 @@ function comms.rplc_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- SCADA management packet
|
-- SCADA management packet
|
||||||
|
---@nodiscard
|
||||||
function comms.mgmt_packet()
|
function comms.mgmt_packet()
|
||||||
local self = {
|
local self = {
|
||||||
frame = nil,
|
frame = nil,
|
||||||
@ -500,9 +517,11 @@ function comms.mgmt_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- get raw to send
|
-- get raw to send
|
||||||
|
---@nodiscard
|
||||||
function public.raw_sendable() return self.raw end
|
function public.raw_sendable() return self.raw end
|
||||||
|
|
||||||
-- get this packet as a frame with an immutable relation to this object
|
-- get this packet as a frame with an immutable relation to this object
|
||||||
|
---@nodiscard
|
||||||
function public.get()
|
function public.get()
|
||||||
---@class mgmt_frame
|
---@class mgmt_frame
|
||||||
local frame = {
|
local frame = {
|
||||||
@ -519,6 +538,7 @@ function comms.mgmt_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- SCADA coordinator packet
|
-- SCADA coordinator packet
|
||||||
|
---@nodiscard
|
||||||
function comms.crdn_packet()
|
function comms.crdn_packet()
|
||||||
local self = {
|
local self = {
|
||||||
frame = nil,
|
frame = nil,
|
||||||
@ -532,6 +552,7 @@ function comms.crdn_packet()
|
|||||||
local public = {}
|
local public = {}
|
||||||
|
|
||||||
-- check that type is known
|
-- check that type is known
|
||||||
|
---@nodiscard
|
||||||
local function _crdn_type_valid()
|
local function _crdn_type_valid()
|
||||||
return self.type == SCADA_CRDN_TYPES.INITIAL_BUILDS or
|
return self.type == SCADA_CRDN_TYPES.INITIAL_BUILDS or
|
||||||
self.type == SCADA_CRDN_TYPES.FAC_BUILDS or
|
self.type == SCADA_CRDN_TYPES.FAC_BUILDS or
|
||||||
@ -590,9 +611,11 @@ function comms.crdn_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- get raw to send
|
-- get raw to send
|
||||||
|
---@nodiscard
|
||||||
function public.raw_sendable() return self.raw end
|
function public.raw_sendable() return self.raw end
|
||||||
|
|
||||||
-- get this packet as a frame with an immutable relation to this object
|
-- get this packet as a frame with an immutable relation to this object
|
||||||
|
---@nodiscard
|
||||||
function public.get()
|
function public.get()
|
||||||
---@class crdn_frame
|
---@class crdn_frame
|
||||||
local frame = {
|
local frame = {
|
||||||
@ -609,7 +632,8 @@ function comms.crdn_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- coordinator API (CAPI) packet
|
-- coordinator API (CAPI) packet
|
||||||
-- @todo
|
---@todo implement for pocket access
|
||||||
|
---@nodiscard
|
||||||
function comms.capi_packet()
|
function comms.capi_packet()
|
||||||
local self = {
|
local self = {
|
||||||
frame = nil,
|
frame = nil,
|
||||||
@ -623,7 +647,7 @@ function comms.capi_packet()
|
|||||||
local public = {}
|
local public = {}
|
||||||
|
|
||||||
local function _capi_type_valid()
|
local function _capi_type_valid()
|
||||||
-- @todo
|
---@todo
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -675,9 +699,11 @@ function comms.capi_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- get raw to send
|
-- get raw to send
|
||||||
|
---@nodiscard
|
||||||
function public.raw_sendable() return self.raw end
|
function public.raw_sendable() return self.raw end
|
||||||
|
|
||||||
-- get this packet as a frame with an immutable relation to this object
|
-- get this packet as a frame with an immutable relation to this object
|
||||||
|
---@nodiscard
|
||||||
function public.get()
|
function public.get()
|
||||||
---@class capi_frame
|
---@class capi_frame
|
||||||
local frame = {
|
local frame = {
|
||||||
@ -694,6 +720,7 @@ function comms.capi_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- convert rtu_t to RTU unit type
|
-- convert rtu_t to RTU unit type
|
||||||
|
---@nodiscard
|
||||||
---@param type rtu_t
|
---@param type rtu_t
|
||||||
---@return RTU_UNIT_TYPES|nil
|
---@return RTU_UNIT_TYPES|nil
|
||||||
function comms.rtu_t_to_unit_type(type)
|
function comms.rtu_t_to_unit_type(type)
|
||||||
@ -717,6 +744,7 @@ function comms.rtu_t_to_unit_type(type)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- convert RTU unit type to rtu_t
|
-- convert RTU unit type to rtu_t
|
||||||
|
---@nodiscard
|
||||||
---@param utype RTU_UNIT_TYPES
|
---@param utype RTU_UNIT_TYPES
|
||||||
---@return rtu_t|nil
|
---@return rtu_t|nil
|
||||||
function comms.advert_type_to_rtu_t(utype)
|
function comms.advert_type_to_rtu_t(utype)
|
||||||
|
@ -70,6 +70,7 @@ function crypto.init(password, server_port)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- encrypt plaintext
|
-- encrypt plaintext
|
||||||
|
---@nodiscard
|
||||||
---@param plaintext string
|
---@param plaintext string
|
||||||
---@return table initial_value, string ciphertext
|
---@return table initial_value, string ciphertext
|
||||||
function crypto.encrypt(plaintext)
|
function crypto.encrypt(plaintext)
|
||||||
@ -113,6 +114,7 @@ function crypto.encrypt(plaintext)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- decrypt ciphertext
|
-- decrypt ciphertext
|
||||||
|
---@nodiscard
|
||||||
---@param iv string CTR initial value
|
---@param iv string CTR initial value
|
||||||
---@param ciphertext string ciphertext hex
|
---@param ciphertext string ciphertext hex
|
||||||
---@return string plaintext
|
---@return string plaintext
|
||||||
@ -135,6 +137,7 @@ function crypto.decrypt(iv, ciphertext)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- generate HMAC of message
|
-- generate HMAC of message
|
||||||
|
---@nodiscard
|
||||||
---@param message_hex string initial value concatenated with ciphertext
|
---@param message_hex string initial value concatenated with ciphertext
|
||||||
function crypto.hmac(message_hex)
|
function crypto.hmac(message_hex)
|
||||||
local start = util.time()
|
local start = util.time()
|
||||||
@ -201,11 +204,12 @@ function crypto.secure_modem(modem)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- parse in a modem message as a network packet
|
-- parse in a modem message as a network packet
|
||||||
---@param side string
|
---@nodiscard
|
||||||
---@param sender integer
|
---@param side string modem side
|
||||||
---@param reply_to integer
|
---@param sender integer sender port
|
||||||
|
---@param reply_to integer reply port
|
||||||
---@param message any encrypted packet sent with secure_modem.transmit
|
---@param message any encrypted packet sent with secure_modem.transmit
|
||||||
---@param distance integer
|
---@param distance integer transmission distance
|
||||||
---@return string side, integer sender, integer reply_to, any plaintext_message, integer distance
|
---@return string side, integer sender, integer reply_to, any plaintext_message, integer distance
|
||||||
function public.receive(side, sender, reply_to, message, distance)
|
function public.receive(side, sender, reply_to, message, distance)
|
||||||
local body = ""
|
local body = ""
|
||||||
|
@ -18,7 +18,7 @@ log.MODE = MODE
|
|||||||
-- whether to log debug messages or not
|
-- whether to log debug messages or not
|
||||||
local LOG_DEBUG = true
|
local LOG_DEBUG = true
|
||||||
|
|
||||||
local _log_sys = {
|
local log_sys = {
|
||||||
path = "/log.txt",
|
path = "/log.txt",
|
||||||
mode = MODE.APPEND,
|
mode = MODE.APPEND,
|
||||||
file = nil,
|
file = nil,
|
||||||
@ -33,27 +33,25 @@ local free_space = fs.getFreeSpace
|
|||||||
---@param write_mode MODE
|
---@param write_mode MODE
|
||||||
---@param dmesg_redirect? table terminal/window to direct dmesg to
|
---@param dmesg_redirect? table terminal/window to direct dmesg to
|
||||||
function log.init(path, write_mode, dmesg_redirect)
|
function log.init(path, write_mode, dmesg_redirect)
|
||||||
_log_sys.path = path
|
log_sys.path = path
|
||||||
_log_sys.mode = write_mode
|
log_sys.mode = write_mode
|
||||||
|
|
||||||
if _log_sys.mode == MODE.APPEND then
|
if log_sys.mode == MODE.APPEND then
|
||||||
_log_sys.file = fs.open(path, "a")
|
log_sys.file = fs.open(path, "a")
|
||||||
else
|
else
|
||||||
_log_sys.file = fs.open(path, "w")
|
log_sys.file = fs.open(path, "w")
|
||||||
end
|
end
|
||||||
|
|
||||||
if dmesg_redirect then
|
if dmesg_redirect then
|
||||||
_log_sys.dmesg_out = dmesg_redirect
|
log_sys.dmesg_out = dmesg_redirect
|
||||||
else
|
else
|
||||||
_log_sys.dmesg_out = term.current()
|
log_sys.dmesg_out = term.current()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- direct dmesg output to a monitor/window
|
-- direct dmesg output to a monitor/window
|
||||||
---@param window table window or terminal reference
|
---@param window table window or terminal reference
|
||||||
function log.direct_dmesg(window)
|
function log.direct_dmesg(window) log_sys.dmesg_out = window end
|
||||||
_log_sys.dmesg_out = window
|
|
||||||
end
|
|
||||||
|
|
||||||
-- private log write function
|
-- private log write function
|
||||||
---@param msg string
|
---@param msg string
|
||||||
@ -64,8 +62,8 @@ local function _log(msg)
|
|||||||
|
|
||||||
-- attempt to write log
|
-- attempt to write log
|
||||||
local status, result = pcall(function ()
|
local status, result = pcall(function ()
|
||||||
_log_sys.file.writeLine(stamped)
|
log_sys.file.writeLine(stamped)
|
||||||
_log_sys.file.flush()
|
log_sys.file.flush()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- if we don't have space, we need to create a new log file
|
-- if we don't have space, we need to create a new log file
|
||||||
@ -80,18 +78,18 @@ local function _log(msg)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if out_of_space or (free_space(_log_sys.path) < 100) then
|
if out_of_space or (free_space(log_sys.path) < 100) then
|
||||||
-- delete the old log file before opening a new one
|
-- delete the old log file before opening a new one
|
||||||
_log_sys.file.close()
|
log_sys.file.close()
|
||||||
fs.delete(_log_sys.path)
|
fs.delete(log_sys.path)
|
||||||
|
|
||||||
-- re-init logger and pass dmesg_out so that it doesn't change
|
-- re-init logger and pass dmesg_out so that it doesn't change
|
||||||
log.init(_log_sys.path, _log_sys.mode, _log_sys.dmesg_out)
|
log.init(log_sys.path, log_sys.mode, log_sys.dmesg_out)
|
||||||
|
|
||||||
-- leave a message
|
-- leave a message
|
||||||
_log_sys.file.writeLine(time_stamp .. "recycled log file")
|
log_sys.file.writeLine(time_stamp .. "recycled log file")
|
||||||
_log_sys.file.writeLine(stamped)
|
log_sys.file.writeLine(stamped)
|
||||||
_log_sys.file.flush()
|
log_sys.file.flush()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -109,7 +107,7 @@ function log.dmesg(msg, tag, tag_color)
|
|||||||
tag = util.strval(tag)
|
tag = util.strval(tag)
|
||||||
|
|
||||||
local t_stamp = string.format("%12.2f", os.clock())
|
local t_stamp = string.format("%12.2f", os.clock())
|
||||||
local out = _log_sys.dmesg_out
|
local out = log_sys.dmesg_out
|
||||||
|
|
||||||
if out ~= nil then
|
if out ~= nil then
|
||||||
local out_w, out_h = out.getSize()
|
local out_w, out_h = out.getSize()
|
||||||
@ -197,6 +195,7 @@ function log.dmesg(msg, tag, tag_color)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- print a dmesg message, but then show remaining seconds instead of timestamp
|
-- print a dmesg message, but then show remaining seconds instead of timestamp
|
||||||
|
---@nodiscard
|
||||||
---@param msg string message
|
---@param msg string message
|
||||||
---@param tag? string log tag
|
---@param tag? string log tag
|
||||||
---@param tag_color? integer log tag color
|
---@param tag_color? integer log tag color
|
||||||
@ -204,7 +203,7 @@ end
|
|||||||
function log.dmesg_working(msg, tag, tag_color)
|
function log.dmesg_working(msg, tag, tag_color)
|
||||||
local ts_coord = log.dmesg(msg, tag, tag_color)
|
local ts_coord = log.dmesg(msg, tag, tag_color)
|
||||||
|
|
||||||
local out = _log_sys.dmesg_out
|
local out = log_sys.dmesg_out
|
||||||
local width = (ts_coord.x2 - ts_coord.x1) + 1
|
local width = (ts_coord.x2 - ts_coord.x1) + 1
|
||||||
|
|
||||||
if out ~= nil then
|
if out ~= nil then
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
local mqueue = {}
|
local mqueue = {}
|
||||||
|
|
||||||
---@alias MQ_TYPE integer
|
---@enum MQ_TYPE
|
||||||
local TYPE = {
|
local TYPE = {
|
||||||
COMMAND = 0,
|
COMMAND = 0,
|
||||||
DATA = 1,
|
DATA = 1,
|
||||||
@ -14,6 +14,7 @@ local TYPE = {
|
|||||||
mqueue.TYPE = TYPE
|
mqueue.TYPE = TYPE
|
||||||
|
|
||||||
-- create a new message queue
|
-- create a new message queue
|
||||||
|
---@nodiscard
|
||||||
function mqueue.new()
|
function mqueue.new()
|
||||||
local queue = {}
|
local queue = {}
|
||||||
|
|
||||||
@ -35,10 +36,13 @@ function mqueue.new()
|
|||||||
function public.length() return #queue end
|
function public.length() return #queue end
|
||||||
|
|
||||||
-- check if queue is empty
|
-- check if queue is empty
|
||||||
|
---@nodiscard
|
||||||
---@return boolean is_empty
|
---@return boolean is_empty
|
||||||
function public.empty() return #queue == 0 end
|
function public.empty() return #queue == 0 end
|
||||||
|
|
||||||
-- check if queue has contents
|
-- check if queue has contents
|
||||||
|
---@nodiscard
|
||||||
|
---@return boolean has_contents
|
||||||
function public.ready() return #queue ~= 0 end
|
function public.ready() return #queue ~= 0 end
|
||||||
|
|
||||||
-- push a new item onto the queue
|
-- push a new item onto the queue
|
||||||
@ -68,6 +72,7 @@ function mqueue.new()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- get an item off the queue
|
-- get an item off the queue
|
||||||
|
---@nodiscard
|
||||||
---@return queue_item|nil
|
---@return queue_item|nil
|
||||||
function public.pop()
|
function public.pop()
|
||||||
if #queue > 0 then
|
if #queue > 0 then
|
||||||
|
@ -24,7 +24,7 @@ ppm.VIRTUAL_DEVICE_TYPE = VIRTUAL_DEVICE_TYPE
|
|||||||
|
|
||||||
local REPORT_FREQUENCY = 20 -- log every 20 faults per function
|
local REPORT_FREQUENCY = 20 -- log every 20 faults per function
|
||||||
|
|
||||||
local _ppm_sys = {
|
local ppm_sys = {
|
||||||
mounts = {},
|
mounts = {},
|
||||||
next_vid = 0,
|
next_vid = 0,
|
||||||
auto_cf = false,
|
auto_cf = false,
|
||||||
@ -34,11 +34,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
|
-- wrap peripheral calls with lua protected call as we don't want a disconnect to crash a program<br>
|
||||||
---
|
-- also provides peripheral-specific fault checks (auto-clear fault defaults to true)<br>
|
||||||
---also provides peripheral-specific fault checks (auto-clear fault defaults to true)
|
-- assumes iface is a valid peripheral
|
||||||
---
|
|
||||||
---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 = {
|
||||||
@ -68,7 +66,7 @@ local function peri_init(iface)
|
|||||||
if status then
|
if status then
|
||||||
-- auto fault clear
|
-- auto fault clear
|
||||||
if self.auto_cf then self.faulted = false end
|
if self.auto_cf then self.faulted = false end
|
||||||
if _ppm_sys.auto_cf then _ppm_sys.faulted = false end
|
if ppm_sys.auto_cf then ppm_sys.faulted = false end
|
||||||
|
|
||||||
self.fault_counts[key] = 0
|
self.fault_counts[key] = 0
|
||||||
|
|
||||||
@ -80,10 +78,10 @@ local function peri_init(iface)
|
|||||||
self.faulted = true
|
self.faulted = true
|
||||||
self.last_fault = result
|
self.last_fault = result
|
||||||
|
|
||||||
_ppm_sys.faulted = true
|
ppm_sys.faulted = true
|
||||||
_ppm_sys.last_fault = result
|
ppm_sys.last_fault = result
|
||||||
|
|
||||||
if not _ppm_sys.mute and (self.fault_counts[key] % REPORT_FREQUENCY == 0) then
|
if not ppm_sys.mute and (self.fault_counts[key] % REPORT_FREQUENCY == 0) then
|
||||||
local count_str = ""
|
local count_str = ""
|
||||||
if self.fault_counts[key] > 0 then
|
if self.fault_counts[key] > 0 then
|
||||||
count_str = " [" .. self.fault_counts[key] .. " total faults]"
|
count_str = " [" .. self.fault_counts[key] .. " total faults]"
|
||||||
@ -95,7 +93,7 @@ local function peri_init(iface)
|
|||||||
self.fault_counts[key] = self.fault_counts[key] + 1
|
self.fault_counts[key] = self.fault_counts[key] + 1
|
||||||
|
|
||||||
if result == "Terminated" then
|
if result == "Terminated" then
|
||||||
_ppm_sys.terminate = true
|
ppm_sys.terminate = true
|
||||||
end
|
end
|
||||||
|
|
||||||
return ACCESS_FAULT
|
return ACCESS_FAULT
|
||||||
@ -136,10 +134,10 @@ local function peri_init(iface)
|
|||||||
self.faulted = true
|
self.faulted = true
|
||||||
self.last_fault = UNDEFINED_FIELD
|
self.last_fault = UNDEFINED_FIELD
|
||||||
|
|
||||||
_ppm_sys.faulted = true
|
ppm_sys.faulted = true
|
||||||
_ppm_sys.last_fault = UNDEFINED_FIELD
|
ppm_sys.last_fault = UNDEFINED_FIELD
|
||||||
|
|
||||||
if not _ppm_sys.mute and (self.fault_counts[key] % REPORT_FREQUENCY == 0) then
|
if not ppm_sys.mute and (self.fault_counts[key] % REPORT_FREQUENCY == 0) then
|
||||||
local count_str = ""
|
local count_str = ""
|
||||||
if self.fault_counts[key] > 0 then
|
if self.fault_counts[key] > 0 then
|
||||||
count_str = " [" .. self.fault_counts[key] .. " total calls]"
|
count_str = " [" .. self.fault_counts[key] .. " total calls]"
|
||||||
@ -169,48 +167,35 @@ end
|
|||||||
-- REPORTING --
|
-- REPORTING --
|
||||||
|
|
||||||
-- silence error prints
|
-- silence error prints
|
||||||
function ppm.disable_reporting()
|
function ppm.disable_reporting() ppm_sys.mute = true end
|
||||||
_ppm_sys.mute = true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- allow error prints
|
-- allow error prints
|
||||||
function ppm.enable_reporting()
|
function ppm.enable_reporting() ppm_sys.mute = false end
|
||||||
_ppm_sys.mute = false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- FAULT MEMORY --
|
-- FAULT MEMORY --
|
||||||
|
|
||||||
-- enable automatically clearing fault flag
|
-- enable automatically clearing fault flag
|
||||||
function ppm.enable_afc()
|
function ppm.enable_afc() ppm_sys.auto_cf = true end
|
||||||
_ppm_sys.auto_cf = true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- disable automatically clearing fault flag
|
-- disable automatically clearing fault flag
|
||||||
function ppm.disable_afc()
|
function ppm.disable_afc() ppm_sys.auto_cf = false end
|
||||||
_ppm_sys.auto_cf = false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- clear fault flag
|
-- clear fault flag
|
||||||
function ppm.clear_fault()
|
function ppm.clear_fault() ppm_sys.faulted = false end
|
||||||
_ppm_sys.faulted = false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- check fault flag
|
-- check fault flag
|
||||||
function ppm.is_faulted()
|
---@nodiscard
|
||||||
return _ppm_sys.faulted
|
function ppm.is_faulted() return ppm_sys.faulted end
|
||||||
end
|
|
||||||
|
|
||||||
-- get the last fault message
|
-- get the last fault message
|
||||||
function ppm.get_last_fault()
|
---@nodiscard
|
||||||
return _ppm_sys.last_fault
|
function ppm.get_last_fault() return ppm_sys.last_fault end
|
||||||
end
|
|
||||||
|
|
||||||
-- TERMINATION --
|
-- TERMINATION --
|
||||||
|
|
||||||
-- if a caught error was a termination request
|
-- if a caught error was a termination request
|
||||||
function ppm.should_terminate()
|
---@nodiscard
|
||||||
return _ppm_sys.terminate
|
function ppm.should_terminate() return ppm_sys.terminate end
|
||||||
end
|
|
||||||
|
|
||||||
-- MOUNTING --
|
-- MOUNTING --
|
||||||
|
|
||||||
@ -218,12 +203,12 @@ end
|
|||||||
function ppm.mount_all()
|
function ppm.mount_all()
|
||||||
local ifaces = peripheral.getNames()
|
local ifaces = peripheral.getNames()
|
||||||
|
|
||||||
_ppm_sys.mounts = {}
|
ppm_sys.mounts = {}
|
||||||
|
|
||||||
for i = 1, #ifaces do
|
for i = 1, #ifaces do
|
||||||
_ppm_sys.mounts[ifaces[i]] = peri_init(ifaces[i])
|
ppm_sys.mounts[ifaces[i]] = peri_init(ifaces[i])
|
||||||
|
|
||||||
log.info(util.c("PPM: found a ", _ppm_sys.mounts[ifaces[i]].type, " (", ifaces[i], ")"))
|
log.info(util.c("PPM: found a ", ppm_sys.mounts[ifaces[i]].type, " (", ifaces[i], ")"))
|
||||||
end
|
end
|
||||||
|
|
||||||
if #ifaces == 0 then
|
if #ifaces == 0 then
|
||||||
@ -232,6 +217,7 @@ function ppm.mount_all()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- mount a particular device
|
-- mount a particular device
|
||||||
|
---@nodiscard
|
||||||
---@param iface string CC peripheral interface
|
---@param iface string CC peripheral interface
|
||||||
---@return string|nil type, table|nil device
|
---@return string|nil type, table|nil device
|
||||||
function ppm.mount(iface)
|
function ppm.mount(iface)
|
||||||
@ -241,10 +227,10 @@ function ppm.mount(iface)
|
|||||||
|
|
||||||
for i = 1, #ifaces do
|
for i = 1, #ifaces do
|
||||||
if iface == ifaces[i] then
|
if iface == ifaces[i] then
|
||||||
_ppm_sys.mounts[iface] = peri_init(iface)
|
ppm_sys.mounts[iface] = peri_init(iface)
|
||||||
|
|
||||||
pm_type = _ppm_sys.mounts[iface].type
|
pm_type = ppm_sys.mounts[iface].type
|
||||||
pm_dev = _ppm_sys.mounts[iface].dev
|
pm_dev = ppm_sys.mounts[iface].dev
|
||||||
|
|
||||||
log.info(util.c("PPM: mount(", iface, ") -> found a ", pm_type))
|
log.info(util.c("PPM: mount(", iface, ") -> found a ", pm_type))
|
||||||
break
|
break
|
||||||
@ -255,26 +241,27 @@ function ppm.mount(iface)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- mount a virtual, placeholder device (specifically designed for RTU startup with missing devices)
|
-- mount a virtual, placeholder device (specifically designed for RTU startup with missing devices)
|
||||||
|
---@nodiscard
|
||||||
---@return string type, table device
|
---@return string type, table device
|
||||||
function ppm.mount_virtual()
|
function ppm.mount_virtual()
|
||||||
local iface = "ppm_vdev_" .. _ppm_sys.next_vid
|
local iface = "ppm_vdev_" .. ppm_sys.next_vid
|
||||||
|
|
||||||
_ppm_sys.mounts[iface] = peri_init("__virtual__")
|
ppm_sys.mounts[iface] = peri_init("__virtual__")
|
||||||
_ppm_sys.next_vid = _ppm_sys.next_vid + 1
|
ppm_sys.next_vid = ppm_sys.next_vid + 1
|
||||||
|
|
||||||
log.info(util.c("PPM: mount_virtual() -> allocated new virtual device ", iface))
|
log.info(util.c("PPM: mount_virtual() -> allocated new virtual device ", iface))
|
||||||
|
|
||||||
return _ppm_sys.mounts[iface].type, _ppm_sys.mounts[iface].dev
|
return ppm_sys.mounts[iface].type, ppm_sys.mounts[iface].dev
|
||||||
end
|
end
|
||||||
|
|
||||||
-- manually unmount a peripheral from the PPM
|
-- manually unmount a peripheral from the PPM
|
||||||
---@param device table device table
|
---@param device table device table
|
||||||
function ppm.unmount(device)
|
function ppm.unmount(device)
|
||||||
if device then
|
if device then
|
||||||
for side, data in pairs(_ppm_sys.mounts) do
|
for side, data in pairs(ppm_sys.mounts) do
|
||||||
if data.dev == device then
|
if data.dev == device then
|
||||||
log.warning(util.c("PPM: manually unmounted ", data.type, " mounted to ", side))
|
log.warning(util.c("PPM: manually unmounted ", data.type, " mounted to ", side))
|
||||||
_ppm_sys.mounts[side] = nil
|
ppm_sys.mounts[side] = nil
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -282,6 +269,7 @@ function ppm.unmount(device)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- handle peripheral_detach event
|
-- handle peripheral_detach event
|
||||||
|
---@nodiscard
|
||||||
---@param iface string CC peripheral interface
|
---@param iface string CC peripheral interface
|
||||||
---@return string|nil type, table|nil device
|
---@return string|nil type, table|nil device
|
||||||
function ppm.handle_unmount(iface)
|
function ppm.handle_unmount(iface)
|
||||||
@ -289,7 +277,7 @@ function ppm.handle_unmount(iface)
|
|||||||
local pm_type = nil
|
local pm_type = nil
|
||||||
|
|
||||||
-- what got disconnected?
|
-- what got disconnected?
|
||||||
local lost_dev = _ppm_sys.mounts[iface]
|
local lost_dev = ppm_sys.mounts[iface]
|
||||||
|
|
||||||
if lost_dev then
|
if lost_dev then
|
||||||
pm_type = lost_dev.type
|
pm_type = lost_dev.type
|
||||||
@ -300,7 +288,7 @@ function ppm.handle_unmount(iface)
|
|||||||
log.error(util.c("PPM: lost device unknown to the PPM mounted to ", iface))
|
log.error(util.c("PPM: lost device unknown to the PPM mounted to ", iface))
|
||||||
end
|
end
|
||||||
|
|
||||||
_ppm_sys.mounts[iface] = nil
|
ppm_sys.mounts[iface] = nil
|
||||||
|
|
||||||
return pm_type, pm_dev
|
return pm_type, pm_dev
|
||||||
end
|
end
|
||||||
@ -308,23 +296,26 @@ end
|
|||||||
-- GENERAL ACCESSORS --
|
-- GENERAL ACCESSORS --
|
||||||
|
|
||||||
-- list all available peripherals
|
-- list all available peripherals
|
||||||
|
---@nodiscard
|
||||||
---@return table names
|
---@return table names
|
||||||
function ppm.list_avail()
|
function ppm.list_avail()
|
||||||
return peripheral.getNames()
|
return peripheral.getNames()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- list mounted peripherals
|
-- list mounted peripherals
|
||||||
|
---@nodiscard
|
||||||
---@return table mounts
|
---@return table mounts
|
||||||
function ppm.list_mounts()
|
function ppm.list_mounts()
|
||||||
return _ppm_sys.mounts
|
return ppm_sys.mounts
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get a mounted peripheral side/interface by device table
|
-- get a mounted peripheral side/interface by device table
|
||||||
|
---@nodiscard
|
||||||
---@param device table device table
|
---@param device table device table
|
||||||
---@return string|nil iface CC peripheral interface
|
---@return string|nil iface CC peripheral interface
|
||||||
function ppm.get_iface(device)
|
function ppm.get_iface(device)
|
||||||
if device then
|
if device then
|
||||||
for side, data in pairs(_ppm_sys.mounts) do
|
for side, data in pairs(ppm_sys.mounts) do
|
||||||
if data.dev == device then return side end
|
if data.dev == device then return side end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -333,30 +324,33 @@ function ppm.get_iface(device)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- get a mounted peripheral by side/interface
|
-- get a mounted peripheral by side/interface
|
||||||
|
---@nodiscard
|
||||||
---@param iface string CC peripheral interface
|
---@param iface string CC peripheral interface
|
||||||
---@return table|nil device function table
|
---@return table|nil device function table
|
||||||
function ppm.get_periph(iface)
|
function ppm.get_periph(iface)
|
||||||
if _ppm_sys.mounts[iface] then
|
if ppm_sys.mounts[iface] then
|
||||||
return _ppm_sys.mounts[iface].dev
|
return ppm_sys.mounts[iface].dev
|
||||||
else return nil end
|
else return nil end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get a mounted peripheral type by side/interface
|
-- get a mounted peripheral type by side/interface
|
||||||
|
---@nodiscard
|
||||||
---@param iface string CC peripheral interface
|
---@param iface string CC peripheral interface
|
||||||
---@return string|nil type
|
---@return string|nil type
|
||||||
function ppm.get_type(iface)
|
function ppm.get_type(iface)
|
||||||
if _ppm_sys.mounts[iface] then
|
if ppm_sys.mounts[iface] then
|
||||||
return _ppm_sys.mounts[iface].type
|
return ppm_sys.mounts[iface].type
|
||||||
else return nil end
|
else return nil end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get all mounted peripherals by type
|
-- get all mounted peripherals by type
|
||||||
|
---@nodiscard
|
||||||
---@param name string type name
|
---@param name string type name
|
||||||
---@return table devices device function tables
|
---@return table devices device function tables
|
||||||
function ppm.get_all_devices(name)
|
function ppm.get_all_devices(name)
|
||||||
local devices = {}
|
local devices = {}
|
||||||
|
|
||||||
for _, data in pairs(_ppm_sys.mounts) do
|
for _, data in pairs(ppm_sys.mounts) do
|
||||||
if data.type == name then
|
if data.type == name then
|
||||||
table.insert(devices, data.dev)
|
table.insert(devices, data.dev)
|
||||||
end
|
end
|
||||||
@ -366,12 +360,13 @@ function ppm.get_all_devices(name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- get a mounted peripheral by type (if multiple, returns the first)
|
-- get a mounted peripheral by type (if multiple, returns the first)
|
||||||
|
---@nodiscard
|
||||||
---@param name string type name
|
---@param name string type name
|
||||||
---@return table|nil device function table
|
---@return table|nil device function table
|
||||||
function ppm.get_device(name)
|
function ppm.get_device(name)
|
||||||
local device = nil
|
local device = nil
|
||||||
|
|
||||||
for side, data in pairs(_ppm_sys.mounts) do
|
for _, data in pairs(ppm_sys.mounts) do
|
||||||
if data.type == name then
|
if data.type == name then
|
||||||
device = data.dev
|
device = data.dev
|
||||||
break
|
break
|
||||||
@ -384,20 +379,21 @@ end
|
|||||||
-- SPECIFIC DEVICE ACCESSORS --
|
-- SPECIFIC DEVICE ACCESSORS --
|
||||||
|
|
||||||
-- get the fission reactor (if multiple, returns the first)
|
-- get the fission reactor (if multiple, returns the first)
|
||||||
|
---@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")
|
return ppm.get_device("fissionReactorLogicAdapter")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get the wireless modem (if multiple, returns the first)
|
-- 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
|
||||||
|
---@nodiscard
|
||||||
---@return table|nil modem function table
|
---@return table|nil modem function table
|
||||||
function ppm.get_wireless_modem()
|
function ppm.get_wireless_modem()
|
||||||
local w_modem = nil
|
local w_modem = nil
|
||||||
local emulated_env = periphemu ~= nil
|
local emulated_env = periphemu ~= nil
|
||||||
|
|
||||||
for _, device in pairs(_ppm_sys.mounts) do
|
for _, device in pairs(ppm_sys.mounts) do
|
||||||
if device.type == "modem" and (emulated_env or device.dev.isWireless()) then
|
if device.type == "modem" and (emulated_env or device.dev.isWireless()) then
|
||||||
w_modem = device.dev
|
w_modem = device.dev
|
||||||
break
|
break
|
||||||
@ -408,11 +404,12 @@ function ppm.get_wireless_modem()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- list all connected monitors
|
-- list all connected monitors
|
||||||
|
---@nodiscard
|
||||||
---@return table monitors
|
---@return table monitors
|
||||||
function ppm.get_monitor_list()
|
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
|
list[iface] = device
|
||||||
end
|
end
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
local psil = {}
|
local psil = {}
|
||||||
|
|
||||||
-- instantiate a new PSI layer
|
-- instantiate a new PSI layer
|
||||||
|
---@nodiscard
|
||||||
function psil.create()
|
function psil.create()
|
||||||
local self = {
|
local self = {
|
||||||
ic = {}
|
ic = {}
|
||||||
@ -19,8 +20,7 @@ function psil.create()
|
|||||||
---@class psil
|
---@class psil
|
||||||
local public = {}
|
local public = {}
|
||||||
|
|
||||||
-- subscribe to a data object in the interconnect
|
-- subscribe to a data object in the interconnect<br>
|
||||||
--
|
|
||||||
-- will call func() right away if a value is already avaliable
|
-- will call func() right away if a value is already avaliable
|
||||||
---@param key string data key
|
---@param key string data key
|
||||||
---@param func function function to call on change
|
---@param func function function to call on change
|
||||||
|
@ -89,6 +89,7 @@ rsio.IO = IO_PORT
|
|||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
-- port to string
|
-- port to string
|
||||||
|
---@nodiscard
|
||||||
---@param port IO_PORT
|
---@param port IO_PORT
|
||||||
function rsio.to_string(port)
|
function rsio.to_string(port)
|
||||||
local names = {
|
local names = {
|
||||||
@ -194,6 +195,7 @@ local RS_DIO_MAP = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
-- get the mode of a port
|
-- get the mode of a port
|
||||||
|
---@nodiscard
|
||||||
---@param port IO_PORT
|
---@param port IO_PORT
|
||||||
---@return IO_MODE
|
---@return IO_MODE
|
||||||
function rsio.get_io_mode(port)
|
function rsio.get_io_mode(port)
|
||||||
@ -239,6 +241,7 @@ end
|
|||||||
local RS_SIDES = rs.getSides()
|
local RS_SIDES = rs.getSides()
|
||||||
|
|
||||||
-- check if a port is valid
|
-- check if a port is valid
|
||||||
|
---@nodiscard
|
||||||
---@param port IO_PORT
|
---@param port IO_PORT
|
||||||
---@return boolean valid
|
---@return boolean valid
|
||||||
function rsio.is_valid_port(port)
|
function rsio.is_valid_port(port)
|
||||||
@ -246,6 +249,7 @@ function rsio.is_valid_port(port)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- check if a side is valid
|
-- check if a side is valid
|
||||||
|
---@nodiscard
|
||||||
---@param side string
|
---@param side string
|
||||||
---@return boolean valid
|
---@return boolean valid
|
||||||
function rsio.is_valid_side(side)
|
function rsio.is_valid_side(side)
|
||||||
@ -258,6 +262,7 @@ function rsio.is_valid_side(side)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- check if a color is a valid single color
|
-- check if a color is a valid single color
|
||||||
|
---@nodiscard
|
||||||
---@param color integer
|
---@param color integer
|
||||||
---@return boolean valid
|
---@return boolean valid
|
||||||
function rsio.is_color(color)
|
function rsio.is_color(color)
|
||||||
@ -269,22 +274,25 @@ end
|
|||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
-- get digital I/O level reading from a redstone boolean input value
|
-- get digital I/O level reading from a redstone boolean input value
|
||||||
---@param rs_value boolean
|
---@nodiscard
|
||||||
|
---@param rs_value boolean raw value from redstone
|
||||||
---@return IO_LVL
|
---@return IO_LVL
|
||||||
function rsio.digital_read(rs_value)
|
function rsio.digital_read(rs_value)
|
||||||
if rs_value then return IO_LVL.HIGH else return IO_LVL.LOW end
|
if rs_value then return IO_LVL.HIGH else return IO_LVL.LOW end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get redstone boolean output value corresponding to a digital I/O level
|
-- get redstone boolean output value corresponding to a digital I/O level
|
||||||
---@param level IO_LVL
|
---@nodiscard
|
||||||
|
---@param level IO_LVL logic level
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function rsio.digital_write(level)
|
function rsio.digital_write(level)
|
||||||
return level == IO_LVL.HIGH
|
return level == IO_LVL.HIGH
|
||||||
end
|
end
|
||||||
|
|
||||||
-- returns the level corresponding to active
|
-- returns the level corresponding to active
|
||||||
---@param port IO_PORT
|
---@nodiscard
|
||||||
---@param active boolean
|
---@param port IO_PORT port (to determine active high/low)
|
||||||
|
---@param active boolean state to convert to logic level
|
||||||
---@return IO_LVL|false
|
---@return IO_LVL|false
|
||||||
function rsio.digital_write_active(port, active)
|
function rsio.digital_write_active(port, active)
|
||||||
if (not util.is_int(port)) or (port < IO_PORT.F_ALARM) or (port > IO_PORT.U_EMER_COOL) then
|
if (not util.is_int(port)) or (port < IO_PORT.F_ALARM) or (port > IO_PORT.U_EMER_COOL) then
|
||||||
@ -295,9 +303,10 @@ function rsio.digital_write_active(port, active)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- returns true if the level corresponds to active
|
-- returns true if the level corresponds to active
|
||||||
---@param port IO_PORT
|
---@nodiscard
|
||||||
---@param level IO_LVL
|
---@param port IO_PORT port (to determine active low/high)
|
||||||
---@return boolean|nil
|
---@param level IO_LVL logic level
|
||||||
|
---@return boolean|nil state true for active, false for inactive, or nil if invalid port or level provided
|
||||||
function rsio.digital_is_active(port, level)
|
function rsio.digital_is_active(port, level)
|
||||||
if not util.is_int(port) then
|
if not util.is_int(port) then
|
||||||
return nil
|
return nil
|
||||||
@ -313,6 +322,7 @@ end
|
|||||||
----------------
|
----------------
|
||||||
|
|
||||||
-- read an analog value scaled from min to max
|
-- read an analog value scaled from min to max
|
||||||
|
---@nodiscard
|
||||||
---@param rs_value number redstone reading (0 to 15)
|
---@param rs_value number redstone reading (0 to 15)
|
||||||
---@param min number minimum of range
|
---@param min number minimum of range
|
||||||
---@param max number maximum of range
|
---@param max number maximum of range
|
||||||
@ -323,6 +333,7 @@ function rsio.analog_read(rs_value, min, max)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- write an analog value from the provided scale range
|
-- write an analog value from the provided scale range
|
||||||
|
---@nodiscard
|
||||||
---@param value number value to write (from min to max range)
|
---@param value number value to write (from min to max range)
|
||||||
---@param min number minimum of range
|
---@param min number minimum of range
|
||||||
---@param max number maximum of range
|
---@param max number maximum of range
|
||||||
|
@ -19,8 +19,6 @@ function tcallbackdsp.dispatch(time, f)
|
|||||||
duration = time,
|
duration = time,
|
||||||
expiry = time + util.time_s()
|
expiry = time + util.time_s()
|
||||||
}
|
}
|
||||||
|
|
||||||
-- log.debug(util.c("TCD: queued callback for ", f, " [timer: ", timer, "]"))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- request a function to be called after the specified time, aborting any registered instances of that function reference
|
-- request a function to be called after the specified time, aborting any registered instances of that function reference
|
||||||
@ -45,8 +43,6 @@ function tcallbackdsp.dispatch_unique(time, f)
|
|||||||
duration = time,
|
duration = time,
|
||||||
expiry = time + util.time_s()
|
expiry = time + util.time_s()
|
||||||
}
|
}
|
||||||
|
|
||||||
-- log.debug(util.c("TCD: queued callback for ", f, " [timer: ", timer, "]"))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- abort a requested callback
|
-- abort a requested callback
|
||||||
@ -72,8 +68,7 @@ function tcallbackdsp.handle(event)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- identify any overdo callbacks
|
-- identify any overdo callbacks<br>
|
||||||
--
|
|
||||||
-- prints to log debug output
|
-- prints to log debug output
|
||||||
function tcallbackdsp.diagnostics()
|
function tcallbackdsp.diagnostics()
|
||||||
for timer, entry in pairs(registry) do
|
for timer, entry in pairs(registry) do
|
||||||
|
@ -12,12 +12,14 @@ local types = {}
|
|||||||
---@field amount integer
|
---@field amount integer
|
||||||
|
|
||||||
-- create a new tank fluid
|
-- create a new tank fluid
|
||||||
|
---@nodiscard
|
||||||
---@param n string name
|
---@param n string name
|
||||||
---@param a integer amount
|
---@param a integer amount
|
||||||
---@return radiation_reading
|
---@return radiation_reading
|
||||||
function types.new_tank_fluid(n, a) return { name = n, amount = a } end
|
function types.new_tank_fluid(n, a) return { name = n, amount = a } end
|
||||||
|
|
||||||
-- create a new empty tank fluid
|
-- create a new empty tank fluid
|
||||||
|
---@nodiscard
|
||||||
---@return tank_fluid
|
---@return tank_fluid
|
||||||
function types.new_empty_gas() return { type = "mekanism:empty_gas", amount = 0 } end
|
function types.new_empty_gas() return { type = "mekanism:empty_gas", amount = 0 } end
|
||||||
|
|
||||||
@ -26,12 +28,14 @@ function types.new_empty_gas() return { type = "mekanism:empty_gas", amount = 0
|
|||||||
---@field unit string
|
---@field unit string
|
||||||
|
|
||||||
-- create a new radiation reading
|
-- create a new radiation reading
|
||||||
|
---@nodiscard
|
||||||
---@param r number radiaiton level
|
---@param r number radiaiton level
|
||||||
---@param u string radiation unit
|
---@param u string radiation unit
|
||||||
---@return radiation_reading
|
---@return radiation_reading
|
||||||
function types.new_radiation_reading(r, u) return { radiation = r, unit = u } end
|
function types.new_radiation_reading(r, u) return { radiation = r, unit = u } end
|
||||||
|
|
||||||
-- create a new zeroed radiation reading
|
-- create a new zeroed radiation reading
|
||||||
|
---@nodiscard
|
||||||
---@return radiation_reading
|
---@return radiation_reading
|
||||||
function types.new_zero_radiation_reading() return { radiation = 0, unit = "nSv" } end
|
function types.new_zero_radiation_reading() return { radiation = 0, unit = "nSv" } end
|
||||||
|
|
||||||
@ -41,6 +45,7 @@ function types.new_zero_radiation_reading() return { radiation = 0, unit = "nSv"
|
|||||||
---@field z integer
|
---@field z integer
|
||||||
|
|
||||||
-- create a new coordinate
|
-- create a new coordinate
|
||||||
|
---@nodiscard
|
||||||
---@param x integer
|
---@param x integer
|
||||||
---@param y integer
|
---@param y integer
|
||||||
---@param z integer
|
---@param z integer
|
||||||
@ -48,11 +53,12 @@ function types.new_zero_radiation_reading() return { radiation = 0, unit = "nSv"
|
|||||||
function types.new_coordinate(x, y, z) return { x = x, y = y, z = z } end
|
function types.new_coordinate(x, y, z) return { x = x, y = y, z = z } end
|
||||||
|
|
||||||
-- create a new zero coordinate
|
-- create a new zero coordinate
|
||||||
|
---@nodiscard
|
||||||
---@return coordinate
|
---@return coordinate
|
||||||
function types.new_zero_coordinate() return { x = 0, y = 0, z = 0 } end
|
function types.new_zero_coordinate() return { x = 0, y = 0, z = 0 } end
|
||||||
|
|
||||||
---@class rtu_advertisement
|
---@class rtu_advertisement
|
||||||
---@field type integer
|
---@field type RTU_UNIT_TYPES
|
||||||
---@field index integer
|
---@field index integer
|
||||||
---@field reactor integer
|
---@field reactor integer
|
||||||
---@field rsio table|nil
|
---@field rsio table|nil
|
||||||
@ -62,15 +68,16 @@ function types.new_zero_coordinate() return { x = 0, y = 0, z = 0 } end
|
|||||||
---@alias color integer
|
---@alias color integer
|
||||||
|
|
||||||
-- ENUMERATION TYPES --
|
-- ENUMERATION TYPES --
|
||||||
|
--#region
|
||||||
|
|
||||||
---@alias TRI_FAIL integer
|
---@enum TRI_FAIL
|
||||||
types.TRI_FAIL = {
|
types.TRI_FAIL = {
|
||||||
OK = 0,
|
OK = 0,
|
||||||
PARTIAL = 1,
|
PARTIAL = 1,
|
||||||
FULL = 2
|
FULL = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias PROCESS integer
|
---@enum PROCESS
|
||||||
types.PROCESS = {
|
types.PROCESS = {
|
||||||
INACTIVE = 0,
|
INACTIVE = 0,
|
||||||
MAX_BURN = 1,
|
MAX_BURN = 1,
|
||||||
@ -93,7 +100,7 @@ types.PROCESS_NAMES = {
|
|||||||
"GEN_RATE_FAULT_IDLE"
|
"GEN_RATE_FAULT_IDLE"
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias WASTE_MODE integer
|
---@enum WASTE_MODE
|
||||||
types.WASTE_MODE = {
|
types.WASTE_MODE = {
|
||||||
AUTO = 1,
|
AUTO = 1,
|
||||||
PLUTONIUM = 2,
|
PLUTONIUM = 2,
|
||||||
@ -101,7 +108,7 @@ types.WASTE_MODE = {
|
|||||||
ANTI_MATTER = 4
|
ANTI_MATTER = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias ALARM integer
|
---@enum ALARM
|
||||||
types.ALARM = {
|
types.ALARM = {
|
||||||
ContainmentBreach = 1,
|
ContainmentBreach = 1,
|
||||||
ContainmentRadiation = 2,
|
ContainmentRadiation = 2,
|
||||||
@ -117,7 +124,7 @@ types.ALARM = {
|
|||||||
TurbineTrip = 12
|
TurbineTrip = 12
|
||||||
}
|
}
|
||||||
|
|
||||||
types.alarm_string = {
|
types.ALARM_NAMES = {
|
||||||
"ContainmentBreach",
|
"ContainmentBreach",
|
||||||
"ContainmentRadiation",
|
"ContainmentRadiation",
|
||||||
"ReactorLost",
|
"ReactorLost",
|
||||||
@ -132,7 +139,7 @@ types.alarm_string = {
|
|||||||
"TurbineTrip"
|
"TurbineTrip"
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias ALARM_PRIORITY integer
|
---@enum ALARM_PRIORITY
|
||||||
types.ALARM_PRIORITY = {
|
types.ALARM_PRIORITY = {
|
||||||
CRITICAL = 0,
|
CRITICAL = 0,
|
||||||
EMERGENCY = 1,
|
EMERGENCY = 1,
|
||||||
@ -140,30 +147,14 @@ types.ALARM_PRIORITY = {
|
|||||||
TIMELY = 3
|
TIMELY = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
types.alarm_prio_string = {
|
types.ALARM_PRIORITY_NAMES = {
|
||||||
"CRITICAL",
|
"CRITICAL",
|
||||||
"EMERGENCY",
|
"EMERGENCY",
|
||||||
"URGENT",
|
"URGENT",
|
||||||
"TIMELY"
|
"TIMELY"
|
||||||
}
|
}
|
||||||
|
|
||||||
-- map alarms to alarm priority
|
---@enum ALARM_STATE
|
||||||
types.ALARM_PRIO_MAP = {
|
|
||||||
types.ALARM_PRIORITY.CRITICAL,
|
|
||||||
types.ALARM_PRIORITY.CRITICAL,
|
|
||||||
types.ALARM_PRIORITY.URGENT,
|
|
||||||
types.ALARM_PRIORITY.CRITICAL,
|
|
||||||
types.ALARM_PRIORITY.EMERGENCY,
|
|
||||||
types.ALARM_PRIORITY.EMERGENCY,
|
|
||||||
types.ALARM_PRIORITY.TIMELY,
|
|
||||||
types.ALARM_PRIORITY.EMERGENCY,
|
|
||||||
types.ALARM_PRIORITY.TIMELY,
|
|
||||||
types.ALARM_PRIORITY.URGENT,
|
|
||||||
types.ALARM_PRIORITY.TIMELY,
|
|
||||||
types.ALARM_PRIORITY.URGENT
|
|
||||||
}
|
|
||||||
|
|
||||||
---@alias ALARM_STATE integer
|
|
||||||
types.ALARM_STATE = {
|
types.ALARM_STATE = {
|
||||||
INACTIVE = 0,
|
INACTIVE = 0,
|
||||||
TRIPPED = 1,
|
TRIPPED = 1,
|
||||||
@ -171,7 +162,10 @@ types.ALARM_STATE = {
|
|||||||
RING_BACK = 3
|
RING_BACK = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--#endregion
|
||||||
|
|
||||||
-- STRING TYPES --
|
-- STRING TYPES --
|
||||||
|
--#region
|
||||||
|
|
||||||
---@alias os_event
|
---@alias os_event
|
||||||
---| "alarm"
|
---| "alarm"
|
||||||
@ -206,21 +200,7 @@ types.ALARM_STATE = {
|
|||||||
---| "websocket_failure"
|
---| "websocket_failure"
|
||||||
---| "websocket_message"
|
---| "websocket_message"
|
||||||
---| "websocket_success"
|
---| "websocket_success"
|
||||||
|
---| "clock_start" custom, added for reactor PLC
|
||||||
---@alias rps_trip_cause
|
|
||||||
---| "ok"
|
|
||||||
---| "dmg_crit"
|
|
||||||
---| "high_temp"
|
|
||||||
---| "no_coolant"
|
|
||||||
---| "full_waste"
|
|
||||||
---| "heated_coolant_backup"
|
|
||||||
---| "no_fuel"
|
|
||||||
---| "fault"
|
|
||||||
---| "timeout"
|
|
||||||
---| "manual"
|
|
||||||
---| "automatic"
|
|
||||||
---| "sys_fail"
|
|
||||||
---| "force_disabled"
|
|
||||||
|
|
||||||
---@alias fluid
|
---@alias fluid
|
||||||
---| "mekanism:empty_gas"
|
---| "mekanism:empty_gas"
|
||||||
@ -246,6 +226,21 @@ types.rtu_t = {
|
|||||||
env_detector = "environment_detector"
|
env_detector = "environment_detector"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@alias rps_trip_cause
|
||||||
|
---| "ok"
|
||||||
|
---| "dmg_crit"
|
||||||
|
---| "high_temp"
|
||||||
|
---| "no_coolant"
|
||||||
|
---| "full_waste"
|
||||||
|
---| "heated_coolant_backup"
|
||||||
|
---| "no_fuel"
|
||||||
|
---| "fault"
|
||||||
|
---| "timeout"
|
||||||
|
---| "manual"
|
||||||
|
---| "automatic"
|
||||||
|
---| "sys_fail"
|
||||||
|
---| "force_disabled"
|
||||||
|
|
||||||
---@alias rps_status_t rps_trip_cause
|
---@alias rps_status_t rps_trip_cause
|
||||||
types.rps_status_t = {
|
types.rps_status_t = {
|
||||||
ok = "ok",
|
ok = "ok",
|
||||||
@ -263,18 +258,24 @@ types.rps_status_t = {
|
|||||||
force_disabled = "force_disabled"
|
force_disabled = "force_disabled"
|
||||||
}
|
}
|
||||||
|
|
||||||
-- turbine steam dumping modes
|
---@alias DUMPING_MODE
|
||||||
---@alias DUMPING_MODE string
|
---| "IDLE"
|
||||||
|
---| "DUMPING"
|
||||||
|
---| "DUMPING_EXCESS"
|
||||||
|
|
||||||
types.DUMPING_MODE = {
|
types.DUMPING_MODE = {
|
||||||
IDLE = "IDLE",
|
IDLE = "IDLE",
|
||||||
DUMPING = "DUMPING",
|
DUMPING = "DUMPING",
|
||||||
DUMPING_EXCESS = "DUMPING_EXCESS"
|
DUMPING_EXCESS = "DUMPING_EXCESS"
|
||||||
}
|
}
|
||||||
|
|
||||||
-- MODBUS
|
--#endregion
|
||||||
|
|
||||||
-- modbus function codes
|
-- MODBUS --
|
||||||
---@alias MODBUS_FCODE integer
|
--#region
|
||||||
|
|
||||||
|
-- MODBUS function codes
|
||||||
|
---@enum MODBUS_FCODE
|
||||||
types.MODBUS_FCODE = {
|
types.MODBUS_FCODE = {
|
||||||
READ_COILS = 0x01,
|
READ_COILS = 0x01,
|
||||||
READ_DISCRETE_INPUTS = 0x02,
|
READ_DISCRETE_INPUTS = 0x02,
|
||||||
@ -287,8 +288,8 @@ types.MODBUS_FCODE = {
|
|||||||
ERROR_FLAG = 0x80
|
ERROR_FLAG = 0x80
|
||||||
}
|
}
|
||||||
|
|
||||||
-- modbus exception codes
|
-- MODBUS exception codes
|
||||||
---@alias MODBUS_EXCODE integer
|
---@enum MODBUS_EXCODE
|
||||||
types.MODBUS_EXCODE = {
|
types.MODBUS_EXCODE = {
|
||||||
ILLEGAL_FUNCTION = 0x01,
|
ILLEGAL_FUNCTION = 0x01,
|
||||||
ILLEGAL_DATA_ADDR = 0x02,
|
ILLEGAL_DATA_ADDR = 0x02,
|
||||||
@ -302,4 +303,6 @@ types.MODBUS_EXCODE = {
|
|||||||
GATEWAY_TARGET_TIMEOUT = 0x0B
|
GATEWAY_TARGET_TIMEOUT = 0x0B
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--#endregion
|
||||||
|
|
||||||
return types
|
return types
|
||||||
|
@ -14,6 +14,7 @@ util.TICK_TIME_MS = 50
|
|||||||
--#region
|
--#region
|
||||||
|
|
||||||
-- trinary operator
|
-- trinary operator
|
||||||
|
---@nodiscard
|
||||||
---@param cond boolean|nil condition
|
---@param cond boolean|nil condition
|
||||||
---@param a any return if true
|
---@param a any return if true
|
||||||
---@param b any return if false
|
---@param b any return if false
|
||||||
@ -57,6 +58,7 @@ end
|
|||||||
--#region
|
--#region
|
||||||
|
|
||||||
-- get a value as a string
|
-- get a value as a string
|
||||||
|
---@nodiscard
|
||||||
---@param val any
|
---@param val any
|
||||||
---@return string
|
---@return string
|
||||||
function util.strval(val)
|
function util.strval(val)
|
||||||
@ -69,6 +71,7 @@ function util.strval(val)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- repeat a string n times
|
-- repeat a string n times
|
||||||
|
---@nodiscard
|
||||||
---@param str string
|
---@param str string
|
||||||
---@param n integer
|
---@param n integer
|
||||||
---@return string
|
---@return string
|
||||||
@ -81,6 +84,7 @@ function util.strrep(str, n)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- repeat a space n times
|
-- repeat a space n times
|
||||||
|
---@nodiscard
|
||||||
---@param n integer
|
---@param n integer
|
||||||
---@return string
|
---@return string
|
||||||
function util.spaces(n)
|
function util.spaces(n)
|
||||||
@ -88,6 +92,7 @@ function util.spaces(n)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- pad text to a minimum width
|
-- pad text to a minimum width
|
||||||
|
---@nodiscard
|
||||||
---@param str string text
|
---@param str string text
|
||||||
---@param n integer minimum width
|
---@param n integer minimum width
|
||||||
---@return string
|
---@return string
|
||||||
@ -100,6 +105,7 @@ function util.pad(str, n)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- wrap a string into a table of lines, supporting single dash splits
|
-- wrap a string into a table of lines, supporting single dash splits
|
||||||
|
---@nodiscard
|
||||||
---@param str string
|
---@param str string
|
||||||
---@param limit integer line limit
|
---@param limit integer line limit
|
||||||
---@return table lines
|
---@return table lines
|
||||||
@ -147,13 +153,12 @@ function util.strwrap(str, limit)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- concatenation with built-in to string
|
-- concatenation with built-in to string
|
||||||
|
---@nodiscard
|
||||||
---@vararg any
|
---@vararg any
|
||||||
---@return string
|
---@return string
|
||||||
function util.concat(...)
|
function util.concat(...)
|
||||||
local str = ""
|
local str = ""
|
||||||
for _, v in ipairs(arg) do
|
for _, v in ipairs(arg) do str = str .. util.strval(v) end
|
||||||
str = str .. util.strval(v)
|
|
||||||
end
|
|
||||||
return str
|
return str
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -161,15 +166,16 @@ end
|
|||||||
util.c = util.concat
|
util.c = util.concat
|
||||||
|
|
||||||
-- sprintf implementation
|
-- sprintf implementation
|
||||||
|
---@nodiscard
|
||||||
---@param format string
|
---@param format string
|
||||||
---@vararg any
|
---@vararg any
|
||||||
function util.sprintf(format, ...)
|
function util.sprintf(format, ...)
|
||||||
return string.format(format, table.unpack(arg))
|
return string.format(format, table.unpack(arg))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- format a number string with commas as the thousands separator
|
-- format a number string with commas as the thousands separator<br>
|
||||||
--
|
|
||||||
-- subtracts from spaces at the start if present for each comma used
|
-- subtracts from spaces at the start if present for each comma used
|
||||||
|
---@nodiscard
|
||||||
---@param num string number string
|
---@param num string number string
|
||||||
---@return string
|
---@return string
|
||||||
function util.comma_format(num)
|
function util.comma_format(num)
|
||||||
@ -196,6 +202,7 @@ end
|
|||||||
--#region
|
--#region
|
||||||
|
|
||||||
-- is a value an integer
|
-- is a value an integer
|
||||||
|
---@nodiscard
|
||||||
---@param x any value
|
---@param x any value
|
||||||
---@return boolean is_integer if the number is an integer
|
---@return boolean is_integer if the number is an integer
|
||||||
function util.is_int(x)
|
function util.is_int(x)
|
||||||
@ -203,6 +210,7 @@ function util.is_int(x)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- get the sign of a number
|
-- get the sign of a number
|
||||||
|
---@nodiscard
|
||||||
---@param x number value
|
---@param x number value
|
||||||
---@return integer sign (-1 for < 0, 1 otherwise)
|
---@return integer sign (-1 for < 0, 1 otherwise)
|
||||||
function util.sign(x)
|
function util.sign(x)
|
||||||
@ -210,12 +218,14 @@ function util.sign(x)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- round a number to an integer
|
-- round a number to an integer
|
||||||
|
---@nodiscard
|
||||||
---@return integer rounded
|
---@return integer rounded
|
||||||
function util.round(x)
|
function util.round(x)
|
||||||
return math.floor(x + 0.5)
|
return math.floor(x + 0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get a new moving average object
|
-- get a new moving average object
|
||||||
|
---@nodiscard
|
||||||
---@param length integer history length
|
---@param length integer history length
|
||||||
---@param default number value to fill history with for first call to compute()
|
---@param default number value to fill history with for first call to compute()
|
||||||
function util.mov_avg(length, default)
|
function util.mov_avg(length, default)
|
||||||
@ -249,6 +259,7 @@ function util.mov_avg(length, default)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- compute the moving average
|
-- compute the moving average
|
||||||
|
---@nodiscard
|
||||||
---@return number average
|
---@return number average
|
||||||
function public.compute()
|
function public.compute()
|
||||||
local sum = 0
|
local sum = 0
|
||||||
@ -264,6 +275,7 @@ end
|
|||||||
-- TIME --
|
-- TIME --
|
||||||
|
|
||||||
-- current time
|
-- current time
|
||||||
|
---@nodiscard
|
||||||
---@return integer milliseconds
|
---@return integer milliseconds
|
||||||
function util.time_ms()
|
function util.time_ms()
|
||||||
---@diagnostic disable-next-line: undefined-field
|
---@diagnostic disable-next-line: undefined-field
|
||||||
@ -271,6 +283,7 @@ function util.time_ms()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- current time
|
-- current time
|
||||||
|
---@nodiscard
|
||||||
---@return number seconds
|
---@return number seconds
|
||||||
function util.time_s()
|
function util.time_s()
|
||||||
---@diagnostic disable-next-line: undefined-field
|
---@diagnostic disable-next-line: undefined-field
|
||||||
@ -278,10 +291,9 @@ function util.time_s()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- current time
|
-- current time
|
||||||
|
---@nodiscard
|
||||||
---@return integer milliseconds
|
---@return integer milliseconds
|
||||||
function util.time()
|
function util.time() return util.time_ms() end
|
||||||
return util.time_ms()
|
|
||||||
end
|
|
||||||
|
|
||||||
--#endregion
|
--#endregion
|
||||||
|
|
||||||
@ -289,6 +301,7 @@ end
|
|||||||
--#region
|
--#region
|
||||||
|
|
||||||
-- OS pull event raw wrapper with types
|
-- OS pull event raw wrapper with types
|
||||||
|
---@nodiscard
|
||||||
---@param target_event? string event to wait for
|
---@param target_event? string event to wait for
|
||||||
---@return os_event event, any param1, any param2, any param3, any param4, any param5
|
---@return os_event event, any param1, any param2, any param3, any param4, any param5
|
||||||
function util.pull_event(target_event)
|
function util.pull_event(target_event)
|
||||||
@ -309,6 +322,7 @@ function util.push_event(event, param1, param2, param3, param4, param5)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- start an OS timer
|
-- start an OS timer
|
||||||
|
---@nodiscard
|
||||||
---@param t number timer duration in seconds
|
---@param t number timer duration in seconds
|
||||||
---@return integer timer ID
|
---@return integer timer ID
|
||||||
function util.start_timer(t)
|
function util.start_timer(t)
|
||||||
@ -336,14 +350,12 @@ function util.psleep(t)
|
|||||||
pcall(os.sleep, t)
|
pcall(os.sleep, t)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- no-op to provide a brief pause (1 tick) to yield
|
-- no-op to provide a brief pause (1 tick) to yield<br>
|
||||||
---
|
|
||||||
--- EVENT_CONSUMER: this function consumes events
|
--- EVENT_CONSUMER: this function consumes events
|
||||||
function util.nop()
|
function util.nop() util.psleep(0.05) end
|
||||||
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)
|
||||||
|
---@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
|
||||||
---@return integer time_now
|
---@return integer time_now
|
||||||
@ -351,9 +363,7 @@ end
|
|||||||
function util.adaptive_delay(target_timing, last_update)
|
function util.adaptive_delay(target_timing, last_update)
|
||||||
local sleep_for = target_timing - (util.time() - last_update)
|
local sleep_for = target_timing - (util.time() - last_update)
|
||||||
-- only if >50ms since worker loops already yield 0.05s
|
-- only if >50ms since worker loops already yield 0.05s
|
||||||
if sleep_for >= 50 then
|
if sleep_for >= 50 then util.psleep(sleep_for / 1000.0) end
|
||||||
util.psleep(sleep_for / 1000.0)
|
|
||||||
end
|
|
||||||
return util.time()
|
return util.time()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -362,8 +372,7 @@ end
|
|||||||
-- TABLE UTILITIES --
|
-- TABLE UTILITIES --
|
||||||
--#region
|
--#region
|
||||||
|
|
||||||
-- delete elements from a table if the passed function returns false when passed a table element
|
-- delete elements from a table if the passed function returns false when passed a table element<br>
|
||||||
--
|
|
||||||
-- put briefly: deletes elements that return false, keeps elements that return true
|
-- put briefly: deletes elements that return false, keeps elements that return true
|
||||||
---@param t table table to remove elements from
|
---@param t table table to remove elements from
|
||||||
---@param f function should return false to delete an element when passed the element: f(elem) = true|false
|
---@param f function should return false to delete an element when passed the element: f(elem) = true|false
|
||||||
@ -388,6 +397,7 @@ function util.filter_table(t, f, on_delete)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- check if a table contains the provided element
|
-- check if a table contains the provided element
|
||||||
|
---@nodiscard
|
||||||
---@param t table table to check
|
---@param t table table to check
|
||||||
---@param element any element to check for
|
---@param element any element to check for
|
||||||
function util.table_contains(t, element)
|
function util.table_contains(t, element)
|
||||||
@ -404,11 +414,13 @@ end
|
|||||||
--#region
|
--#region
|
||||||
|
|
||||||
-- convert Joules to FE
|
-- convert Joules to FE
|
||||||
|
---@nodiscard
|
||||||
---@param J number Joules
|
---@param J number Joules
|
||||||
---@return number FE Forge Energy
|
---@return number FE Forge Energy
|
||||||
function util.joules_to_fe(J) return (J * 0.4) end
|
function util.joules_to_fe(J) return (J * 0.4) end
|
||||||
|
|
||||||
-- convert FE to Joules
|
-- convert FE to Joules
|
||||||
|
---@nodiscard
|
||||||
---@param FE number Forge Energy
|
---@param FE number Forge Energy
|
||||||
---@return number J Joules
|
---@return number J Joules
|
||||||
function util.fe_to_joules(FE) return (FE * 2.5) end
|
function util.fe_to_joules(FE) return (FE * 2.5) end
|
||||||
@ -418,10 +430,11 @@ local function MFE(fe) return fe / 1000000.0 end
|
|||||||
local function GFE(fe) return fe / 1000000000.0 end
|
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 -- please stop
|
||||||
|
|
||||||
-- 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
|
||||||
---@param fe number forge energy value
|
---@param fe number forge energy value
|
||||||
---@param combine_label? boolean if a label should be included in the string itself
|
---@param combine_label? boolean if a label should be included in the string itself
|
||||||
---@param format? string format override
|
---@param format? string format override
|
||||||
@ -430,9 +443,7 @@ function util.power_format(fe, combine_label, format)
|
|||||||
local unit
|
local unit
|
||||||
local value
|
local value
|
||||||
|
|
||||||
if type(format) ~= "string" then
|
if type(format) ~= "string" then format = "%.2f" end
|
||||||
format = "%.2f"
|
|
||||||
end
|
|
||||||
|
|
||||||
if fe < 1000.0 then
|
if fe < 1000.0 then
|
||||||
unit = "FE"
|
unit = "FE"
|
||||||
@ -474,10 +485,10 @@ end
|
|||||||
|
|
||||||
-- WATCHDOG --
|
-- WATCHDOG --
|
||||||
|
|
||||||
-- ComputerCraft OS Timer based Watchdog
|
-- OS timer based watchdog<br>
|
||||||
|
-- triggers a timer event if not fed within 'timeout' seconds
|
||||||
|
---@nodiscard
|
||||||
---@param timeout number timeout duration
|
---@param timeout number timeout duration
|
||||||
---
|
|
||||||
--- triggers a timer event if not fed within 'timeout' seconds
|
|
||||||
function util.new_watchdog(timeout)
|
function util.new_watchdog(timeout)
|
||||||
local self = {
|
local self = {
|
||||||
timeout = timeout,
|
timeout = timeout,
|
||||||
@ -487,10 +498,10 @@ function util.new_watchdog(timeout)
|
|||||||
---@class watchdog
|
---@class watchdog
|
||||||
local public = {}
|
local public = {}
|
||||||
|
|
||||||
|
-- check if a timer is this watchdog
|
||||||
|
---@nodiscard
|
||||||
---@param timer number timer event timer ID
|
---@param timer number timer event timer ID
|
||||||
function public.is_timer(timer)
|
function public.is_timer(timer) return self.wd_timer == timer end
|
||||||
return self.wd_timer == timer
|
|
||||||
end
|
|
||||||
|
|
||||||
-- satiate the beast
|
-- satiate the beast
|
||||||
function public.feed()
|
function public.feed()
|
||||||
@ -512,10 +523,10 @@ end
|
|||||||
|
|
||||||
-- LOOP CLOCK --
|
-- LOOP CLOCK --
|
||||||
|
|
||||||
-- ComputerCraft OS Timer based Loop Clock
|
-- OS timer based loop clock<br>
|
||||||
|
-- fires a timer event at the specified period, does not start at construct time
|
||||||
|
---@nodiscard
|
||||||
---@param period number clock period
|
---@param period number clock period
|
||||||
---
|
|
||||||
--- fires a timer event at the specified period, does not start at construct time
|
|
||||||
function util.new_clock(period)
|
function util.new_clock(period)
|
||||||
local self = {
|
local self = {
|
||||||
period = period,
|
period = period,
|
||||||
@ -525,24 +536,22 @@ function util.new_clock(period)
|
|||||||
---@class clock
|
---@class clock
|
||||||
local public = {}
|
local public = {}
|
||||||
|
|
||||||
|
-- check if a timer is this clock
|
||||||
|
---@nodiscard
|
||||||
---@param timer number timer event timer ID
|
---@param timer number timer event timer ID
|
||||||
function public.is_clock(timer)
|
function public.is_clock(timer) return self.timer == timer end
|
||||||
return self.timer == timer
|
|
||||||
end
|
|
||||||
|
|
||||||
-- start the clock
|
-- start the clock
|
||||||
function public.start()
|
function public.start() self.timer = util.start_timer(self.period) end
|
||||||
self.timer = util.start_timer(self.period)
|
|
||||||
end
|
|
||||||
|
|
||||||
return public
|
return public
|
||||||
end
|
end
|
||||||
|
|
||||||
-- FIELD VALIDATOR --
|
-- FIELD VALIDATOR --
|
||||||
|
|
||||||
-- create a new type validator
|
-- create a new type validator<br>
|
||||||
--
|
|
||||||
-- can execute sequential checks and check valid() to see if it is still valid
|
-- can execute sequential checks and check valid() to see if it is still valid
|
||||||
|
---@nodiscard
|
||||||
function util.new_validator()
|
function util.new_validator()
|
||||||
local valid = true
|
local valid = true
|
||||||
|
|
||||||
@ -565,6 +574,8 @@ function util.new_validator()
|
|||||||
|
|
||||||
function public.assert_port(port) valid = valid and type(port) == "number" and port >= 0 and port <= 65535 end
|
function public.assert_port(port) valid = valid and type(port) == "number" and port >= 0 and port <= 65535 end
|
||||||
|
|
||||||
|
-- check if all assertions passed successfully
|
||||||
|
---@nodiscard
|
||||||
function public.valid() return valid end
|
function public.valid() return valid end
|
||||||
|
|
||||||
return public
|
return public
|
||||||
|
@ -367,8 +367,8 @@ local function _update_alarm_state(self, tripped, alarm)
|
|||||||
else
|
else
|
||||||
alarm.state = AISTATE.TRIPPED
|
alarm.state = AISTATE.TRIPPED
|
||||||
self.db.alarm_states[alarm.id] = ALARM_STATE.TRIPPED
|
self.db.alarm_states[alarm.id] = ALARM_STATE.TRIPPED
|
||||||
log.info(util.c("UNIT ", self.r_id, " ALARM ", alarm.id, " (", types.alarm_string[alarm.id], "): TRIPPED [PRIORITY ",
|
log.info(util.c("UNIT ", self.r_id, " ALARM ", alarm.id, " (", types.ALARM_NAMES[alarm.id], "): TRIPPED [PRIORITY ",
|
||||||
types.alarm_prio_string[alarm.tier + 1],"]"))
|
types.ALARM_PRIORITY_NAMES[alarm.tier + 1],"]"))
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
alarm.trip_time = util.time_ms()
|
alarm.trip_time = util.time_ms()
|
||||||
@ -381,8 +381,8 @@ local function _update_alarm_state(self, tripped, alarm)
|
|||||||
if elapsed > (alarm.hold_time * 1000) then
|
if elapsed > (alarm.hold_time * 1000) then
|
||||||
alarm.state = AISTATE.TRIPPED
|
alarm.state = AISTATE.TRIPPED
|
||||||
self.db.alarm_states[alarm.id] = ALARM_STATE.TRIPPED
|
self.db.alarm_states[alarm.id] = ALARM_STATE.TRIPPED
|
||||||
log.info(util.c("UNIT ", self.r_id, " ALARM ", alarm.id, " (", types.alarm_string[alarm.id], "): TRIPPED [PRIORITY ",
|
log.info(util.c("UNIT ", self.r_id, " ALARM ", alarm.id, " (", types.ALARM_NAMES[alarm.id], "): TRIPPED [PRIORITY ",
|
||||||
types.alarm_prio_string[alarm.tier + 1],"]"))
|
types.ALARM_PRIORITY_NAMES[alarm.tier + 1],"]"))
|
||||||
end
|
end
|
||||||
elseif int_state == AISTATE.RING_BACK_TRIPPING then
|
elseif int_state == AISTATE.RING_BACK_TRIPPING then
|
||||||
alarm.trip_time = 0
|
alarm.trip_time = 0
|
||||||
@ -432,7 +432,7 @@ local function _update_alarm_state(self, tripped, alarm)
|
|||||||
-- check for state change
|
-- check for state change
|
||||||
if alarm.state ~= int_state then
|
if alarm.state ~= int_state then
|
||||||
local change_str = util.c(aistate_string[int_state + 1], " -> ", aistate_string[alarm.state + 1])
|
local change_str = util.c(aistate_string[int_state + 1], " -> ", aistate_string[alarm.state + 1])
|
||||||
log.debug(util.c("UNIT ", self.r_id, " ALARM ", alarm.id, " (", types.alarm_string[alarm.id], "): ", change_str))
|
log.debug(util.c("UNIT ", self.r_id, " ALARM ", alarm.id, " (", types.ALARM_NAMES[alarm.id], "): ", change_str))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -530,8 +530,8 @@ function logic.update_auto_safety(public, self)
|
|||||||
for _, alarm in pairs(self.alarms) do
|
for _, alarm in pairs(self.alarms) do
|
||||||
if alarm.tier <= PRIO.URGENT and (alarm.state == AISTATE.TRIPPED or alarm.state == AISTATE.ACKED) then
|
if alarm.tier <= PRIO.URGENT and (alarm.state == AISTATE.TRIPPED or alarm.state == AISTATE.ACKED) then
|
||||||
if not self.auto_was_alarmed then
|
if not self.auto_was_alarmed then
|
||||||
log.info(util.c("UNIT ", self.r_id, " AUTO SCRAM due to ALARM ", alarm.id, " (", types.alarm_string[alarm.id], ") [PRIORITY ",
|
log.info(util.c("UNIT ", self.r_id, " AUTO SCRAM due to ALARM ", alarm.id, " (", types.ALARM_NAMES[alarm.id], ") [PRIORITY ",
|
||||||
types.alarm_prio_string[alarm.tier + 1],"]"))
|
types.ALARM_PRIORITY_NAMES[alarm.tier + 1],"]"))
|
||||||
end
|
end
|
||||||
|
|
||||||
alarmed = true
|
alarmed = true
|
||||||
|
Loading…
Reference in New Issue
Block a user