#431 handle ppm mount of unformed reactor race condition
This commit is contained in:
@@ -129,6 +129,21 @@ function plc.rps_init(reactor, is_formed)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- check if the result of a peripheral call was OK, handle the failure if not
|
||||||
|
---@nodiscard
|
||||||
|
---@param result any PPM function call result
|
||||||
|
---@return boolean succeeded if the result is OK, false if it was a PPM failure
|
||||||
|
local function _check_and_handle_ppm_call(result)
|
||||||
|
if result == ppm.ACCESS_FAULT then
|
||||||
|
_set_fault()
|
||||||
|
elseif result == ppm.UNDEFINED_FIELD then
|
||||||
|
_set_fault()
|
||||||
|
self.formed = false
|
||||||
|
else return true end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
-- set emergency coolant control (if configured)
|
-- set emergency coolant control (if configured)
|
||||||
---@param state boolean true to enable emergency coolant, false to disable
|
---@param state boolean true to enable emergency coolant, false to disable
|
||||||
local function _set_emer_cool(state)
|
local function _set_emer_cool(state)
|
||||||
@@ -167,25 +182,20 @@ function plc.rps_init(reactor, is_formed)
|
|||||||
-- check if the reactor is formed
|
-- check if the reactor is formed
|
||||||
local function _is_formed()
|
local function _is_formed()
|
||||||
local formed = reactor.isFormed()
|
local formed = reactor.isFormed()
|
||||||
if formed == ppm.ACCESS_FAULT then
|
if _check_and_handle_ppm_call(formed) then
|
||||||
-- lost the peripheral or terminated, handled later
|
|
||||||
_set_fault()
|
|
||||||
else
|
|
||||||
self.formed = formed
|
self.formed = formed
|
||||||
|
end
|
||||||
|
|
||||||
if not self.state[state_keys.sys_fail] then
|
-- always update, since some ppm failures constitute not being formed
|
||||||
self.state[state_keys.sys_fail] = not formed
|
if not self.state[state_keys.sys_fail] then
|
||||||
end
|
self.state[state_keys.sys_fail] = not self.formed
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check if the reactor is force disabled
|
-- check if the reactor is force disabled
|
||||||
local function _is_force_disabled()
|
local function _is_force_disabled()
|
||||||
local disabled = reactor.isForceDisabled()
|
local disabled = reactor.isForceDisabled()
|
||||||
if disabled == ppm.ACCESS_FAULT then
|
if _check_and_handle_ppm_call(disabled) then
|
||||||
-- lost the peripheral or terminated, handled later
|
|
||||||
_set_fault()
|
|
||||||
else
|
|
||||||
self.force_disabled = disabled
|
self.force_disabled = disabled
|
||||||
|
|
||||||
if not self.state[state_keys.force_disabled] then
|
if not self.state[state_keys.force_disabled] then
|
||||||
@@ -197,22 +207,16 @@ function plc.rps_init(reactor, is_formed)
|
|||||||
-- check for high damage
|
-- check for high damage
|
||||||
local function _high_damage()
|
local function _high_damage()
|
||||||
local damage_percent = reactor.getDamagePercent()
|
local damage_percent = reactor.getDamagePercent()
|
||||||
if damage_percent == ppm.ACCESS_FAULT then
|
if _check_and_handle_ppm_call(damage_percent) and not self.state[state_keys.high_dmg] then
|
||||||
-- lost the peripheral or terminated, handled later
|
|
||||||
_set_fault()
|
|
||||||
elseif not self.state[state_keys.high_dmg] then
|
|
||||||
self.state[state_keys.high_dmg] = damage_percent >= RPS_LIMITS.MAX_DAMAGE_PERCENT
|
self.state[state_keys.high_dmg] = damage_percent >= RPS_LIMITS.MAX_DAMAGE_PERCENT
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check if the reactor is at a critically high temperature
|
-- check if the reactor is at a critically high temperature
|
||||||
local function _high_temp()
|
local function _high_temp()
|
||||||
-- mekanism: MAX_DAMAGE_TEMPERATURE = 1_200
|
-- mekanism: MAX_DAMAGE_TEMPERATURE = 1200K
|
||||||
local temp = reactor.getTemperature()
|
local temp = reactor.getTemperature()
|
||||||
if temp == ppm.ACCESS_FAULT then
|
if _check_and_handle_ppm_call(temp) and not self.state[state_keys.high_temp] then
|
||||||
-- lost the peripheral or terminated, handled later
|
|
||||||
_set_fault()
|
|
||||||
elseif not self.state[state_keys.high_temp] then
|
|
||||||
self.state[state_keys.high_temp] = temp >= RPS_LIMITS.MAX_DAMAGE_TEMPERATURE
|
self.state[state_keys.high_temp] = temp >= RPS_LIMITS.MAX_DAMAGE_TEMPERATURE
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -220,10 +224,7 @@ function plc.rps_init(reactor, is_formed)
|
|||||||
-- check if there is very low coolant
|
-- check if there is very low coolant
|
||||||
local function _low_coolant()
|
local function _low_coolant()
|
||||||
local coolant_filled = reactor.getCoolantFilledPercentage()
|
local coolant_filled = reactor.getCoolantFilledPercentage()
|
||||||
if coolant_filled == ppm.ACCESS_FAULT then
|
if _check_and_handle_ppm_call(coolant_filled) and not self.state[state_keys.low_coolant] then
|
||||||
-- lost the peripheral or terminated, handled later
|
|
||||||
_set_fault()
|
|
||||||
elseif not self.state[state_keys.low_coolant] then
|
|
||||||
self.state[state_keys.low_coolant] = coolant_filled < RPS_LIMITS.MIN_COOLANT_FILL
|
self.state[state_keys.low_coolant] = coolant_filled < RPS_LIMITS.MIN_COOLANT_FILL
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -231,10 +232,7 @@ function plc.rps_init(reactor, is_formed)
|
|||||||
-- check for excess waste (>80% filled)
|
-- check for excess waste (>80% filled)
|
||||||
local function _excess_waste()
|
local function _excess_waste()
|
||||||
local w_filled = reactor.getWasteFilledPercentage()
|
local w_filled = reactor.getWasteFilledPercentage()
|
||||||
if w_filled == ppm.ACCESS_FAULT then
|
if _check_and_handle_ppm_call(w_filled) and not self.state[state_keys.ex_waste] then
|
||||||
-- lost the peripheral or terminated, handled later
|
|
||||||
_set_fault()
|
|
||||||
elseif not self.state[state_keys.ex_waste] then
|
|
||||||
self.state[state_keys.ex_waste] = w_filled > RPS_LIMITS.MAX_WASTE_FILL
|
self.state[state_keys.ex_waste] = w_filled > RPS_LIMITS.MAX_WASTE_FILL
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -242,10 +240,7 @@ function plc.rps_init(reactor, is_formed)
|
|||||||
-- check for heated coolant backup (>95% filled)
|
-- check for heated coolant backup (>95% filled)
|
||||||
local function _excess_heated_coolant()
|
local function _excess_heated_coolant()
|
||||||
local hc_filled = reactor.getHeatedCoolantFilledPercentage()
|
local hc_filled = reactor.getHeatedCoolantFilledPercentage()
|
||||||
if hc_filled == ppm.ACCESS_FAULT then
|
if _check_and_handle_ppm_call(hc_filled) and not self.state[state_keys.ex_hcoolant] then
|
||||||
-- lost the peripheral or terminated, handled later
|
|
||||||
_set_fault()
|
|
||||||
elseif not self.state[state_keys.ex_hcoolant] then
|
|
||||||
self.state[state_keys.ex_hcoolant] = hc_filled > RPS_LIMITS.MAX_HEATED_COLLANT_FILL
|
self.state[state_keys.ex_hcoolant] = hc_filled > RPS_LIMITS.MAX_HEATED_COLLANT_FILL
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -253,10 +248,7 @@ function plc.rps_init(reactor, is_formed)
|
|||||||
-- check if there is no fuel
|
-- check if there is no fuel
|
||||||
local function _insufficient_fuel()
|
local function _insufficient_fuel()
|
||||||
local fuel = reactor.getFuelFilledPercentage()
|
local fuel = reactor.getFuelFilledPercentage()
|
||||||
if fuel == ppm.ACCESS_FAULT then
|
if _check_and_handle_ppm_call(fuel) and not self.state[state_keys.no_fuel] then
|
||||||
-- lost the peripheral or terminated, handled later
|
|
||||||
_set_fault()
|
|
||||||
elseif not self.state[state_keys.no_fuel] then
|
|
||||||
self.state[state_keys.no_fuel] = fuel <= RPS_LIMITS.NO_FUEL_FILL
|
self.state[state_keys.no_fuel] = fuel <= RPS_LIMITS.NO_FUEL_FILL
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ local plc = require("reactor-plc.plc")
|
|||||||
local renderer = require("reactor-plc.renderer")
|
local renderer = require("reactor-plc.renderer")
|
||||||
local threads = require("reactor-plc.threads")
|
local threads = require("reactor-plc.threads")
|
||||||
|
|
||||||
local R_PLC_VERSION = "v1.6.11"
|
local R_PLC_VERSION = "v1.6.12"
|
||||||
|
|
||||||
local println = util.println
|
local println = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
@@ -131,15 +131,22 @@ local function main()
|
|||||||
|
|
||||||
-- we need a reactor, can at least do some things even if it isn't formed though
|
-- we need a reactor, can at least do some things even if it isn't formed though
|
||||||
if plc_state.no_reactor then
|
if plc_state.no_reactor then
|
||||||
println("init> fission reactor not found");
|
println("init> fission reactor not found")
|
||||||
log.warning("init> no reactor on startup")
|
log.warning("init> no reactor on startup")
|
||||||
|
|
||||||
plc_state.init_ok = false
|
plc_state.init_ok = false
|
||||||
plc_state.degraded = true
|
plc_state.degraded = true
|
||||||
elseif not smem_dev.reactor.isFormed() then
|
elseif not smem_dev.reactor.isFormed() then
|
||||||
println("init> fission reactor not formed");
|
println("init> fission reactor is not formed")
|
||||||
log.warning("init> reactor logic adapter present, but reactor is not formed")
|
log.warning("init> reactor logic adapter present, but reactor is not formed")
|
||||||
|
|
||||||
|
plc_state.degraded = true
|
||||||
|
plc_state.reactor_formed = false
|
||||||
|
elseif smem_dev.reactor.getStatus() == ppm.UNDEFINED_FIELD then
|
||||||
|
-- reactor formed after ppm.mount_all was called
|
||||||
|
println("init> fission reactor was not formed")
|
||||||
|
log.warning("init> reactor reported formed, but multiblock functions are not available")
|
||||||
|
|
||||||
plc_state.degraded = true
|
plc_state.degraded = true
|
||||||
plc_state.reactor_formed = false
|
plc_state.reactor_formed = false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ local util = require("scada-common.util")
|
|||||||
local ppm = {}
|
local ppm = {}
|
||||||
|
|
||||||
local ACCESS_FAULT = nil ---@type nil
|
local ACCESS_FAULT = nil ---@type nil
|
||||||
local UNDEFINED_FIELD = "undefined field"
|
local UNDEFINED_FIELD = "__PPM_UNDEF_FIELD__"
|
||||||
local VIRTUAL_DEVICE_TYPE = "ppm_vdev"
|
local VIRTUAL_DEVICE_TYPE = "ppm_vdev"
|
||||||
|
|
||||||
ppm.ACCESS_FAULT = ACCESS_FAULT
|
ppm.ACCESS_FAULT = ACCESS_FAULT
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ local t_pack = table.pack
|
|||||||
local util = {}
|
local util = {}
|
||||||
|
|
||||||
-- scada-common version
|
-- scada-common version
|
||||||
util.version = "1.1.16"
|
util.version = "1.1.17"
|
||||||
|
|
||||||
util.TICK_TIME_S = 0.05
|
util.TICK_TIME_S = 0.05
|
||||||
util.TICK_TIME_MS = 50
|
util.TICK_TIME_MS = 50
|
||||||
|
|||||||
Reference in New Issue
Block a user