#147 possible fix for MODBUS failures on server startup
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)"))
|
||||
|
||||
Reference in New Issue
Block a user