Merge branch 'devel' of github.com:MikaylaFischler/cc-mek-scada into front-panels

This commit is contained in:
Mikayla Fischler 2023-04-08 21:51:34 -04:00
commit 527f3446a1
16 changed files with 163 additions and 32 deletions

View File

@ -3,14 +3,14 @@
--
--[[
Copyright © 2023 Mikayla Fischler
Copyright (c) 2023 Mikayla Fischler
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the Software), to deal in the Software without restriction,
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE

View File

@ -7,7 +7,7 @@ def list_files(path):
for (root, dirs, files) in os.walk(path):
for f in files:
list.append(root[2:] + "/" + f)
list.append((root[2:] + "/" + f).replace('\\','/'))
return list

View File

@ -1 +1 @@
{"versions": {"installer": "v1.0", "bootloader": "0.2", "comms": "1.4.0", "reactor-plc": "v1.0.0", "rtu": "v0.13.0", "supervisor": "v0.14.2", "coordinator": "v0.12.3", "pocket": "alpha-v0.0.0"}, "files": {"system": ["initenv.lua", "startup.lua"], "common": ["scada-common/crypto.lua", "scada-common/ppm.lua", "scada-common/comms.lua", "scada-common/psil.lua", "scada-common/tcallbackdsp.lua", "scada-common/rsio.lua", "scada-common/constants.lua", "scada-common/mqueue.lua", "scada-common/crash.lua", "scada-common/log.lua", "scada-common/types.lua", "scada-common/util.lua"], "graphics": ["graphics/element.lua", "graphics/flasher.lua", "graphics/core.lua", "graphics/elements/textbox.lua", "graphics/elements/displaybox.lua", "graphics/elements/pipenet.lua", "graphics/elements/rectangle.lua", "graphics/elements/div.lua", "graphics/elements/tiling.lua", "graphics/elements/colormap.lua", "graphics/elements/indicators/alight.lua", "graphics/elements/indicators/icon.lua", "graphics/elements/indicators/power.lua", "graphics/elements/indicators/rad.lua", "graphics/elements/indicators/state.lua", "graphics/elements/indicators/light.lua", "graphics/elements/indicators/vbar.lua", "graphics/elements/indicators/coremap.lua", "graphics/elements/indicators/data.lua", "graphics/elements/indicators/hbar.lua", "graphics/elements/indicators/trilight.lua", "graphics/elements/controls/switch_button.lua", "graphics/elements/controls/spinbox_numeric.lua", "graphics/elements/controls/hazard_button.lua", "graphics/elements/controls/push_button.lua", "graphics/elements/controls/radio_button.lua", "graphics/elements/controls/multi_button.lua", "graphics/elements/animations/waiting.lua"], "lockbox": ["lockbox/init.lua", "lockbox/LICENSE", "lockbox/kdf/pbkdf2.lua", "lockbox/util/bit.lua", "lockbox/util/array.lua", "lockbox/util/stream.lua", "lockbox/util/queue.lua", "lockbox/digest/sha2_224.lua", "lockbox/digest/sha1.lua", "lockbox/digest/sha2_256.lua", "lockbox/cipher/aes128.lua", "lockbox/cipher/aes256.lua", "lockbox/cipher/aes192.lua", "lockbox/cipher/mode/ofb.lua", "lockbox/cipher/mode/cbc.lua", "lockbox/cipher/mode/ctr.lua", "lockbox/cipher/mode/cfb.lua", "lockbox/mac/hmac.lua", "lockbox/padding/ansix923.lua", "lockbox/padding/pkcs7.lua", "lockbox/padding/zero.lua", "lockbox/padding/isoiec7816.lua"], "reactor-plc": ["reactor-plc/threads.lua", "reactor-plc/plc.lua", "reactor-plc/config.lua", "reactor-plc/startup.lua"], "rtu": ["rtu/threads.lua", "rtu/rtu.lua", "rtu/modbus.lua", "rtu/config.lua", "rtu/startup.lua", "rtu/dev/sps_rtu.lua", "rtu/dev/envd_rtu.lua", "rtu/dev/boilerv_rtu.lua", "rtu/dev/redstone_rtu.lua", "rtu/dev/sna_rtu.lua", "rtu/dev/imatrix_rtu.lua", "rtu/dev/turbinev_rtu.lua"], "supervisor": ["supervisor/supervisor.lua", "supervisor/unit.lua", "supervisor/config.lua", "supervisor/startup.lua", "supervisor/unitlogic.lua", "supervisor/facility.lua", "supervisor/session/coordinator.lua", "supervisor/session/svqtypes.lua", "supervisor/session/svsessions.lua", "supervisor/session/rtu.lua", "supervisor/session/plc.lua", "supervisor/session/rsctl.lua", "supervisor/session/rtu/boilerv.lua", "supervisor/session/rtu/txnctrl.lua", "supervisor/session/rtu/unit_session.lua", "supervisor/session/rtu/turbinev.lua", "supervisor/session/rtu/envd.lua", "supervisor/session/rtu/imatrix.lua", "supervisor/session/rtu/sps.lua", "supervisor/session/rtu/qtypes.lua", "supervisor/session/rtu/sna.lua", "supervisor/session/rtu/redstone.lua"], "coordinator": ["coordinator/coordinator.lua", "coordinator/renderer.lua", "coordinator/iocontrol.lua", "coordinator/sounder.lua", "coordinator/config.lua", "coordinator/startup.lua", "coordinator/apisessions.lua", "coordinator/process.lua", "coordinator/ui/dialog.lua", "coordinator/ui/style.lua", "coordinator/ui/layout/main_view.lua", "coordinator/ui/layout/unit_view.lua", "coordinator/ui/components/reactor.lua", "coordinator/ui/components/processctl.lua", "coordinator/ui/components/unit_overview.lua", "coordinator/ui/components/boiler.lua", "coordinator/ui/components/unit_detail.lua", "coordinator/ui/components/imatrix.lua", "coordinator/ui/components/unit_waiting.lua", "coordinator/ui/components/turbine.lua"], "pocket": ["pocket/config.lua", "pocket/startup.lua"]}, "depends": {"reactor-plc": ["system", "common"], "rtu": ["system", "common"], "supervisor": ["system", "common"], "coordinator": ["system", "common", "graphics"], "pocket": ["system", "common", "graphics"]}, "sizes": {"manifest": 4646, "system": 1982, "common": 91084, "graphics": 99858, "lockbox": 100797, "reactor-plc": 75529, "rtu": 83729, "supervisor": 275020, "coordinator": 181148, "pocket": 335}}
{"versions": {"installer": "v1.0", "bootloader": "0.2", "comms": "1.4.0", "reactor-plc": "v1.0.1", "rtu": "v0.13.1", "supervisor": "v0.14.2", "coordinator": "v0.12.3", "pocket": "alpha-v0.0.0"}, "files": {"system": ["initenv.lua", "startup.lua"], "common": ["scada-common/comms.lua", "scada-common/constants.lua", "scada-common/crash.lua", "scada-common/crypto.lua", "scada-common/log.lua", "scada-common/mqueue.lua", "scada-common/ppm.lua", "scada-common/psil.lua", "scada-common/rsio.lua", "scada-common/tcallbackdsp.lua", "scada-common/types.lua", "scada-common/util.lua"], "graphics": ["graphics/core.lua", "graphics/element.lua", "graphics/flasher.lua", "graphics/elements/colormap.lua", "graphics/elements/displaybox.lua", "graphics/elements/div.lua", "graphics/elements/pipenet.lua", "graphics/elements/rectangle.lua", "graphics/elements/textbox.lua", "graphics/elements/tiling.lua", "graphics/elements/animations/waiting.lua", "graphics/elements/controls/hazard_button.lua", "graphics/elements/controls/multi_button.lua", "graphics/elements/controls/push_button.lua", "graphics/elements/controls/radio_button.lua", "graphics/elements/controls/spinbox_numeric.lua", "graphics/elements/controls/switch_button.lua", "graphics/elements/indicators/alight.lua", "graphics/elements/indicators/coremap.lua", "graphics/elements/indicators/data.lua", "graphics/elements/indicators/hbar.lua", "graphics/elements/indicators/icon.lua", "graphics/elements/indicators/light.lua", "graphics/elements/indicators/power.lua", "graphics/elements/indicators/rad.lua", "graphics/elements/indicators/state.lua", "graphics/elements/indicators/trilight.lua", "graphics/elements/indicators/vbar.lua"], "lockbox": ["lockbox/init.lua", "lockbox/LICENSE", "lockbox/cipher/aes128.lua", "lockbox/cipher/aes192.lua", "lockbox/cipher/aes256.lua", "lockbox/cipher/mode/cbc.lua", "lockbox/cipher/mode/cfb.lua", "lockbox/cipher/mode/ctr.lua", "lockbox/cipher/mode/ofb.lua", "lockbox/digest/sha1.lua", "lockbox/digest/sha2_224.lua", "lockbox/digest/sha2_256.lua", "lockbox/kdf/pbkdf2.lua", "lockbox/mac/hmac.lua", "lockbox/padding/ansix923.lua", "lockbox/padding/isoiec7816.lua", "lockbox/padding/pkcs7.lua", "lockbox/padding/zero.lua", "lockbox/util/array.lua", "lockbox/util/bit.lua", "lockbox/util/queue.lua", "lockbox/util/stream.lua"], "reactor-plc": ["reactor-plc/config.lua", "reactor-plc/plc.lua", "reactor-plc/startup.lua", "reactor-plc/threads.lua"], "rtu": ["rtu/config.lua", "rtu/modbus.lua", "rtu/rtu.lua", "rtu/startup.lua", "rtu/threads.lua", "rtu/dev/boilerv_rtu.lua", "rtu/dev/envd_rtu.lua", "rtu/dev/imatrix_rtu.lua", "rtu/dev/redstone_rtu.lua", "rtu/dev/sna_rtu.lua", "rtu/dev/sps_rtu.lua", "rtu/dev/turbinev_rtu.lua"], "supervisor": ["supervisor/config.lua", "supervisor/facility.lua", "supervisor/startup.lua", "supervisor/supervisor.lua", "supervisor/unit.lua", "supervisor/unitlogic.lua", "supervisor/session/coordinator.lua", "supervisor/session/plc.lua", "supervisor/session/rsctl.lua", "supervisor/session/rtu.lua", "supervisor/session/svqtypes.lua", "supervisor/session/svsessions.lua", "supervisor/session/rtu/boilerv.lua", "supervisor/session/rtu/envd.lua", "supervisor/session/rtu/imatrix.lua", "supervisor/session/rtu/qtypes.lua", "supervisor/session/rtu/redstone.lua", "supervisor/session/rtu/sna.lua", "supervisor/session/rtu/sps.lua", "supervisor/session/rtu/turbinev.lua", "supervisor/session/rtu/txnctrl.lua", "supervisor/session/rtu/unit_session.lua"], "coordinator": ["coordinator/apisessions.lua", "coordinator/config.lua", "coordinator/coordinator.lua", "coordinator/iocontrol.lua", "coordinator/process.lua", "coordinator/renderer.lua", "coordinator/sounder.lua", "coordinator/startup.lua", "coordinator/ui/dialog.lua", "coordinator/ui/style.lua", "coordinator/ui/components/boiler.lua", "coordinator/ui/components/imatrix.lua", "coordinator/ui/components/processctl.lua", "coordinator/ui/components/reactor.lua", "coordinator/ui/components/turbine.lua", "coordinator/ui/components/unit_detail.lua", "coordinator/ui/components/unit_overview.lua", "coordinator/ui/components/unit_waiting.lua", "coordinator/ui/layout/main_view.lua", "coordinator/ui/layout/unit_view.lua"], "pocket": ["pocket/config.lua", "pocket/startup.lua"]}, "depends": {"reactor-plc": ["system", "common"], "rtu": ["system", "common"], "supervisor": ["system", "common"], "coordinator": ["system", "common", "graphics"], "pocket": ["system", "common", "graphics"]}, "sizes": {"manifest": 4647, "system": 2050, "common": 94425, "graphics": 103176, "lockbox": 104193, "reactor-plc": 80189, "rtu": 88644, "supervisor": 282356, "coordinator": 185569, "pocket": 351}}

View File

@ -5,6 +5,10 @@ config.NETWORKED = true
-- unique reactor ID
config.REACTOR_ID = 1
-- for offline mode, this redstone interface will turn off (open a valve)
-- when emergency coolant is needed due to low coolant
config.EMERGENCY_COOL = { side = "right", color = nil }
-- port to send packets TO server
config.SERVER_PORT = 16000
-- port to listen to incoming packets FROM server

View File

@ -1,10 +1,11 @@
local comms = require("scada-common.comms")
local const = require("scada-common.constants")
local databus = require("reactor-plc.databus")
local log = require("scada-common.log")
local ppm = require("scada-common.ppm")
local rsio = require("scada-common.rsio")
local types = require("scada-common.types")
local util = require("scada-common.util")
local databus = require("reactor-plc.databus")
local plc = {}
@ -30,7 +31,8 @@ local PCALL_START_MSG = "pcall: Reactor is already active."
---@nodiscard
---@param reactor table
---@param is_formed boolean
function plc.rps_init(reactor, is_formed)
---@param emer_cool nil|table emergency coolant configuration
function plc.rps_init(reactor, is_formed, emer_cool)
local state_keys = {
high_dmg = 1,
high_temp = 2,
@ -50,6 +52,7 @@ function plc.rps_init(reactor, is_formed)
state = { false, false, false, false, false, false, false, false, false, false, false, false },
reactor_enabled = false,
enabled_at = 0,
emer_cool_active = nil, ---@type boolean
formed = is_formed,
force_disabled = false,
tripped = false,
@ -70,6 +73,41 @@ function plc.rps_init(reactor, is_formed)
self.state[state_keys.fault] = false
end
-- set emergency coolant control (if configured)
---@param state boolean true to enable emergency coolant, false to disable
local function _set_emer_cool(state)
-- check if this was configured: if it's a table, fields have already been validated.
if type(emer_cool) == "table" then
local level = rsio.digital_write_active(rsio.IO.U_EMER_COOL, state)
if level ~= false then
if rsio.is_color(emer_cool.color) then
local output = rs.getBundledOutput(emer_cool.side)
if rsio.digital_write(level) then
output = colors.combine(output, emer_cool.color)
else
output = colors.subtract(output, emer_cool.color)
end
rs.setBundledOutput(emer_cool.side, output)
else
rs.setOutput(emer_cool.side, rsio.digital_write(level))
end
if state ~= self.emer_cool_active then
if state then
log.info("RPS: emergency coolant valve OPENED")
else
log.info("RPS: emergency coolant valve CLOSED")
end
self.emer_cool_active = state
end
end
end
end
-- check if the reactor is formed
local function _is_formed()
local formed = reactor.isFormed()
@ -344,6 +382,9 @@ function plc.rps_init(reactor, is_formed)
end
end
-- update emergency coolant control if configured
_set_emer_cool(self.state[state_keys.low_coolant])
-- report RPS status
databus.tx_rps(self.tripped, self.state)
@ -357,6 +398,8 @@ function plc.rps_init(reactor, is_formed)
function public.is_tripped() return self.tripped end
---@nodiscard
function public.get_trip_cause() return self.trip_cause end
---@nodiscard
function public.is_low_coolant() return self.states[state_keys.low_coolant] end
---@nodiscard
function public.is_active() return self.reactor_enabled end

View File

@ -9,6 +9,7 @@ local crash = require("scada-common.crash")
local log = require("scada-common.log")
local mqueue = require("scada-common.mqueue")
local ppm = require("scada-common.ppm")
local rsio = require("scada-common.rsio")
local util = require("scada-common.util")
local config = require("reactor-plc.config")
@ -17,7 +18,7 @@ local plc = require("reactor-plc.plc")
local renderer = require("reactor-plc.renderer")
local threads = require("reactor-plc.threads")
local R_PLC_VERSION = "v1.1.3"
local R_PLC_VERSION = "v1.1.4"
local print = util.print
local println = util.println
@ -42,6 +43,15 @@ cfv.assert_type_int(config.LOG_MODE)
assert(cfv.valid(), "bad config file: missing/invalid fields")
-- check emergency coolant configuration
if type(config.EMERGENCY_COOL) == "table" then
if not rsio.is_valid_side(config.EMERGENCY_COOL.side) then
assert(false, "bad config file: emergency coolant side unrecognized")
elseif config.EMERGENCY_COOL.color ~= nil and not rsio.is_color(config.EMERGENCY_COOL.color) then
assert(false, "bad config file: emergency coolant invalid redstone channel color provided")
end
end
----------------------------------------
-- log init
----------------------------------------
@ -179,7 +189,7 @@ local function main()
if plc_state.init_ok then
-- init reactor protection system
smem_sys.rps = plc.rps_init(smem_dev.reactor, plc_state.reactor_formed)
smem_sys.rps = plc.rps_init(smem_dev.reactor, plc_state.reactor_formed, config.EMERGENCY_COOL)
log.debug("init> rps init")
if __shared_memory.networked then
@ -196,6 +206,12 @@ local function main()
log.info("init> running without networking")
end
-- notify user of emergency coolant configuration status
if config.EMERGENCY_COOL ~= nil then
println("init> emergency coolant control ready")
log.info("init> running with emergency coolant control available")
end
util.push_event("clock_start")
_println_no_fp("init> completed")

View File

@ -345,7 +345,6 @@ function threads.thread__rps(smem)
rps.trip_timeout()
end
else
-- would do elseif not networked but there is no reason to do that extra operation
was_linked = true
end

View File

@ -5,9 +5,13 @@ local boilerv_rtu = {}
-- create new boiler (mek 10.1+) device
---@nodiscard
---@param boiler table
---@return rtu_device interface, boolean faulted
function boilerv_rtu.new(boiler)
local unit = rtu.init_unit()
-- disable auto fault clearing
boiler.__p_disable_afc()
-- discrete inputs --
unit.connect_di(boiler.isFormed)
@ -50,7 +54,12 @@ function boilerv_rtu.new(boiler)
-- holding registers --
-- none
return unit.interface()
-- check if any calls faulted
local faulted = boiler.__p_is_faulted()
boiler.__p_clear_fault()
boiler.__p_enable_afc()
return unit.interface(), faulted
end
return boilerv_rtu

View File

@ -5,9 +5,13 @@ local envd_rtu = {}
-- create new environment detector device
---@nodiscard
---@param envd table
---@return rtu_device interface, boolean faulted
function envd_rtu.new(envd)
local unit = rtu.init_unit()
-- disable auto fault clearing
envd.__p_disable_afc()
-- discrete inputs --
-- none
@ -21,7 +25,12 @@ function envd_rtu.new(envd)
-- holding registers --
-- none
return unit.interface()
-- check if any calls faulted
local faulted = envd.__p_is_faulted()
envd.__p_clear_fault()
envd.__p_enable_afc()
return unit.interface(), faulted
end
return envd_rtu

View File

@ -5,9 +5,13 @@ local imatrix_rtu = {}
-- create new induction matrix (mek 10.1+) device
---@nodiscard
---@param imatrix table
---@return rtu_device interface, boolean faulted
function imatrix_rtu.new(imatrix)
local unit = rtu.init_unit()
-- disable auto fault clearing
imatrix.__p_disable_afc()
-- discrete inputs --
unit.connect_di(imatrix.isFormed)
@ -37,7 +41,12 @@ function imatrix_rtu.new(imatrix)
-- holding registers --
-- none
return unit.interface()
-- check if any calls faulted
local faulted = imatrix.__p_is_faulted()
imatrix.__p_clear_fault()
imatrix.__p_enable_afc()
return unit.interface(), faulted
end
return imatrix_rtu

View File

@ -11,6 +11,7 @@ local digital_write = rsio.digital_write
-- create new redstone device
---@nodiscard
---@return rtu_rs_device interface, boolean faulted
function redstone_rtu.new()
local unit = rtu.init_unit()
@ -111,7 +112,7 @@ function redstone_rtu.new()
)
end
return public
return public, false
end
return redstone_rtu

View File

@ -5,9 +5,13 @@ local sna_rtu = {}
-- create new solar neutron activator (SNA) device
---@nodiscard
---@param sna table
---@return rtu_device interface, boolean faulted
function sna_rtu.new(sna)
local unit = rtu.init_unit()
-- disable auto fault clearing
sna.__p_disable_afc()
-- discrete inputs --
-- none
@ -32,7 +36,12 @@ function sna_rtu.new(sna)
-- holding registers --
-- none
return unit.interface()
-- check if any calls faulted
local faulted = sna.__p_is_faulted()
sna.__p_clear_fault()
sna.__p_enable_afc()
return unit.interface(), faulted
end
return sna_rtu

View File

@ -5,9 +5,13 @@ local sps_rtu = {}
-- create new super-critical phase shifter (SPS) device
---@nodiscard
---@param sps table
---@return rtu_device interface, boolean faulted
function sps_rtu.new(sps)
local unit = rtu.init_unit()
-- disable auto fault clearing
sps.__p_disable_afc()
-- discrete inputs --
unit.connect_di(sps.isFormed)
@ -42,7 +46,12 @@ function sps_rtu.new(sps)
-- holding registers --
-- none
return unit.interface()
-- check if any calls faulted
local faulted = sps.__p_is_faulted()
sps.__p_clear_fault()
sps.__p_enable_afc()
return unit.interface(), faulted
end
return sps_rtu

View File

@ -5,9 +5,13 @@ local turbinev_rtu = {}
-- create new turbine (mek 10.1+) device
---@nodiscard
---@param turbine table
---@return rtu_device interface, boolean faulted
function turbinev_rtu.new(turbine)
local unit = rtu.init_unit()
-- disable auto fault clearing
turbine.__p_disable_afc()
-- discrete inputs --
unit.connect_di(turbine.isFormed)
@ -49,7 +53,12 @@ function turbinev_rtu.new(turbine)
-- holding registers --
unit.connect_holding_reg(turbine.getDumpingMode, turbine.setDumpingMode)
return unit.interface()
-- check if any calls faulted
local faulted = turbine.__p_is_faulted()
turbine.__p_clear_fault()
turbine.__p_enable_afc()
return unit.interface(), faulted
end
return turbinev_rtu

View File

@ -25,7 +25,7 @@ local sna_rtu = require("rtu.dev.sna_rtu")
local sps_rtu = require("rtu.dev.sps_rtu")
local turbinev_rtu = require("rtu.dev.turbinev_rtu")
local RTU_VERSION = "v0.13.0"
local RTU_VERSION = "v0.13.1"
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
@ -290,8 +290,9 @@ local function main()
local type = nil ---@type string|nil
local rtu_iface = nil ---@type rtu_device
local rtu_type = nil ---@type RTU_UNIT_TYPE
local is_multiblock = false
local is_multiblock = false ---@type boolean
local formed = nil ---@type boolean|nil
local faulted = nil ---@type boolean|nil
if device == nil then
local message = util.c("configure> '", name, "' not found, using placeholder")
@ -307,7 +308,7 @@ local function main()
if type == "boilerValve" then
-- boiler multiblock
rtu_type = RTU_UNIT_TYPE.BOILER_VALVE
rtu_iface = boilerv_rtu.new(device)
rtu_iface, faulted = boilerv_rtu.new(device)
is_multiblock = true
formed = device.isFormed()
@ -319,7 +320,7 @@ local function main()
elseif type == "turbineValve" then
-- turbine multiblock
rtu_type = RTU_UNIT_TYPE.TURBINE_VALVE
rtu_iface = turbinev_rtu.new(device)
rtu_iface, faulted = turbinev_rtu.new(device)
is_multiblock = true
formed = device.isFormed()
@ -331,7 +332,7 @@ local function main()
elseif type == "inductionPort" then
-- induction matrix multiblock
rtu_type = RTU_UNIT_TYPE.IMATRIX
rtu_iface = imatrix_rtu.new(device)
rtu_iface, faulted = imatrix_rtu.new(device)
is_multiblock = true
formed = device.isFormed()
@ -343,7 +344,7 @@ local function main()
elseif type == "spsPort" then
-- SPS multiblock
rtu_type = RTU_UNIT_TYPE.SPS
rtu_iface = sps_rtu.new(device)
rtu_iface, faulted = sps_rtu.new(device)
is_multiblock = true
formed = device.isFormed()
@ -355,11 +356,11 @@ local function main()
elseif type == "solarNeutronActivator" then
-- SNA
rtu_type = RTU_UNIT_TYPE.SNA
rtu_iface = sna_rtu.new(device)
rtu_iface, _ = sna_rtu.new(device)
elseif type == "environmentDetector" then
-- advanced peripherals environment detector
rtu_type = RTU_UNIT_TYPE.ENV_DETECTOR
rtu_iface = envd_rtu.new(device)
rtu_iface, _ = envd_rtu.new(device)
elseif type == ppm.VIRTUAL_DEVICE_TYPE then
-- placeholder device
rtu_type = RTU_UNIT_TYPE.VIRTUAL
@ -391,8 +392,15 @@ local function main()
table.insert(units, rtu_unit)
if is_multiblock and not formed then
log.info(util.c("configure> device '", name, "' is not formed"))
if is_multiblock then
if not formed then
log.info(util.c("configure> device '", name, "' is not formed"))
elseif faulted then
-- sometimes there is a race condition on server boot where it reports formed, but
-- the other functions are not yet defined (that's the theory at least). mark as unformed to attempt connection later
formed = false
log.warning(util.c("configure> device '", name, "' is formed, but initialization had one or more faults: marked as unformed"))
end
end
local for_message = "facility"

View File

@ -375,37 +375,43 @@ function threads.thread__unit_comms(smem, unit)
ppm.unmount(unit.device)
local type, device = ppm.mount(iface)
local faulted = false
if device ~= nil then
if type == "boilerValve" and unit.type == RTU_UNIT_TYPE.BOILER_VALVE then
-- boiler multiblock
unit.device = device
unit.rtu = boilerv_rtu.new(device)
unit.rtu, faulted = boilerv_rtu.new(device)
unit.formed = device.isFormed()
unit.modbus_io = modbus.new(unit.rtu, true)
elseif type == "turbineValve" and unit.type == RTU_UNIT_TYPE.TURBINE_VALVE then
-- turbine multiblock
unit.device = device
unit.rtu = turbinev_rtu.new(device)
unit.rtu, faulted = turbinev_rtu.new(device)
unit.formed = device.isFormed()
unit.modbus_io = modbus.new(unit.rtu, true)
elseif type == "inductionPort" and unit.type == RTU_UNIT_TYPE.IMATRIX then
-- induction matrix multiblock
unit.device = device
unit.rtu = imatrix_rtu.new(device)
unit.rtu, faulted = imatrix_rtu.new(device)
unit.formed = device.isFormed()
unit.modbus_io = modbus.new(unit.rtu, true)
elseif type == "spsPort" and unit.type == RTU_UNIT_TYPE.SPS then
-- SPS multiblock
unit.device = device
unit.rtu = sps_rtu.new(device)
unit.rtu, faulted = sps_rtu.new(device)
unit.formed = device.isFormed()
unit.modbus_io = modbus.new(unit.rtu, true)
else
log.error("illegal remount of non-multiblock RTU attempted for " .. short_name, true)
end
rtu_comms.send_remounted(unit.uid)
if unit.formed and faulted then
-- something is still wrong = can't mark as formed yet
unit.formed = false
else
rtu_comms.send_remounted(unit.uid)
end
else
-- fully lost the peripheral now :(
log.error(util.c(unit.name, " lost (failed reconnect)"))