mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
Merge pull request #277 from MikaylaFischler/25-process-waste-control
25 process waste control
This commit is contained in:
commit
ab193db153
@ -364,8 +364,9 @@ function coordinator.comms(version, nic, crd_channel, svr_channel, pkt_channel,
|
||||
|
||||
-- send a facility command
|
||||
---@param cmd FAC_COMMAND command
|
||||
function public.send_fac_command(cmd)
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_CMD, { cmd })
|
||||
---@param option any? optional option options for the optional options (like waste mode)
|
||||
function public.send_fac_command(cmd, option)
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_CMD, { cmd, option })
|
||||
end
|
||||
|
||||
-- send the auto process control configuration with a start command
|
||||
@ -379,7 +380,7 @@ function coordinator.comms(version, nic, crd_channel, svr_channel, pkt_channel,
|
||||
-- send a unit command
|
||||
---@param cmd UNIT_COMMAND command
|
||||
---@param unit integer unit ID
|
||||
---@param option any? optional option options for the optional options (like burn rate) (does option still look like a word?)
|
||||
---@param option any? optional option options for the optional options (like burn rate)
|
||||
function public.send_unit_command(cmd, unit, option)
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.UNIT_CMD, { cmd, unit, option })
|
||||
end
|
||||
@ -563,6 +564,10 @@ function coordinator.comms(version, nic, crd_channel, svr_channel, pkt_channel,
|
||||
end
|
||||
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
||||
iocontrol.get_db().facility.ack_alarms_ack(ack)
|
||||
elseif cmd == FAC_COMMAND.SET_WASTE_MODE then
|
||||
process.waste_ack_handle(packet.data[2])
|
||||
elseif cmd == FAC_COMMAND.SET_PU_FB then
|
||||
process.pu_fb_ack_handle(packet.data[2])
|
||||
else
|
||||
log.debug(util.c("received facility command ack with unknown command ", cmd))
|
||||
end
|
||||
|
@ -52,6 +52,10 @@ function iocontrol.init(conf, comms)
|
||||
gen_fault = false
|
||||
},
|
||||
|
||||
---@type WASTE_PRODUCT
|
||||
auto_current_waste_product = types.WASTE_PRODUCT.PLUTONIUM,
|
||||
auto_pu_fallback_active = false,
|
||||
|
||||
radiation = types.new_zero_radiation_reading(),
|
||||
|
||||
save_cfg_ack = __generic_ack,
|
||||
@ -65,16 +69,18 @@ function iocontrol.init(conf, comms)
|
||||
induction_ps_tbl = {},
|
||||
induction_data_tbl = {},
|
||||
|
||||
sps_ps_tbl = {},
|
||||
sps_data_tbl = {},
|
||||
|
||||
env_d_ps = psil.create(),
|
||||
env_d_data = {}
|
||||
}
|
||||
|
||||
-- create induction tables (currently only 1 is supported)
|
||||
for _ = 1, conf.num_units do
|
||||
local data = {} ---@type imatrix_session_db
|
||||
table.insert(io.facility.induction_ps_tbl, psil.create())
|
||||
table.insert(io.facility.induction_data_tbl, data)
|
||||
end
|
||||
-- create induction and SPS tables (currently only 1 of each is supported)
|
||||
table.insert(io.facility.induction_ps_tbl, psil.create())
|
||||
table.insert(io.facility.induction_data_tbl, {})
|
||||
table.insert(io.facility.sps_ps_tbl, psil.create())
|
||||
table.insert(io.facility.sps_data_tbl, {})
|
||||
|
||||
io.units = {}
|
||||
for i = 1, conf.num_units do
|
||||
@ -87,11 +93,15 @@ function iocontrol.init(conf, comms)
|
||||
|
||||
num_boilers = 0,
|
||||
num_turbines = 0,
|
||||
num_snas = 0,
|
||||
|
||||
control_state = false,
|
||||
burn_rate_cmd = 0.0,
|
||||
waste_control = 0,
|
||||
radiation = types.new_zero_radiation_reading(),
|
||||
sna_prod_rate = 0.0,
|
||||
|
||||
waste_mode = types.WASTE_MODE.MANUAL_PLUTONIUM,
|
||||
waste_product = types.WASTE_PRODUCT.PLUTONIUM,
|
||||
|
||||
-- auto control group
|
||||
a_group = 0,
|
||||
@ -100,10 +110,10 @@ function iocontrol.init(conf, comms)
|
||||
scram = function () process.scram(i) end,
|
||||
reset_rps = function () process.reset_rps(i) end,
|
||||
ack_alarms = function () process.ack_all_alarms(i) end,
|
||||
set_burn = function (rate) process.set_rate(i, rate) end, ---@param rate number burn rate
|
||||
set_waste = function (mode) process.set_waste(i, mode) end, ---@param mode integer waste processing mode
|
||||
set_burn = function (rate) process.set_rate(i, rate) end, ---@param rate number burn rate
|
||||
set_waste = function (mode) process.set_unit_waste(i, mode) end, ---@param mode WASTE_MODE waste processing mode
|
||||
|
||||
set_group = function (grp) process.set_group(i, grp) end, ---@param grp integer|0 group ID or 0
|
||||
set_group = function (grp) process.set_group(i, grp) end, ---@param grp integer|0 group ID or 0 for manual
|
||||
|
||||
start_ack = __generic_ack,
|
||||
scram_ack = __generic_ack,
|
||||
@ -206,6 +216,25 @@ function iocontrol.record_facility_builds(build)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- SPS
|
||||
if type(build.sps) == "table" then
|
||||
for id, sps in pairs(build.sps) do
|
||||
if type(fac.sps_data_tbl[id]) == "table" then
|
||||
fac.sps_data_tbl[id].formed = sps[1] ---@type boolean
|
||||
fac.sps_data_tbl[id].build = sps[2] ---@type table
|
||||
|
||||
fac.sps_ps_tbl[id].publish("formed", sps[1])
|
||||
|
||||
for key, val in pairs(fac.sps_data_tbl[id].build) do
|
||||
fac.sps_ps_tbl[id].publish(key, val)
|
||||
end
|
||||
else
|
||||
log.debug(util.c("iocontrol.record_facility_builds: invalid SPS id ", id))
|
||||
valid = false
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
log.debug("facility builds not a table")
|
||||
valid = false
|
||||
@ -306,7 +335,7 @@ function iocontrol.update_facility_status(status)
|
||||
|
||||
local ctl_status = status[1]
|
||||
|
||||
if type(ctl_status) == "table" and #ctl_status == 14 then
|
||||
if type(ctl_status) == "table" and #ctl_status == 16 then
|
||||
fac.all_sys_ok = ctl_status[1]
|
||||
fac.auto_ready = ctl_status[2]
|
||||
|
||||
@ -354,6 +383,12 @@ function iocontrol.update_facility_status(status)
|
||||
io.units[i].unit_ps.publish("auto_group", names[group_map[i] + 1])
|
||||
end
|
||||
end
|
||||
|
||||
fac.auto_current_waste_product = ctl_status[15]
|
||||
fac.auto_pu_fallback_active = ctl_status[16]
|
||||
|
||||
fac.ps.publish("current_waste_product", fac.auto_current_waste_product)
|
||||
fac.ps.publish("pu_fallback_active", fac.auto_pu_fallback_active)
|
||||
else
|
||||
log.debug(log_header .. "control status not a table or length mismatch")
|
||||
valid = false
|
||||
@ -430,6 +465,52 @@ function iocontrol.update_facility_status(status)
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- SPS statuses
|
||||
if type(rtu_statuses.sps) == "table" then
|
||||
for id = 1, #fac.sps_ps_tbl do
|
||||
if rtu_statuses.sps[id] == nil then
|
||||
-- disconnected
|
||||
fac.sps_ps_tbl[id].publish("computed_status", 1)
|
||||
end
|
||||
end
|
||||
|
||||
for id, sps in pairs(rtu_statuses.sps) do
|
||||
if type(fac.sps_data_tbl[id]) == "table" then
|
||||
local rtu_faulted = sps[1] ---@type boolean
|
||||
fac.sps_data_tbl[id].formed = sps[2] ---@type boolean
|
||||
fac.sps_data_tbl[id].state = sps[3] ---@type table
|
||||
fac.sps_data_tbl[id].tanks = sps[4] ---@type table
|
||||
|
||||
local data = fac.sps_data_tbl[id] ---@type sps_session_db
|
||||
|
||||
fac.sps_ps_tbl[id].publish("formed", data.formed)
|
||||
fac.sps_ps_tbl[id].publish("faulted", rtu_faulted)
|
||||
|
||||
if data.formed then
|
||||
if rtu_faulted then
|
||||
fac.sps_ps_tbl[id].publish("computed_status", 3) -- faulted
|
||||
elseif data.state.process_rate > 0 then
|
||||
fac.sps_ps_tbl[id].publish("computed_status", 5) -- active
|
||||
else
|
||||
fac.sps_ps_tbl[id].publish("computed_status", 4) -- idle
|
||||
end
|
||||
else
|
||||
fac.sps_ps_tbl[id].publish("computed_status", 2) -- not formed
|
||||
end
|
||||
|
||||
for key, val in pairs(data.state) do fac.sps_ps_tbl[id].publish(key, val) end
|
||||
for key, val in pairs(data.tanks) do fac.sps_ps_tbl[id].publish(key, val) end
|
||||
|
||||
io.facility.ps.publish("am_rate", data.state.process_rate * 1000)
|
||||
else
|
||||
log.debug(util.c(log_header, "invalid sps id ", id))
|
||||
end
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "sps list not a table")
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- environment detector status
|
||||
if type(rtu_statuses.rad_mon) == "table" then
|
||||
if #rtu_statuses.rad_mon > 0 then
|
||||
@ -472,6 +553,9 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
valid = false
|
||||
else
|
||||
local burn_rate_sum = 0.0
|
||||
local sna_count_sum = 0
|
||||
local pu_rate = 0.0
|
||||
local po_rate = 0.0
|
||||
|
||||
-- get all unit statuses
|
||||
for i = 1, #statuses do
|
||||
@ -480,6 +564,8 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
local unit = io.units[i] ---@type ioctl_unit
|
||||
local status = statuses[i]
|
||||
|
||||
local burn_rate = 0.0
|
||||
|
||||
if type(status) ~= "table" or #status ~= 5 then
|
||||
log.debug(log_header .. "invalid status entry in unit statuses (not a table or invalid length)")
|
||||
valid = false
|
||||
@ -515,7 +601,8 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
|
||||
-- if status hasn't been received, mek_status = {}
|
||||
if type(unit.reactor_data.mek_status.act_burn_rate) == "number" then
|
||||
burn_rate_sum = burn_rate_sum + unit.reactor_data.mek_status.act_burn_rate
|
||||
burn_rate = unit.reactor_data.mek_status.act_burn_rate
|
||||
burn_rate_sum = burn_rate_sum + burn_rate
|
||||
end
|
||||
|
||||
if unit.reactor_data.mek_status.status then
|
||||
@ -662,6 +749,19 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- solar neutron activator status info
|
||||
if type(rtu_statuses.sna) == "table" then
|
||||
unit.num_snas = rtu_statuses.sna[1] ---@type integer
|
||||
unit.sna_prod_rate = rtu_statuses.sna[2] ---@type number
|
||||
|
||||
unit.unit_ps.publish("sna_prod_rate", unit.sna_prod_rate)
|
||||
|
||||
sna_count_sum = sna_count_sum + unit.num_snas
|
||||
else
|
||||
log.debug(log_header .. "sna statistic list not a table")
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- environment detector status
|
||||
if type(rtu_statuses.rad_mon) == "table" then
|
||||
if #rtu_statuses.rad_mon > 0 then
|
||||
@ -739,12 +839,17 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
local unit_state = status[5]
|
||||
|
||||
if type(unit_state) == "table" then
|
||||
if #unit_state == 5 then
|
||||
if #unit_state == 6 then
|
||||
unit.waste_mode = unit_state[5]
|
||||
unit.waste_product = unit_state[6]
|
||||
|
||||
unit.unit_ps.publish("U_StatusLine1", unit_state[1])
|
||||
unit.unit_ps.publish("U_StatusLine2", unit_state[2])
|
||||
unit.unit_ps.publish("U_WasteMode", unit_state[3])
|
||||
unit.unit_ps.publish("U_AutoReady", unit_state[4])
|
||||
unit.unit_ps.publish("U_AutoDegraded", unit_state[5])
|
||||
unit.unit_ps.publish("U_AutoReady", unit_state[3])
|
||||
unit.unit_ps.publish("U_AutoDegraded", unit_state[4])
|
||||
unit.unit_ps.publish("U_AutoWaste", unit.waste_mode == types.WASTE_MODE.AUTO)
|
||||
unit.unit_ps.publish("U_WasteMode", unit.waste_mode)
|
||||
unit.unit_ps.publish("U_WasteProduct", unit.waste_product)
|
||||
else
|
||||
log.debug(log_header .. "unit state length mismatch")
|
||||
valid = false
|
||||
@ -753,10 +858,18 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
log.debug(log_header .. "unit state not a table")
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- determine waste production for this unit, add to statistics
|
||||
local is_pu = unit.waste_product == types.WASTE_PRODUCT.PLUTONIUM
|
||||
pu_rate = pu_rate + util.trinary(is_pu, burn_rate / 10.0, 0.0)
|
||||
po_rate = po_rate + util.trinary(not is_pu, math.min(burn_rate / 10.0, unit.sna_prod_rate), 0.0)
|
||||
end
|
||||
end
|
||||
|
||||
io.facility.ps.publish("burn_sum", burn_rate_sum)
|
||||
io.facility.ps.publish("sna_count", sna_count_sum)
|
||||
io.facility.ps.publish("pu_rate", pu_rate)
|
||||
io.facility.ps.publish("po_rate", po_rate)
|
||||
|
||||
-- update alarm sounder
|
||||
sounder.eval(io.units)
|
||||
|
@ -11,6 +11,7 @@ local FAC_COMMAND = comms.FAC_COMMAND
|
||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||
|
||||
local PROCESS = types.PROCESS
|
||||
local PRODUCT = types.WASTE_PRODUCT
|
||||
|
||||
---@class process_controller
|
||||
local process = {}
|
||||
@ -24,7 +25,9 @@ local self = {
|
||||
burn_target = 0.0,
|
||||
charge_target = 0.0,
|
||||
gen_target = 0.0,
|
||||
limits = {}
|
||||
limits = {},
|
||||
waste_product = PRODUCT.PLUTONIUM,
|
||||
pu_fallback = false
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,19 +51,23 @@ function process.init(iocontrol, coord_comms)
|
||||
log.error("process.init(): failed to load coordinator settings file")
|
||||
end
|
||||
|
||||
-- facility auto control configuration
|
||||
local config = settings.get("PROCESS") ---@type coord_auto_config|nil
|
||||
|
||||
if type(config) == "table" then
|
||||
self.config.mode = config.mode
|
||||
self.config.burn_target = config.burn_target
|
||||
self.config.charge_target = config.charge_target
|
||||
self.config.gen_target = config.gen_target
|
||||
self.config.limits = config.limits
|
||||
self.config.waste_product = config.waste_product
|
||||
self.config.pu_fallback = config.pu_fallback
|
||||
|
||||
self.io.facility.ps.publish("process_mode", self.config.mode)
|
||||
self.io.facility.ps.publish("process_burn_target", self.config.burn_target)
|
||||
self.io.facility.ps.publish("process_charge_target", self.config.charge_target)
|
||||
self.io.facility.ps.publish("process_gen_target", self.config.gen_target)
|
||||
self.io.facility.ps.publish("process_waste_product", self.config.waste_product)
|
||||
self.io.facility.ps.publish("process_pu_fallback", self.config.pu_fallback)
|
||||
|
||||
for id = 1, math.min(#self.config.limits, self.io.facility.num_units) do
|
||||
local unit = self.io.units[id] ---@type ioctl_unit
|
||||
@ -70,18 +77,18 @@ function process.init(iocontrol, coord_comms)
|
||||
log.info("PROCESS: loaded auto control settings from coord.settings")
|
||||
end
|
||||
|
||||
local waste_mode = settings.get("WASTE_MODES") ---@type table|nil
|
||||
|
||||
if type(waste_mode) == "table" then
|
||||
for id, mode in pairs(waste_mode) do
|
||||
-- unit waste states
|
||||
local waste_modes = settings.get("WASTE_MODES") ---@type table|nil
|
||||
if type(waste_modes) == "table" then
|
||||
for id, mode in pairs(waste_modes) do
|
||||
self.comms.send_unit_command(UNIT_COMMAND.SET_WASTE, id, mode)
|
||||
end
|
||||
|
||||
log.info("PROCESS: loaded waste mode settings from coord.settings")
|
||||
log.info("PROCESS: loaded unit waste mode settings from coord.settings")
|
||||
end
|
||||
|
||||
-- unit priority groups
|
||||
local prio_groups = settings.get("PRIORITY_GROUPS") ---@type table|nil
|
||||
|
||||
if type(prio_groups) == "table" then
|
||||
for id, group in pairs(prio_groups) do
|
||||
self.comms.send_unit_command(UNIT_COMMAND.SET_GROUP, id, group)
|
||||
@ -137,7 +144,7 @@ end
|
||||
-- set waste mode
|
||||
---@param id integer unit ID
|
||||
---@param mode integer waste mode
|
||||
function process.set_waste(id, mode)
|
||||
function process.set_unit_waste(id, mode)
|
||||
-- publish so that if it fails then it gets reset
|
||||
self.io.units[id].unit_ps.publish("U_WasteMode", mode)
|
||||
|
||||
@ -153,7 +160,7 @@ function process.set_waste(id, mode)
|
||||
settings.set("WASTE_MODES", waste_mode)
|
||||
|
||||
if not settings.save("/coord.settings") then
|
||||
log.error("process.set_waste(): failed to save coordinator settings file")
|
||||
log.error("process.set_unit_waste(): failed to save coordinator settings file")
|
||||
end
|
||||
end
|
||||
|
||||
@ -204,6 +211,24 @@ end
|
||||
-- AUTO PROCESS CONTROL --
|
||||
--------------------------
|
||||
|
||||
-- write auto process control to config file
|
||||
local function _write_auto_config()
|
||||
-- attempt to load settings
|
||||
if not settings.load("/coord.settings") then
|
||||
log.warning("process._write_auto_config(): failed to load coordinator settings file")
|
||||
end
|
||||
|
||||
-- save config
|
||||
settings.set("PROCESS", self.config)
|
||||
local saved = settings.save("/coord.settings")
|
||||
|
||||
if not saved then
|
||||
log.warning("process._write_auto_config(): failed to save coordinator settings file")
|
||||
end
|
||||
|
||||
return not not saved
|
||||
end
|
||||
|
||||
-- stop automatic process control
|
||||
function process.stop_auto()
|
||||
self.comms.send_fac_command(FAC_COMMAND.STOP)
|
||||
@ -216,6 +241,30 @@ function process.start_auto()
|
||||
log.debug("PROCESS: START AUTO CTL")
|
||||
end
|
||||
|
||||
-- set automatic process control waste mode
|
||||
---@param product WASTE_PRODUCT waste product for auto control
|
||||
function process.set_process_waste(product)
|
||||
self.comms.send_fac_command(FAC_COMMAND.SET_WASTE_MODE, product)
|
||||
|
||||
log.debug(util.c("PROCESS: SET WASTE ", product))
|
||||
|
||||
-- update config table and save
|
||||
self.config.waste_product = product
|
||||
_write_auto_config()
|
||||
end
|
||||
|
||||
-- set automatic process control plutonium fallback
|
||||
---@param enabled boolean whether to enable plutonium fallback
|
||||
function process.set_pu_fallback(enabled)
|
||||
self.comms.send_fac_command(FAC_COMMAND.SET_PU_FB, enabled)
|
||||
|
||||
log.debug(util.c("PROCESS: SET PU FALLBACK ", enabled))
|
||||
|
||||
-- update config table and save
|
||||
self.config.pu_fallback = enabled
|
||||
_write_auto_config()
|
||||
end
|
||||
|
||||
-- save process control settings
|
||||
---@param mode PROCESS control mode
|
||||
---@param burn_target number burn rate target
|
||||
@ -223,29 +272,17 @@ end
|
||||
---@param gen_target number generation rate target
|
||||
---@param limits table unit burn rate limits
|
||||
function process.save(mode, burn_target, charge_target, gen_target, limits)
|
||||
-- attempt to load settings
|
||||
if not settings.load("/coord.settings") then
|
||||
log.warning("process.save(): failed to load coordinator settings file")
|
||||
end
|
||||
log.debug("PROCESS: SAVE")
|
||||
|
||||
-- config table
|
||||
self.config = {
|
||||
mode = mode,
|
||||
burn_target = burn_target,
|
||||
charge_target = charge_target,
|
||||
gen_target = gen_target,
|
||||
limits = limits
|
||||
}
|
||||
-- update config table
|
||||
self.config.mode = mode
|
||||
self.config.burn_target = burn_target
|
||||
self.config.charge_target = charge_target
|
||||
self.config.gen_target = gen_target
|
||||
self.config.limits = limits
|
||||
|
||||
-- save config
|
||||
settings.set("PROCESS", self.config)
|
||||
local saved = settings.save("/coord.settings")
|
||||
|
||||
if not saved then
|
||||
log.warning("process.save(): failed to save coordinator settings file")
|
||||
end
|
||||
|
||||
self.io.facility.save_cfg_ack(saved)
|
||||
self.io.facility.save_cfg_ack(_write_auto_config())
|
||||
end
|
||||
|
||||
-- handle a start command acknowledgement
|
||||
@ -258,16 +295,33 @@ function process.start_ack_handle(response)
|
||||
self.config.charge_target = response[4]
|
||||
self.config.gen_target = response[5]
|
||||
|
||||
for i = 1, #response[6] do
|
||||
for i = 1, math.min(#response[6], self.io.facility.num_units) do
|
||||
self.config.limits[i] = response[6][i]
|
||||
|
||||
local unit = self.io.units[i] ---@type ioctl_unit
|
||||
unit.unit_ps.publish("burn_limit", self.config.limits[i])
|
||||
end
|
||||
|
||||
self.io.facility.ps.publish("auto_mode", self.config.mode)
|
||||
self.io.facility.ps.publish("burn_target", self.config.burn_target)
|
||||
self.io.facility.ps.publish("charge_target", self.config.charge_target)
|
||||
self.io.facility.ps.publish("gen_target", self.config.gen_target)
|
||||
self.io.facility.ps.publish("process_mode", self.config.mode)
|
||||
self.io.facility.ps.publish("process_burn_target", self.config.burn_target)
|
||||
self.io.facility.ps.publish("process_charge_target", self.config.charge_target)
|
||||
self.io.facility.ps.publish("process_gen_target", self.config.gen_target)
|
||||
|
||||
self.io.facility.start_ack(ack)
|
||||
end
|
||||
|
||||
-- record waste product state after attempting to change it
|
||||
---@param response WASTE_PRODUCT supervisor waste product state
|
||||
function process.waste_ack_handle(response)
|
||||
self.config.waste_product = response
|
||||
self.io.facility.ps.publish("process_waste_product", response)
|
||||
end
|
||||
|
||||
-- record plutonium fallback state after attempting to change it
|
||||
---@param response boolean supervisor plutonium fallback state
|
||||
function process.pu_fb_ack_handle(response)
|
||||
self.config.pu_fallback = response
|
||||
self.io.facility.ps.publish("process_pu_fallback", response)
|
||||
end
|
||||
|
||||
return process
|
||||
|
@ -21,7 +21,7 @@ local sounder = require("coordinator.sounder")
|
||||
|
||||
local apisessions = require("coordinator.session.apisessions")
|
||||
|
||||
local COORDINATOR_VERSION = "v0.17.1"
|
||||
local COORDINATOR_VERSION = "v0.18.0"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
@ -15,8 +15,10 @@ local TextBox = require("graphics.elements.textbox")
|
||||
local DataIndicator = require("graphics.elements.indicators.data")
|
||||
local IndicatorLight = require("graphics.elements.indicators.light")
|
||||
local RadIndicator = require("graphics.elements.indicators.rad")
|
||||
local StateIndicator = require("graphics.elements.indicators.state")
|
||||
local TriIndicatorLight = require("graphics.elements.indicators.trilight")
|
||||
|
||||
local Checkbox = require("graphics.elements.controls.checkbox")
|
||||
local HazardButton = require("graphics.elements.controls.hazard_button")
|
||||
local RadioButton = require("graphics.elements.controls.radio_button")
|
||||
local SpinboxNumeric = require("graphics.elements.controls.spinbox_numeric")
|
||||
@ -43,7 +45,7 @@ local function new_view(root, x, y)
|
||||
local lu_cpair = cpair(colors.gray, colors.gray)
|
||||
local dis_colors = cpair(colors.white, colors.lightGray)
|
||||
|
||||
local main = Div{parent=root,width=104,height=24,x=x,y=y}
|
||||
local main = Div{parent=root,width=128,height=24,x=x,y=y}
|
||||
|
||||
local scram = HazardButton{parent=main,x=1,y=1,text="FAC SCRAM",accent=colors.yellow,dis_colors=dis_colors,callback=process.fac_scram,fg_bg=hzd_fg_bg}
|
||||
local ack_a = HazardButton{parent=main,x=16,y=1,text="ACK \x13",accent=colors.orange,dis_colors=dis_colors,callback=process.fac_ack_alarms,fg_bg=hzd_fg_bg}
|
||||
@ -52,12 +54,14 @@ local function new_view(root, x, y)
|
||||
facility.ack_alarms_ack = ack_a.on_response
|
||||
|
||||
local all_ok = IndicatorLight{parent=main,y=5,label="Unit Systems Online",colors=cpair(colors.green,colors.red)}
|
||||
local ind_mat = IndicatorLight{parent=main,label="Induction Matrix",colors=cpair(colors.green,colors.gray)}
|
||||
local rad_mon = TriIndicatorLight{parent=main,label="Radiation Monitor",c1=colors.gray,c2=colors.yellow,c3=colors.green}
|
||||
local ind_mat = IndicatorLight{parent=main,label="Induction Matrix",colors=cpair(colors.green,colors.gray)}
|
||||
local sps = IndicatorLight{parent=main,label="SPS Connected",colors=cpair(colors.green,colors.gray)}
|
||||
|
||||
all_ok.register(facility.ps, "all_sys_ok", all_ok.update)
|
||||
ind_mat.register(facility.induction_ps_tbl[1], "computed_status", function (status) ind_mat.update(status > 1) end)
|
||||
rad_mon.register(facility.ps, "rad_computed_status", rad_mon.update)
|
||||
ind_mat.register(facility.induction_ps_tbl[1], "computed_status", function (status) ind_mat.update(status > 1) end)
|
||||
sps.register(facility.sps_ps_tbl[1], "computed_status", function (status) sps.update(status > 1) end)
|
||||
|
||||
main.line_break()
|
||||
|
||||
@ -99,7 +103,7 @@ local function new_view(root, x, y)
|
||||
-- process control --
|
||||
---------------------
|
||||
|
||||
local proc = Div{parent=main,width=78,height=24,x=27,y=1}
|
||||
local proc = Div{parent=main,width=103,height=24,x=27,y=1}
|
||||
|
||||
-----------------------------
|
||||
-- process control targets --
|
||||
@ -148,46 +152,77 @@ local function new_view(root, x, y)
|
||||
|
||||
local rate_limits = {}
|
||||
|
||||
for i = 1, facility.num_units do
|
||||
local unit = units[i] ---@type ioctl_unit
|
||||
for i = 1, 4 do
|
||||
local unit
|
||||
local tag_fg_bg = cpair(colors.gray,colors.white)
|
||||
local lim_fg_bg = cpair(colors.lightGray,colors.white)
|
||||
local ctl_fg = colors.lightGray
|
||||
local cur_fg_bg = cpair(colors.lightGray,colors.white)
|
||||
local cur_lu = colors.lightGray
|
||||
|
||||
if i <= facility.num_units then
|
||||
unit = units[i] ---@type ioctl_unit
|
||||
tag_fg_bg = cpair(colors.black,colors.lightBlue)
|
||||
lim_fg_bg = bw_fg_bg
|
||||
ctl_fg = colors.gray
|
||||
cur_fg_bg = cpair(colors.black,colors.brown)
|
||||
cur_lu = colors.black
|
||||
end
|
||||
|
||||
local _y = ((i - 1) * 5) + 1
|
||||
|
||||
local unit_tag = Div{parent=limit_div,x=1,y=_y,width=8,height=4,fg_bg=cpair(colors.black,colors.lightBlue)}
|
||||
local unit_tag = Div{parent=limit_div,x=1,y=_y,width=8,height=4,fg_bg=tag_fg_bg}
|
||||
TextBox{parent=unit_tag,x=2,y=2,text="Unit "..i.." Limit",width=7,height=2}
|
||||
|
||||
local lim_ctl = Div{parent=limit_div,x=9,y=_y,width=14,height=3,fg_bg=cpair(colors.gray,colors.white)}
|
||||
rate_limits[i] = SpinboxNumeric{parent=lim_ctl,x=2,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=cpair(colors.gray,colors.white),fg_bg=bw_fg_bg}
|
||||
local lim_ctl = Div{parent=limit_div,x=9,y=_y,width=14,height=3,fg_bg=cpair(ctl_fg,colors.white)}
|
||||
local lim = SpinboxNumeric{parent=lim_ctl,x=2,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=cpair(colors.gray,colors.white),fg_bg=lim_fg_bg}
|
||||
TextBox{parent=lim_ctl,x=9,y=2,text="mB/t",width=4,height=1}
|
||||
|
||||
rate_limits[i].register(unit.unit_ps, "max_burn", rate_limits[i].set_max)
|
||||
rate_limits[i].register(unit.unit_ps, "burn_limit", rate_limits[i].set_value)
|
||||
local cur_burn = DataIndicator{parent=limit_div,x=9,y=_y+3,label="",format="%7.1f",value=0,unit="mB/t",commas=false,lu_colors=cpair(cur_lu,cur_lu),width=14,fg_bg=cur_fg_bg}
|
||||
|
||||
local cur_burn = DataIndicator{parent=limit_div,x=9,y=_y+3,label="",format="%7.1f",value=0,unit="mB/t",commas=false,lu_colors=cpair(colors.black,colors.black),width=14,fg_bg=cpair(colors.black,colors.brown)}
|
||||
if i <= facility.num_units then
|
||||
rate_limits[i] = lim
|
||||
rate_limits[i].register(unit.unit_ps, "max_burn", rate_limits[i].set_max)
|
||||
rate_limits[i].register(unit.unit_ps, "burn_limit", rate_limits[i].set_value)
|
||||
|
||||
cur_burn.register(unit.unit_ps, "act_burn_rate", cur_burn.update)
|
||||
cur_burn.register(unit.unit_ps, "act_burn_rate", cur_burn.update)
|
||||
else
|
||||
lim.disable()
|
||||
end
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- unit statuses --
|
||||
-------------------
|
||||
|
||||
local stat_div = Div{parent=proc,width=38,height=19,x=57,y=6}
|
||||
local stat_div = Div{parent=proc,width=22,height=24,x=57,y=6}
|
||||
|
||||
for i = 1, facility.num_units do
|
||||
local unit = units[i] ---@type ioctl_unit
|
||||
for i = 1, 4 do
|
||||
local tag_fg_bg = cpair(colors.gray,colors.white)
|
||||
local ind_fg_bg = cpair(colors.lightGray,colors.white)
|
||||
local ind_off = colors.lightGray
|
||||
|
||||
if i <= facility.num_units then
|
||||
tag_fg_bg = cpair(colors.black,colors.cyan)
|
||||
ind_fg_bg = bw_fg_bg
|
||||
ind_off = colors.gray
|
||||
end
|
||||
|
||||
local _y = ((i - 1) * 5) + 1
|
||||
|
||||
local unit_tag = Div{parent=stat_div,x=1,y=_y,width=8,height=4,fg_bg=cpair(colors.black,colors.lightBlue)}
|
||||
local unit_tag = Div{parent=stat_div,x=1,y=_y,width=8,height=4,fg_bg=tag_fg_bg}
|
||||
TextBox{parent=unit_tag,x=2,y=2,text="Unit "..i.." Status",width=7,height=2}
|
||||
|
||||
local lights = Div{parent=stat_div,x=9,y=_y,width=12,height=4,fg_bg=bw_fg_bg}
|
||||
local ready = IndicatorLight{parent=lights,x=2,y=2,label="Ready",colors=cpair(colors.green,colors.gray)}
|
||||
local degraded = IndicatorLight{parent=lights,x=2,y=3,label="Degraded",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS}
|
||||
local lights = Div{parent=stat_div,x=9,y=_y,width=14,height=4,fg_bg=ind_fg_bg}
|
||||
local ready = IndicatorLight{parent=lights,x=2,y=2,label="Ready",colors=cpair(colors.green,ind_off)}
|
||||
local degraded = IndicatorLight{parent=lights,x=2,y=3,label="Degraded",colors=cpair(colors.red,ind_off),flash=true,period=period.BLINK_250_MS}
|
||||
|
||||
ready.register(unit.unit_ps, "U_AutoReady", ready.update)
|
||||
degraded.register(unit.unit_ps, "U_AutoDegraded", degraded.update)
|
||||
if i <= facility.num_units then
|
||||
local unit = units[i] ---@type ioctl_unit
|
||||
|
||||
ready.register(unit.unit_ps, "U_AutoReady", ready.update)
|
||||
degraded.register(unit.unit_ps, "U_AutoDegraded", degraded.update)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------
|
||||
@ -195,7 +230,7 @@ local function new_view(root, x, y)
|
||||
-------------------------
|
||||
|
||||
local ctl_opts = { "Monitored Max Burn", "Combined Burn Rate", "Charge Level", "Generation Rate" }
|
||||
local mode = RadioButton{parent=proc,x=34,y=1,options=ctl_opts,callback=function()end,radio_colors=cpair(colors.purple,colors.black),radio_bg=colors.gray}
|
||||
local mode = RadioButton{parent=proc,x=34,y=1,options=ctl_opts,callback=function()end,radio_colors=cpair(colors.white,colors.black),radio_bg=colors.purple}
|
||||
|
||||
mode.register(facility.ps, "process_mode", mode.set_value)
|
||||
|
||||
@ -261,6 +296,60 @@ local function new_view(root, x, y)
|
||||
for i = 1, #rate_limits do rate_limits[i].enable() end
|
||||
end
|
||||
end)
|
||||
|
||||
------------------------------
|
||||
-- waste production control --
|
||||
------------------------------
|
||||
|
||||
local waste_status = Div{parent=proc,width=24,height=4,x=57,y=1,}
|
||||
|
||||
for i = 1, facility.num_units do
|
||||
local unit = units[i] ---@type ioctl_unit
|
||||
|
||||
TextBox{parent=waste_status,y=i,text="U"..i.." Waste",width=8,height=1}
|
||||
local a_waste = IndicatorLight{parent=waste_status,x=10,y=i,label="Auto",colors=cpair(colors.white,colors.gray)}
|
||||
local waste_m = StateIndicator{parent=waste_status,x=17,y=i,states=style.waste.states_abbrv,value=1,min_width=6}
|
||||
|
||||
a_waste.register(unit.unit_ps, "U_AutoWaste", a_waste.update)
|
||||
waste_m.register(unit.unit_ps, "U_WasteProduct", waste_m.update)
|
||||
end
|
||||
|
||||
local waste_sel = Div{parent=proc,width=21,height=24,x=81,y=1}
|
||||
|
||||
TextBox{parent=waste_sel,text=" ",width=21,height=1,x=1,y=1,fg_bg=cpair(colors.black,colors.brown)}
|
||||
TextBox{parent=waste_sel,text="WASTE PRODUCTION",alignment=TEXT_ALIGN.CENTER,width=21,height=1,x=1,y=2,fg_bg=cpair(colors.lightGray,colors.brown)}
|
||||
|
||||
local rect = Rectangle{parent=waste_sel,border=border(1,colors.brown,true),width=21,height=22,x=1,y=3}
|
||||
local status = StateIndicator{parent=rect,x=2,y=1,states=style.waste.states,value=1,min_width=17}
|
||||
|
||||
status.register(facility.ps, "current_waste_product", status.update)
|
||||
|
||||
local waste_prod = RadioButton{parent=rect,x=2,y=3,options=style.waste.options,callback=process.set_process_waste,radio_colors=cpair(colors.white,colors.black),radio_bg=colors.brown}
|
||||
local pu_fallback = Checkbox{parent=rect,x=2,y=7,label="Pu Fallback",callback=process.set_pu_fallback,box_fg_bg=cpair(colors.green,colors.black)}
|
||||
|
||||
waste_prod.register(facility.ps, "process_waste_product", waste_prod.set_value)
|
||||
pu_fallback.register(facility.ps, "process_pu_fallback", pu_fallback.set_value)
|
||||
|
||||
local fb_active = IndicatorLight{parent=rect,x=2,y=9,label="Fallback Active",colors=cpair(colors.white,colors.gray)}
|
||||
|
||||
fb_active.register(facility.ps, "pu_fallback_active", fb_active.update)
|
||||
|
||||
TextBox{parent=rect,x=2,y=11,text="Plutonium Rate",height=1,width=17,fg_bg=style.label}
|
||||
local pu_rate = DataIndicator{parent=rect,x=2,label="",unit="mB/t",format="%12.2f",value=0,lu_colors=lu_cpair,fg_bg=bw_fg_bg,width=17}
|
||||
|
||||
TextBox{parent=rect,x=2,y=14,text="Polonium Rate",height=1,width=17,fg_bg=style.label}
|
||||
local po_rate = DataIndicator{parent=rect,x=2,label="",unit="mB/t",format="%12.2f",value=0,lu_colors=lu_cpair,fg_bg=bw_fg_bg,width=17}
|
||||
|
||||
TextBox{parent=rect,x=2,y=17,text="Antimatter Rate",height=1,width=17,fg_bg=style.label}
|
||||
local am_rate = DataIndicator{parent=rect,x=2,label="",unit="\xb5B/t",format="%12.2f",value=0,lu_colors=lu_cpair,fg_bg=bw_fg_bg,width=17}
|
||||
|
||||
pu_rate.register(facility.ps, "pu_rate", pu_rate.update)
|
||||
po_rate.register(facility.ps, "po_rate", po_rate.update)
|
||||
am_rate.register(facility.ps, "am_rate", am_rate.update)
|
||||
|
||||
local sna_count = DataIndicator{parent=rect,x=2,y=20,label="Linked SNAs:",format="%4d",value=0,lu_colors=lu_cpair,width=17}
|
||||
|
||||
sna_count.register(facility.ps, "sna_count", sna_count.update)
|
||||
end
|
||||
|
||||
return new_view
|
@ -33,41 +33,21 @@ local border = core.border
|
||||
|
||||
local period = core.flasher.PERIOD
|
||||
|
||||
local waste_opts = {
|
||||
{
|
||||
text = "Auto",
|
||||
fg_bg = cpair(colors.black, colors.lightGray),
|
||||
active_fg_bg = cpair(colors.white, colors.gray)
|
||||
},
|
||||
{
|
||||
text = "Pu",
|
||||
fg_bg = cpair(colors.black, colors.lightGray),
|
||||
active_fg_bg = cpair(colors.black, colors.green)
|
||||
},
|
||||
{
|
||||
text = "Po",
|
||||
fg_bg = cpair(colors.black, colors.lightGray),
|
||||
active_fg_bg = cpair(colors.black, colors.cyan)
|
||||
},
|
||||
{
|
||||
text = "AM",
|
||||
fg_bg = cpair(colors.black, colors.lightGray),
|
||||
active_fg_bg = cpair(colors.black, colors.purple)
|
||||
}
|
||||
}
|
||||
|
||||
-- create a unit view
|
||||
---@param parent graphics_element parent
|
||||
---@param id integer
|
||||
local function init(parent, id)
|
||||
local unit = iocontrol.get_db().units[id] ---@type ioctl_unit
|
||||
local f_ps = iocontrol.get_db().facility.ps
|
||||
|
||||
local main = Div{parent=parent,x=1,y=1}
|
||||
|
||||
if unit == nil then return main end
|
||||
|
||||
local u_ps = unit.unit_ps
|
||||
local b_ps = unit.boiler_ps_tbl
|
||||
local t_ps = unit.turbine_ps_tbl
|
||||
|
||||
local main = Div{parent=parent,x=1,y=1}
|
||||
|
||||
TextBox{parent=main,text="Reactor Unit #" .. id,alignment=TEXT_ALIGN.CENTER,height=1,fg_bg=style.header}
|
||||
|
||||
local bw_fg_bg = cpair(colors.black, colors.white)
|
||||
@ -398,7 +378,7 @@ local function init(parent, id)
|
||||
local waste_proc = Rectangle{parent=main,border=border(1,colors.brown,true),thin=true,width=33,height=3,x=46,y=49}
|
||||
local waste_div = Div{parent=waste_proc,x=2,y=1,width=31,height=1}
|
||||
|
||||
local waste_mode = MultiButton{parent=waste_div,x=1,y=1,options=waste_opts,callback=unit.set_waste,min_width=6}
|
||||
local waste_mode = MultiButton{parent=waste_div,x=1,y=1,options=style.waste.unit_opts,callback=unit.set_waste,min_width=6}
|
||||
|
||||
waste_mode.register(u_ps, "U_WasteMode", waste_mode.set_value)
|
||||
|
||||
|
@ -9,7 +9,7 @@ local iocontrol = require("coordinator.iocontrol")
|
||||
local style = require("coordinator.ui.style")
|
||||
|
||||
local imatrix = require("coordinator.ui.components.imatrix")
|
||||
local process_ctl = require("coordinator.ui.components.processctl")
|
||||
local process_ctl = require("coordinator.ui.components.process_ctl")
|
||||
local unit_overview = require("coordinator.ui.components.unit_overview")
|
||||
|
||||
local core = require("graphics.core")
|
||||
|
@ -151,7 +151,90 @@ style.imatrix = {
|
||||
{
|
||||
color = cpair(colors.black, colors.yellow),
|
||||
text = "HIGH CHARGE"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
style.sps = {
|
||||
-- SPS states
|
||||
states = {
|
||||
{
|
||||
color = cpair(colors.black, colors.yellow),
|
||||
text = "OFF-LINE"
|
||||
},
|
||||
{
|
||||
color = cpair(colors.black, colors.orange),
|
||||
text = "NOT FORMED"
|
||||
},
|
||||
{
|
||||
color = cpair(colors.black, colors.orange),
|
||||
text = "RTU FAULT"
|
||||
},
|
||||
{
|
||||
color = cpair(colors.black, colors.gray),
|
||||
text = "IDLE"
|
||||
},
|
||||
{
|
||||
color = cpair(colors.black, colors.green),
|
||||
text = "ACTIVE"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
style.waste = {
|
||||
-- auto waste processing states
|
||||
states = {
|
||||
{
|
||||
color = cpair(colors.black, colors.green),
|
||||
text = "PLUTONIUM"
|
||||
},
|
||||
{
|
||||
color = cpair(colors.black, colors.cyan),
|
||||
text = "POLONIUM"
|
||||
},
|
||||
{
|
||||
color = cpair(colors.black, colors.purple),
|
||||
text = "ANTI MATTER"
|
||||
}
|
||||
},
|
||||
states_abbrv = {
|
||||
{
|
||||
color = cpair(colors.black, colors.green),
|
||||
text = "Pu"
|
||||
},
|
||||
{
|
||||
color = cpair(colors.black, colors.cyan),
|
||||
text = "Po"
|
||||
},
|
||||
{
|
||||
color = cpair(colors.black, colors.purple),
|
||||
text = "AM"
|
||||
}
|
||||
},
|
||||
-- process radio button options
|
||||
options = { "Plutonium", "Polonium", "Antimatter" },
|
||||
-- unit waste selection
|
||||
unit_opts = {
|
||||
{
|
||||
text = "Auto",
|
||||
fg_bg = cpair(colors.black, colors.lightGray),
|
||||
active_fg_bg = cpair(colors.white, colors.gray)
|
||||
},
|
||||
{
|
||||
text = "Pu",
|
||||
fg_bg = cpair(colors.black, colors.lightGray),
|
||||
active_fg_bg = cpair(colors.black, colors.green)
|
||||
},
|
||||
{
|
||||
text = "Po",
|
||||
fg_bg = cpair(colors.black, colors.lightGray),
|
||||
active_fg_bg = cpair(colors.black, colors.cyan)
|
||||
},
|
||||
{
|
||||
text = "AM",
|
||||
fg_bg = cpair(colors.black, colors.lightGray),
|
||||
active_fg_bg = cpair(colors.black, colors.purple)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ local element = {}
|
||||
|
||||
---@alias graphics_args graphics_args_generic
|
||||
---|waiting_args
|
||||
---|checkbox_args
|
||||
---|hazard_button_args
|
||||
---|multi_button_args
|
||||
---|push_button_args
|
||||
|
85
graphics/elements/controls/checkbox.lua
Normal file
85
graphics/elements/controls/checkbox.lua
Normal file
@ -0,0 +1,85 @@
|
||||
-- Checkbox Graphics Element
|
||||
|
||||
local core = require("graphics.core")
|
||||
local element = require("graphics.element")
|
||||
|
||||
---@class checkbox_args
|
||||
---@field label string checkbox text
|
||||
---@field box_fg_bg cpair colors for checkbox
|
||||
---@field callback function function to call on press
|
||||
---@field parent graphics_element
|
||||
---@field id? string element id
|
||||
---@field x? integer 1 if omitted
|
||||
---@field y? integer 1 if omitted
|
||||
---@field fg_bg? cpair foreground/background colors
|
||||
---@field hidden? boolean true to hide on initial draw
|
||||
|
||||
-- new checkbox control
|
||||
---@param args checkbox_args
|
||||
---@return graphics_element element, element_id id
|
||||
local function checkbox(args)
|
||||
assert(type(args.label) == "string", "graphics.elements.controls.checkbox: label is a required field")
|
||||
assert(type(args.box_fg_bg) == "table", "graphics.elements.controls.checkbox: box_fg_bg is a required field")
|
||||
assert(type(args.callback) == "function", "graphics.elements.controls.checkbox: callback is a required field")
|
||||
|
||||
args.height = 1
|
||||
args.width = 3 + string.len(args.label)
|
||||
|
||||
-- create new graphics element base object
|
||||
local e = element.new(args)
|
||||
|
||||
e.value = false
|
||||
|
||||
-- show the button state
|
||||
local function draw()
|
||||
e.window.setCursorPos(1, 1)
|
||||
|
||||
if e.value then
|
||||
-- show as selected
|
||||
e.window.setTextColor(args.box_fg_bg.bkg)
|
||||
e.window.setBackgroundColor(args.box_fg_bg.fgd)
|
||||
e.window.write("\x88")
|
||||
e.window.setTextColor(args.box_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.window.write("\x95")
|
||||
else
|
||||
-- show as unselected
|
||||
e.window.setTextColor(e.fg_bg.bkg)
|
||||
e.window.setBackgroundColor(args.box_fg_bg.bkg)
|
||||
e.window.write("\x88")
|
||||
e.window.setTextColor(args.box_fg_bg.bkg)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.window.write("\x95")
|
||||
end
|
||||
end
|
||||
|
||||
-- handle mouse interaction
|
||||
---@param event mouse_interaction mouse event
|
||||
function e.handle_mouse(event)
|
||||
if e.enabled and core.events.was_clicked(event.type) then
|
||||
e.value = not e.value
|
||||
draw()
|
||||
args.callback(e.value)
|
||||
end
|
||||
end
|
||||
|
||||
-- set the value
|
||||
---@param val integer new value
|
||||
function e.set_value(val)
|
||||
e.value = val
|
||||
draw()
|
||||
end
|
||||
|
||||
-- write label text
|
||||
e.window.setCursorPos(3, 1)
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.window.write(args.label)
|
||||
|
||||
-- initial draw
|
||||
draw()
|
||||
|
||||
return e.complete()
|
||||
end
|
||||
|
||||
return checkbox
|
File diff suppressed because one or more lines are too long
@ -14,7 +14,7 @@ local max_distance = nil ---@type number|nil maximum acceptable t
|
||||
---@class comms
|
||||
local comms = {}
|
||||
|
||||
comms.version = "2.1.0"
|
||||
comms.version = "2.1.1"
|
||||
|
||||
---@enum PROTOCOL
|
||||
local PROTOCOL = {
|
||||
@ -92,9 +92,11 @@ local PLC_AUTO_ACK = {
|
||||
---@enum FAC_COMMAND
|
||||
local FAC_COMMAND = {
|
||||
SCRAM_ALL = 0, -- SCRAM all reactors
|
||||
STOP = 1, -- stop automatic control
|
||||
START = 2, -- start automatic control
|
||||
ACK_ALL_ALARMS = 3 -- acknowledge all alarms on all units
|
||||
STOP = 1, -- stop automatic process control
|
||||
START = 2, -- start automatic process control
|
||||
ACK_ALL_ALARMS = 3, -- acknowledge all alarms on all units
|
||||
SET_WASTE_MODE = 4, -- set automatic waste processing mode
|
||||
SET_PU_FB = 5 -- set plutonium fallback mode
|
||||
}
|
||||
|
||||
---@enum UNIT_COMMAND
|
||||
|
@ -158,13 +158,26 @@ types.PROCESS_NAMES = {
|
||||
---@enum WASTE_MODE
|
||||
types.WASTE_MODE = {
|
||||
AUTO = 1,
|
||||
PLUTONIUM = 2,
|
||||
POLONIUM = 3,
|
||||
ANTI_MATTER = 4
|
||||
MANUAL_PLUTONIUM = 2,
|
||||
MANUAL_POLONIUM = 3,
|
||||
MANUAL_ANTI_MATTER = 4
|
||||
}
|
||||
|
||||
types.WASTE_MODE_NAMES = {
|
||||
"AUTO",
|
||||
"MANUAL_PLUTONIUM",
|
||||
"MANUAL_POLONIUM",
|
||||
"MANUAL_ANTI_MATTER"
|
||||
}
|
||||
|
||||
---@enum WASTE_PRODUCT
|
||||
types.WASTE_PRODUCT = {
|
||||
PLUTONIUM = 1,
|
||||
POLONIUM = 2,
|
||||
ANTI_MATTER = 3
|
||||
}
|
||||
|
||||
types.WASTE_PRODUCT_NAMES = {
|
||||
"PLUTONIUM",
|
||||
"POLONIUM",
|
||||
"ANTI_MATTER"
|
||||
|
@ -11,6 +11,9 @@ local rsctl = require("supervisor.session.rsctl")
|
||||
local PROCESS = types.PROCESS
|
||||
local PROCESS_NAMES = types.PROCESS_NAMES
|
||||
local PRIO = types.ALARM_PRIORITY
|
||||
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
|
||||
local WASTE = types.WASTE_PRODUCT
|
||||
local WASTE_MODE = types.WASTE_MODE
|
||||
|
||||
local IO = rsio.IO
|
||||
|
||||
@ -61,6 +64,7 @@ function facility.new(num_reactors, cooling_conf)
|
||||
rtu_conn_count = 0,
|
||||
redstone = {},
|
||||
induction = {},
|
||||
sps = {},
|
||||
envd = {},
|
||||
-- redstone I/O control
|
||||
io_ctl = nil, ---@type rs_controller
|
||||
@ -99,6 +103,10 @@ function facility.new(num_reactors, cooling_conf)
|
||||
last_update = 0,
|
||||
last_error = 0.0,
|
||||
last_time = 0.0,
|
||||
-- waste processing
|
||||
waste_product = WASTE.PLUTONIUM,
|
||||
current_waste_product = WASTE.PLUTONIUM,
|
||||
pu_fallback = false,
|
||||
-- statistics
|
||||
im_stat_init = false,
|
||||
avg_charge = util.mov_avg(3, 0.0),
|
||||
@ -205,12 +213,18 @@ function facility.new(num_reactors, cooling_conf)
|
||||
table.insert(self.redstone, rs_unit)
|
||||
end
|
||||
|
||||
-- link an imatrix RTU session
|
||||
-- link an induction matrix RTU session
|
||||
---@param imatrix unit_session
|
||||
function public.add_imatrix(imatrix)
|
||||
table.insert(self.induction, imatrix)
|
||||
end
|
||||
|
||||
-- link an SPS RTU session
|
||||
---@param sps unit_session
|
||||
function public.add_sps(sps)
|
||||
table.insert(self.sps, sps)
|
||||
end
|
||||
|
||||
-- link an environment detector RTU session
|
||||
---@param envd unit_session
|
||||
function public.add_envd(envd)
|
||||
@ -222,6 +236,7 @@ function facility.new(num_reactors, cooling_conf)
|
||||
function public.purge_rtu_devices(session)
|
||||
util.filter_table(self.redstone, function (s) return s.get_session_id() ~= session end)
|
||||
util.filter_table(self.induction, function (s) return s.get_session_id() ~= session end)
|
||||
util.filter_table(self.sps, function (s) return s.get_session_id() ~= session end)
|
||||
util.filter_table(self.envd, function (s) return s.get_session_id() ~= session end)
|
||||
end
|
||||
|
||||
@ -238,6 +253,7 @@ function facility.new(num_reactors, cooling_conf)
|
||||
-- unlink RTU unit sessions if they are closed
|
||||
_unlink_disconnected_units(self.redstone)
|
||||
_unlink_disconnected_units(self.induction)
|
||||
_unlink_disconnected_units(self.sps)
|
||||
_unlink_disconnected_units(self.envd)
|
||||
|
||||
-- current state for process control
|
||||
@ -277,6 +293,8 @@ function facility.new(num_reactors, cooling_conf)
|
||||
-- Run Process Control --
|
||||
-------------------------
|
||||
|
||||
--#region Process Control
|
||||
|
||||
local avg_charge = self.avg_charge.compute()
|
||||
local avg_inflow = self.avg_inflow.compute()
|
||||
|
||||
@ -542,10 +560,14 @@ function facility.new(num_reactors, cooling_conf)
|
||||
next_mode = PROCESS.INACTIVE
|
||||
end
|
||||
|
||||
--#endregion
|
||||
|
||||
------------------------------
|
||||
-- Evaluate Automatic SCRAM --
|
||||
------------------------------
|
||||
|
||||
--#region Automatic SCRAM
|
||||
|
||||
local astatus = self.ascram_status
|
||||
|
||||
if self.induction[1] ~= nil then
|
||||
@ -659,6 +681,8 @@ function facility.new(num_reactors, cooling_conf)
|
||||
end
|
||||
end
|
||||
|
||||
--#endregion
|
||||
|
||||
-- update last mode and set next mode
|
||||
self.last_mode = self.mode
|
||||
self.mode = next_mode
|
||||
@ -692,12 +716,33 @@ function facility.new(num_reactors, cooling_conf)
|
||||
|
||||
self.io_ctl.digital_write(IO.F_ALARM, has_alarm)
|
||||
end
|
||||
|
||||
-----------------------------
|
||||
-- Update Waste Processing --
|
||||
-----------------------------
|
||||
|
||||
local insufficent_po_rate = false
|
||||
for i = 1, #self.units do
|
||||
local u = self.units[i] ---@type reactor_unit
|
||||
if u.get_control_inf().waste_mode == WASTE_MODE.AUTO then
|
||||
if (u.get_sna_rate() * 10.0) < u.get_burn_rate() then
|
||||
insufficent_po_rate = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.waste_product == WASTE.PLUTONIUM or (self.pu_fallback and insufficent_po_rate) then
|
||||
self.current_waste_product = WASTE.PLUTONIUM
|
||||
else self.current_waste_product = self.waste_product end
|
||||
end
|
||||
|
||||
-- call the update function of all units in the facility
|
||||
-- call the update function of all units in the facility<br>
|
||||
-- additionally sets the requested auto waste mode if applicable
|
||||
function public.update_units()
|
||||
for i = 1, #self.units do
|
||||
local u = self.units[i] ---@type reactor_unit
|
||||
u.auto_set_waste(self.current_waste_product)
|
||||
u.update()
|
||||
end
|
||||
end
|
||||
@ -721,15 +766,15 @@ function facility.new(num_reactors, cooling_conf)
|
||||
end
|
||||
|
||||
-- stop auto control
|
||||
function public.auto_stop()
|
||||
self.mode = PROCESS.INACTIVE
|
||||
end
|
||||
function public.auto_stop() self.mode = PROCESS.INACTIVE end
|
||||
|
||||
-- set automatic control configuration and start the process
|
||||
---@param config coord_auto_config configuration
|
||||
---@return table response ready state (successfully started) and current configuration (after updating)
|
||||
function public.auto_start(config)
|
||||
local ready = false
|
||||
local charge_scaler = 1000000 -- convert MFE to FE
|
||||
local gen_scaler = 1000 -- convert kFE to FE
|
||||
local ready = false
|
||||
|
||||
-- load up current limits
|
||||
local limits = {}
|
||||
@ -749,11 +794,11 @@ function facility.new(num_reactors, cooling_conf)
|
||||
end
|
||||
|
||||
if (type(config.charge_target) == "number") and config.charge_target >= 0 then
|
||||
self.charge_setpoint = config.charge_target * 1000000 -- convert MFE to FE
|
||||
self.charge_setpoint = config.charge_target * charge_scaler
|
||||
end
|
||||
|
||||
if (type(config.gen_target) == "number") and config.gen_target >= 0 then
|
||||
self.gen_rate_setpoint = config.gen_target * 1000 -- convert kFE to FE
|
||||
self.gen_rate_setpoint = config.gen_target * gen_scaler
|
||||
end
|
||||
|
||||
if (type(config.limits) == "table") and (#config.limits == num_reactors) then
|
||||
@ -782,7 +827,14 @@ function facility.new(num_reactors, cooling_conf)
|
||||
if ready then self.mode = self.mode_set end
|
||||
end
|
||||
|
||||
return { ready, self.mode_set, self.burn_target, self.charge_setpoint, self.gen_rate_setpoint, limits }
|
||||
return {
|
||||
ready,
|
||||
self.mode_set,
|
||||
self.burn_target,
|
||||
self.charge_setpoint / charge_scaler,
|
||||
self.gen_rate_setpoint / gen_scaler,
|
||||
limits
|
||||
}
|
||||
end
|
||||
|
||||
-- SETTINGS --
|
||||
@ -807,15 +859,35 @@ function facility.new(num_reactors, cooling_conf)
|
||||
end
|
||||
end
|
||||
|
||||
-- set waste production
|
||||
---@param product WASTE_PRODUCT target product
|
||||
---@return WASTE_PRODUCT product newly set value, if valid
|
||||
function public.set_waste_product(product)
|
||||
if product == WASTE.PLUTONIUM or product == WASTE.POLONIUM or product == WASTE.ANTI_MATTER then
|
||||
self.waste_product = product
|
||||
end
|
||||
|
||||
return self.waste_product
|
||||
end
|
||||
|
||||
-- enable/disable plutonium fallback
|
||||
---@param enabled boolean requested state
|
||||
---@return boolean enabled newly set value
|
||||
function public.set_pu_fallback(enabled)
|
||||
self.pu_fallback = enabled == true
|
||||
return self.pu_fallback
|
||||
end
|
||||
|
||||
-- READ STATES/PROPERTIES --
|
||||
|
||||
-- get build properties of all machines
|
||||
-- get build properties of all facility devices
|
||||
---@nodiscard
|
||||
---@param inc_imatrix boolean? true/nil to include induction matrix build, false to exclude
|
||||
function public.get_build(inc_imatrix)
|
||||
---@param type RTU_UNIT_TYPE? type or nil to include only a particular unit type, or to include all if nil
|
||||
function public.get_build(type)
|
||||
local all = type == nil
|
||||
local build = {}
|
||||
|
||||
if inc_imatrix ~= false then
|
||||
if all or type == RTU_UNIT_TYPE.IMATRIX then
|
||||
build.induction = {}
|
||||
for i = 1, #self.induction do
|
||||
local matrix = self.induction[i] ---@type unit_session
|
||||
@ -823,6 +895,14 @@ function facility.new(num_reactors, cooling_conf)
|
||||
end
|
||||
end
|
||||
|
||||
if all or type == RTU_UNIT_TYPE.SPS then
|
||||
build.sps = {}
|
||||
for i = 1, #self.sps do
|
||||
local sps = self.sps[i] ---@type unit_session
|
||||
build.sps[sps.get_device_idx()] = { sps.get_db().formed, sps.get_db().build }
|
||||
end
|
||||
end
|
||||
|
||||
return build
|
||||
end
|
||||
|
||||
@ -844,7 +924,9 @@ function facility.new(num_reactors, cooling_conf)
|
||||
astat.gen_fault or self.mode == PROCESS.GEN_RATE_FAULT_IDLE,
|
||||
self.status_text[1],
|
||||
self.status_text[2],
|
||||
self.group_map
|
||||
self.group_map,
|
||||
self.current_waste_product,
|
||||
(self.current_waste_product == WASTE.PLUTONIUM) and (self.waste_product ~= WASTE.PLUTONIUM)
|
||||
}
|
||||
end
|
||||
|
||||
@ -875,6 +957,18 @@ function facility.new(num_reactors, cooling_conf)
|
||||
}
|
||||
end
|
||||
|
||||
-- status of sps
|
||||
status.sps = {}
|
||||
for i = 1, #self.sps do
|
||||
local sps = self.sps[i] ---@type unit_session
|
||||
status.sps[sps.get_device_idx()] = {
|
||||
sps.is_faulted(),
|
||||
sps.get_db().formed,
|
||||
sps.get_db().state,
|
||||
sps.get_db().tanks
|
||||
}
|
||||
end
|
||||
|
||||
-- radiation monitors (environment detectors)
|
||||
status.rad_mon = {}
|
||||
for i = 1, #self.envd do
|
||||
|
@ -258,6 +258,18 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
||||
facility.ack_all()
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
elseif cmd == FAC_COMMAND.SET_WASTE_MODE then
|
||||
if pkt.length == 2 then
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, facility.set_waste_product(pkt.data[2]) })
|
||||
else
|
||||
log.debug(log_header .. "CRDN set waste mode packet length mismatch")
|
||||
end
|
||||
elseif cmd == FAC_COMMAND.SET_PU_FB then
|
||||
if pkt.length == 2 then
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, facility.set_pu_fallback(pkt.data[2]) })
|
||||
else
|
||||
log.debug(log_header .. "CRDN set pu fallback packet length mismatch")
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "CRDN facility command unknown")
|
||||
end
|
||||
@ -294,9 +306,9 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
end
|
||||
elseif cmd == UNIT_COMMAND.SET_WASTE then
|
||||
if (pkt.length == 3) and (type(pkt.data[3]) == "number") and (pkt.data[3] > 0) and (pkt.data[3] <= 4) then
|
||||
unit.set_waste(pkt.data[3])
|
||||
unit.set_waste_mode(pkt.data[3])
|
||||
else
|
||||
log.debug(log_header .. "CRDN unit command set waste missing option")
|
||||
log.debug(log_header .. "CRDN unit command set waste missing/invalid option")
|
||||
end
|
||||
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
||||
unit.ack_all()
|
||||
@ -417,7 +429,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
self.retry_times.f_builds_packet = util.time() + PARTIAL_RETRY_PERIOD
|
||||
self.acks.fac_builds = false
|
||||
|
||||
_send(SCADA_CRDN_TYPE.FAC_BUILDS, { facility.get_build(cmd.val.type == RTU_UNIT_TYPE.IMATRIX) })
|
||||
_send(SCADA_CRDN_TYPE.FAC_BUILDS, { facility.get_build(cmd.val.type) })
|
||||
end
|
||||
else
|
||||
log.error(log_header .. "unsupported data command received in in_queue (this is a bug)", true)
|
||||
|
@ -138,6 +138,10 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
-- turbine
|
||||
unit = svrs_turbinev.new(id, i, unit_advert, self.modbus_q)
|
||||
if type(unit) ~= "nil" then target_unit.add_turbine(unit) end
|
||||
elseif u_type == RTU_UNIT_TYPE.SNA then
|
||||
-- solar neutron activator
|
||||
unit = svrs_sna.new(id, i, unit_advert, self.modbus_q)
|
||||
if type(unit) ~= "nil" then target_unit.add_sna(unit) end
|
||||
elseif u_type == RTU_UNIT_TYPE.ENV_DETECTOR then
|
||||
-- environment detector
|
||||
unit = svrs_envd.new(id, i, unit_advert, self.modbus_q)
|
||||
@ -161,9 +165,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
elseif u_type == RTU_UNIT_TYPE.SPS then
|
||||
-- super-critical phase shifter
|
||||
unit = svrs_sps.new(id, i, unit_advert, self.modbus_q)
|
||||
elseif u_type == RTU_UNIT_TYPE.SNA then
|
||||
-- solar neutron activator
|
||||
unit = svrs_sna.new(id, i, unit_advert, self.modbus_q)
|
||||
if type(unit) ~= "nil" then facility.add_sps(unit) end
|
||||
elseif u_type == RTU_UNIT_TYPE.ENV_DETECTOR then
|
||||
-- environment detector
|
||||
unit = svrs_envd.new(id, i, unit_advert, self.modbus_q)
|
||||
|
@ -21,7 +21,7 @@ local supervisor = require("supervisor.supervisor")
|
||||
|
||||
local svsessions = require("supervisor.session.svsessions")
|
||||
|
||||
local SUPERVISOR_VERSION = "v0.18.0"
|
||||
local SUPERVISOR_VERSION = "v0.19.0"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
@ -12,6 +12,7 @@ local rsctl = require("supervisor.session.rsctl")
|
||||
local unit = {}
|
||||
|
||||
local WASTE_MODE = types.WASTE_MODE
|
||||
local WASTE = types.WASTE_PRODUCT
|
||||
local ALARM = types.ALARM
|
||||
local PRIO = types.ALARM_PRIORITY
|
||||
local ALARM_STATE = types.ALARM_STATE
|
||||
@ -71,7 +72,9 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
redstone = {},
|
||||
boilers = {},
|
||||
turbines = {},
|
||||
sna = {},
|
||||
envd = {},
|
||||
sna_prod_rate = 0,
|
||||
-- redstone control
|
||||
io_ctl = nil, ---@type rs_controller
|
||||
valves = {}, ---@type unit_valves
|
||||
@ -89,7 +92,7 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
damage_start = 0,
|
||||
damage_last = 0,
|
||||
damage_est_last = 0,
|
||||
waste_mode = WASTE_MODE.AUTO,
|
||||
waste_product = WASTE.PLUTONIUM, ---@type WASTE_PRODUCT
|
||||
status_text = { "UNKNOWN", "awaiting connection..." },
|
||||
-- logic for alarms
|
||||
had_reactor = false,
|
||||
@ -221,7 +224,8 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
degraded = false,
|
||||
blade_count = 0,
|
||||
br100 = 0,
|
||||
lim_br100 = 0
|
||||
lim_br100 = 0,
|
||||
waste_mode = WASTE_MODE.AUTO ---@type WASTE_MODE
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -341,6 +345,32 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
emer_cool = emer_cool
|
||||
}
|
||||
|
||||
-- route reactor waste for a given waste product
|
||||
---@param product WASTE_PRODUCT waste product to route valves for
|
||||
local function _set_waste_valves(product)
|
||||
self.waste_product = product
|
||||
|
||||
if product == WASTE.PLUTONIUM then
|
||||
-- route through plutonium generation
|
||||
waste_pu.open()
|
||||
waste_sna.close()
|
||||
waste_po.close()
|
||||
waste_sps.close()
|
||||
elseif product == WASTE.POLONIUM then
|
||||
-- route through polonium generation into pellets
|
||||
waste_pu.close()
|
||||
waste_sna.open()
|
||||
waste_po.open()
|
||||
waste_sps.close()
|
||||
elseif product == WASTE.ANTI_MATTER then
|
||||
-- route through polonium generation into SPS
|
||||
waste_pu.close()
|
||||
waste_sna.open()
|
||||
waste_po.close()
|
||||
waste_sps.open()
|
||||
end
|
||||
end
|
||||
|
||||
--#endregion
|
||||
|
||||
-- unlink disconnected units
|
||||
@ -378,7 +408,7 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
table.insert(self.redstone, rs_unit)
|
||||
|
||||
-- send or re-send waste settings
|
||||
public.set_waste(self.waste_mode)
|
||||
_set_waste_valves(self.waste_product)
|
||||
end
|
||||
|
||||
-- link a turbine RTU session
|
||||
@ -415,6 +445,12 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
end
|
||||
end
|
||||
|
||||
-- link a solar neutron activator RTU session
|
||||
---@param sna unit_session
|
||||
function public.add_sna(sna)
|
||||
table.insert(self.sna, sna)
|
||||
end
|
||||
|
||||
-- link an environment detector RTU session
|
||||
---@param envd unit_session
|
||||
function public.add_envd(envd)
|
||||
@ -427,6 +463,7 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
util.filter_table(self.redstone, function (s) return s.get_session_id() ~= session end)
|
||||
util.filter_table(self.boilers, function (s) return s.get_session_id() ~= session end)
|
||||
util.filter_table(self.turbines, function (s) return s.get_session_id() ~= session end)
|
||||
util.filter_table(self.sna, function (s) return s.get_session_id() ~= session end)
|
||||
util.filter_table(self.envd, function (s) return s.get_session_id() ~= session end)
|
||||
end
|
||||
|
||||
@ -448,6 +485,7 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
_unlink_disconnected_units(self.redstone)
|
||||
_unlink_disconnected_units(self.boilers)
|
||||
_unlink_disconnected_units(self.turbines)
|
||||
_unlink_disconnected_units(self.sna)
|
||||
_unlink_disconnected_units(self.envd)
|
||||
|
||||
-- update degraded state for auto control
|
||||
@ -577,6 +615,15 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
end
|
||||
end
|
||||
|
||||
-- set automatic waste product if mode is set to auto
|
||||
---@param product WASTE_PRODUCT waste product to generate
|
||||
function public.auto_set_waste(product)
|
||||
if self.db.control.waste_mode == WASTE_MODE.AUTO then
|
||||
self.waste_product = product
|
||||
_set_waste_valves(product)
|
||||
end
|
||||
end
|
||||
|
||||
--#endregion
|
||||
|
||||
-- OPERATIONS --
|
||||
@ -621,34 +668,18 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
end
|
||||
end
|
||||
|
||||
-- route reactor waste
|
||||
---@param mode WASTE_MODE waste handling mode
|
||||
function public.set_waste(mode)
|
||||
if mode == WASTE_MODE.AUTO then
|
||||
---@todo automatic waste routing
|
||||
self.waste_mode = mode
|
||||
elseif mode == WASTE_MODE.PLUTONIUM then
|
||||
-- route through plutonium generation
|
||||
self.waste_mode = mode
|
||||
waste_pu.open()
|
||||
waste_sna.close()
|
||||
waste_po.close()
|
||||
waste_sps.close()
|
||||
elseif mode == WASTE_MODE.POLONIUM then
|
||||
-- route through polonium generation into pellets
|
||||
self.waste_mode = mode
|
||||
waste_pu.close()
|
||||
waste_sna.open()
|
||||
waste_po.open()
|
||||
waste_sps.close()
|
||||
elseif mode == WASTE_MODE.ANTI_MATTER then
|
||||
-- route through polonium generation into SPS
|
||||
self.waste_mode = mode
|
||||
waste_pu.close()
|
||||
waste_sna.open()
|
||||
waste_po.close()
|
||||
waste_sps.open()
|
||||
else
|
||||
-- set waste processing mode
|
||||
---@param mode WASTE_MODE processing mode
|
||||
function public.set_waste_mode(mode)
|
||||
self.db.control.waste_mode = mode
|
||||
|
||||
if mode == WASTE_MODE.MANUAL_PLUTONIUM then
|
||||
_set_waste_valves(WASTE.PLUTONIUM)
|
||||
elseif mode == WASTE_MODE.MANUAL_POLONIUM then
|
||||
_set_waste_valves(WASTE.POLONIUM)
|
||||
elseif mode == WASTE_MODE.MANUAL_ANTI_MATTER then
|
||||
_set_waste_valves(WASTE.ANTI_MATTER)
|
||||
elseif mode > WASTE_MODE.MANUAL_ANTI_MATTER then
|
||||
log.debug(util.c("invalid waste mode setting ", mode))
|
||||
end
|
||||
end
|
||||
@ -730,6 +761,14 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
return status
|
||||
end
|
||||
|
||||
-- get the current burn rate (actual rate)
|
||||
---@nodiscard
|
||||
function public.get_burn_rate()
|
||||
local rate = 0
|
||||
if self.plc_i ~= nil then rate = self.plc_i.get_status().act_burn_rate end
|
||||
return rate or 0
|
||||
end
|
||||
|
||||
-- get RTU statuses
|
||||
---@nodiscard
|
||||
function public.get_rtu_statuses()
|
||||
@ -750,7 +789,7 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
-- status of turbines (including tanks)
|
||||
status.turbines = {}
|
||||
for i = 1, #self.turbines do
|
||||
local turbine = self.turbines[i] ---@type unit_session
|
||||
local turbine = self.turbines[i] ---@type unit_session
|
||||
status.turbines[turbine.get_device_idx()] = {
|
||||
turbine.is_faulted(),
|
||||
turbine.get_db().formed,
|
||||
@ -759,10 +798,13 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
}
|
||||
end
|
||||
|
||||
-- basic SNA statistical information, don't send everything, it's not necessary
|
||||
status.sna = { #self.sna, public.get_sna_rate() }
|
||||
|
||||
-- radiation monitors (environment detectors)
|
||||
status.rad_mon = {}
|
||||
for i = 1, #self.envd do
|
||||
local envd = self.envd[i] ---@type unit_session
|
||||
local envd = self.envd[i] ---@type unit_session
|
||||
status.rad_mon[envd.get_device_idx()] = {
|
||||
envd.is_faulted(),
|
||||
envd.get_db().radiation
|
||||
@ -772,6 +814,20 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
return status
|
||||
end
|
||||
|
||||
-- get the current total [max] production rate is
|
||||
---@nodiscard
|
||||
---@return number total_avail_rate
|
||||
function public.get_sna_rate()
|
||||
local total_avail_rate = 0
|
||||
|
||||
for i = 1, #self.sna do
|
||||
local db = self.sna[i].get_db() ---@type sna_session_db
|
||||
total_avail_rate = total_avail_rate + db.state.production_rate
|
||||
end
|
||||
|
||||
return total_avail_rate
|
||||
end
|
||||
|
||||
-- get the annunciator status
|
||||
---@nodiscard
|
||||
function public.get_annunciator() return self.db.annunciator end
|
||||
@ -787,7 +843,14 @@ function unit.new(reactor_id, num_boilers, num_turbines)
|
||||
-- get unit state
|
||||
---@nodiscard
|
||||
function public.get_state()
|
||||
return { self.status_text[1], self.status_text[2], self.waste_mode, self.db.control.ready, self.db.control.degraded }
|
||||
return {
|
||||
self.status_text[1],
|
||||
self.status_text[2],
|
||||
self.db.control.ready,
|
||||
self.db.control.degraded,
|
||||
self.db.control.waste_mode,
|
||||
self.waste_product
|
||||
}
|
||||
end
|
||||
|
||||
-- get the reactor ID
|
||||
|
Loading…
Reference in New Issue
Block a user