#4 PLC degraded start and reconnects appear to be working now, fixed prints, and bugfixes to PPM

This commit is contained in:
Mikayla Fischler 2022-04-05 17:29:27 -04:00
parent 895750ea14
commit ba1dd1b50e
2 changed files with 68 additions and 40 deletions

View File

@ -10,11 +10,17 @@ os.loadAPI("scada-common/comms.lua")
os.loadAPI("config.lua") os.loadAPI("config.lua")
os.loadAPI("plc.lua") os.loadAPI("plc.lua")
local R_PLC_VERSION = "alpha-v0.1.1" local R_PLC_VERSION = "alpha-v0.1.2"
local print = util.print
local println = util.println
local print_ts = util.print_ts local print_ts = util.print_ts
local println_ts = util.println_ts
print(">> Reactor PLC " .. R_PLC_VERSION .. " <<") log._info("========================================")
log._info("BOOTING reactor-plc.startup " .. R_PLC_VERSION)
log._info("========================================")
println(">> Reactor PLC " .. R_PLC_VERSION .. " <<")
-- mount connected devices -- mount connected devices
ppm.mount_all() ppm.mount_all()
@ -34,21 +40,21 @@ local plc_state = {
-- we need a reactor and a modem -- we need a reactor and a modem
if reactor == nil then if reactor == nil then
print_ts("Fission reactor not found. Running in a degraded state...\n"); println("boot> fission reactor not found");
log._warning("no reactor on startup") log._warning("no reactor on startup")
plc_state.init_ok = false plc_state.init_ok = false
plc_state.degraded = true plc_state.degraded = true
plc_state.no_reactor = true plc_state.no_reactor = true
end end
if networked and modem == nil then if networked and modem == nil then
println("boot> modem not found")
log._warning("no modem on startup")
if reactor ~= nil then if reactor ~= nil then
print_ts("No modem found. Disabling reactor and running in a degraded state...\n")
reactor.scram() reactor.scram()
else
print_ts("No modem found. Running in a degraded state...\n")
end end
log._warning("no modem on startup")
plc_state.init_ok = false plc_state.init_ok = false
plc_state.degraded = true plc_state.degraded = true
plc_state.no_modem = true plc_state.no_modem = true
@ -81,7 +87,7 @@ function init()
log._debug("comms init") log._debug("comms init")
-- comms watchdog, 3 second timeout -- comms watchdog, 3 second timeout
conn_watchdog = watchdog.new_watchdog(3) conn_watchdog = util.new_watchdog(3)
log._debug("conn watchdog started") log._debug("conn watchdog started")
else else
log._debug("running without networking") log._debug("running without networking")
@ -90,7 +96,10 @@ function init()
-- loop clock (10Hz, 2 ticks) -- loop clock (10Hz, 2 ticks)
loop_tick = os.startTimer(0.05) loop_tick = os.startTimer(0.05)
log._debug("loop clock started") log._debug("loop clock started")
println("boot> completed");
else else
println("boot> system in degraded state, awaiting devices...")
log._warning("booted in a degraded state, awaiting peripheral connections...") log._warning("booted in a degraded state, awaiting peripheral connections...")
end end
end end
@ -107,7 +116,7 @@ while true do
-- if it disconnected, isPowered will return nil (and error logs will get spammed at 10Hz, so disable reporting) -- if it disconnected, isPowered will return nil (and error logs will get spammed at 10Hz, so disable reporting)
-- in that case, SCRAM won't be called until it reconnects (this is the expected use of this check) -- in that case, SCRAM won't be called until it reconnects (this is the expected use of this check)
ppm.disable_reporting() ppm.disable_reporting()
if plc_state.degraded or (plc_state.scram and reactor.isPowered()) then if plc_state.scram and reactor.getStatus() then
reactor.scram() reactor.scram()
end end
ppm.enable_reporting() ppm.enable_reporting()
@ -118,12 +127,13 @@ while true do
local device = ppm.handle_unmount(param1) local device = ppm.handle_unmount(param1)
if device.type == "fissionReactor" then if device.type == "fissionReactor" then
print_ts("reactor disconnected!\n") println_ts("reactor disconnected!")
log._error("reactor disconnected!") log._error("reactor disconnected!")
plc_state.no_reactor = true plc_state.no_reactor = true
plc_state.degraded = true
-- send an alarm: plc_comms.send_alarm(ALARMS.PLC_PERI_DC) ? -- send an alarm: plc_comms.send_alarm(ALARMS.PLC_PERI_DC) ?
elseif networked and device.type == "modem" then elseif networked and device.type == "modem" then
print_ts("modem disconnected!\n") println_ts("modem disconnected!")
log._error("modem disconnected!") log._error("modem disconnected!")
plc_state.no_modem = true plc_state.no_modem = true
@ -131,44 +141,48 @@ while true do
-- try to scram reactor if it is still connected -- try to scram reactor if it is still connected
plc_state.scram = true plc_state.scram = true
if reactor.scram() then if reactor.scram() then
print_ts("successful reactor SCRAM\n") println_ts("successful reactor SCRAM")
else else
print_ts("failed reactor SCRAM\n") println_ts("failed reactor SCRAM")
end end
end end
plc_state.degraded = true plc_state.degraded = true
end end
elseif event == "peripheral" then elseif event == "peripheral" then
local device = ppm.mount(param1) local type, device = ppm.mount(param1)
if device.type == "fissionReactor" then if type == "fissionReactor" then
-- reconnected reactor -- reconnected reactor
plc_state.scram = true reactor = device
device.scram()
print_ts("reactor reconnected.\n") plc_state.scram = true
reactor.scram()
println_ts("reactor reconnected.")
log._info("reactor reconnected.") log._info("reactor reconnected.")
plc_state.no_reactor = false plc_state.no_reactor = false
if plc_state.init_ok then if plc_state.init_ok then
iss.reconnect_reactor(device) iss.reconnect_reactor(reactor)
if networked then if networked then
plc_comms.reconnect_reactor(device) plc_comms.reconnect_reactor(reactor)
end end
end end
-- determine if we are still in a degraded state -- determine if we are still in a degraded state
if not networked or get_device("modem") ~= nil then if not networked or ppm.get_device("modem") ~= nil then
plc_state.degraded = false plc_state.degraded = false
end end
elseif networked and device.type == "modem" then elseif networked and type == "modem" then
-- reconnected modem -- reconnected modem
modem = device
if plc_state.init_ok then if plc_state.init_ok then
plc_comms.reconnect_modem(device) plc_comms.reconnect_modem(modem)
end end
print_ts("modem reconnected.\n") println_ts("modem reconnected.")
log._info("modem reconnected.") log._info("modem reconnected.")
plc_state.no_modem = false plc_state.no_modem = false
@ -179,7 +193,7 @@ while true do
end end
if not plc_state.init_ok and not plc_state.degraded then if not plc_state.init_ok and not plc_state.degraded then
plc_state.init_ok = false plc_state.init_ok = true
init() init()
end end
end end
@ -191,6 +205,8 @@ while true do
if networked and iss_first then if networked and iss_first then
plc_comms.send_iss_alarm(iss_status) plc_comms.send_iss_alarm(iss_status)
end end
elseif plc_state.init_ok then
reactor.scram()
end end
-- handle event -- handle event
@ -223,20 +239,22 @@ while true do
plc_state.scram = true plc_state.scram = true
plc_comms.unlink() plc_comms.unlink()
iss.trip_timeout() iss.trip_timeout()
print_ts("[alert] server timeout, reactor disabled\n") println_ts("server timeout, reactor disabled")
log._warning("server timeout, reactor disabled")
elseif event == "terminate" then elseif event == "terminate" then
-- safe exit -- safe exit
if plc_state.init_ok then if plc_state.init_ok then
plc_state.scram = true plc_state.scram = true
if reactor.scram() then if reactor.scram() then
print_ts("[alert] exiting, reactor disabled\n") println_ts("reactor disabled")
else else
-- send an alarm: plc_comms.send_alarm(ALARMS.PLC_LOST_CONTROL) ? -- send an alarm: plc_comms.send_alarm(ALARMS.PLC_LOST_CONTROL) ?
print_ts("[alert] exiting, reactor failed to disable\n") println_ts("exiting, reactor failed to disable")
end end
end end
-- send an alarm: plc_comms.send_alarm(ALARMS.PLC_SHUTDOWN) ? -- send an alarm: plc_comms.send_alarm(ALARMS.PLC_SHUTDOWN) ?
print_ts("[alert] exited") println_ts("exited")
log._info("terminate requested, exiting")
return return
end end
end end

View File

@ -53,7 +53,13 @@ function mount_all()
for i = 1, #ifaces do for i = 1, #ifaces do
local pm_dev = peripheral.wrap(ifaces[i]) local pm_dev = peripheral.wrap(ifaces[i])
peri_init(pm_dev) peri_init(pm_dev)
self.mounts[ifaces[i]] = { peripheral.getType(ifaces[i]), pm_dev }
self.mounts[ifaces[i]] = {
type = peripheral.getType(ifaces[i]),
dev = pm_dev
}
log._debug("PPM: found a " .. self.mounts[ifaces[i]].type)
end end
if #ifaces == 0 then if #ifaces == 0 then
@ -62,24 +68,28 @@ function mount_all()
end end
-- mount a particular device -- mount a particular device
function mount(name) function mount(iface)
local ifaces = peripheral.getNames() local ifaces = peripheral.getNames()
local pm_dev = nil local pm_dev = nil
local type = nil
for i = 1, #ifaces do for i = 1, #ifaces do
if name == peripheral.getType(ifaces[i]) then if iface == ifaces[i] then
pm_dev = peripheral.wrap(ifaces[i]) log._debug("PPM: mount(" .. iface .. ") -> found a " .. peripheral.getType(iface))
type = peripheral.getType(iface)
pm_dev = peripheral.wrap(iface)
peri_init(pm_dev) peri_init(pm_dev)
self.mounts[ifaces[i]] = { self.mounts[iface] = {
type = peripheral.getType(ifaces[i]), type = peripheral.getType(iface),
device = pm_dev dev = pm_dev
} }
break break
end end
end end
return pm_dev return type, pm_dev
end end
-- handle peripheral_detach event -- handle peripheral_detach event
@ -105,7 +115,7 @@ end
-- get a mounted peripheral by side/interface -- get a mounted peripheral by side/interface
function get_periph(iface) function get_periph(iface)
return self.mounts[iface].device return self.mounts[iface].dev
end end
-- get a mounted peripheral type by side/interface -- get a mounted peripheral type by side/interface
@ -119,7 +129,7 @@ function get_device(name)
for side, data in pairs(self.mounts) do for side, data in pairs(self.mounts) do
if data.type == name then if data.type == name then
device = data.device device = data.dev
break break
end end
end end
@ -133,7 +143,7 @@ function list_monitors()
for side, data in pairs(self.mounts) do for side, data in pairs(self.mounts) do
if data.type == "monitor" then if data.type == "monitor" then
monitors[side] = data.device table.insert(monitors, data.dev)
end end
end end