mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
parent
e9562a140c
commit
fe71615c12
@ -116,6 +116,8 @@ function iocontrol.init(conf, comms)
|
||||
ALARM_STATE.INACTIVE -- turbine trip
|
||||
},
|
||||
|
||||
annunciator = {}, ---@type annunciator
|
||||
|
||||
reactor_ps = psil.create(),
|
||||
reactor_data = {}, ---@type reactor_db
|
||||
|
||||
@ -272,12 +274,23 @@ function iocontrol.update_facility_status(status)
|
||||
fac.auto_active = ctl_status[1] > 0
|
||||
fac.auto_ramping = ctl_status[2]
|
||||
fac.auto_scram = ctl_status[3]
|
||||
fac.auto_scram_cause = ctl_status[4]
|
||||
fac.status_line_1 = ctl_status[4]
|
||||
fac.status_line_2 = ctl_status[5]
|
||||
|
||||
fac.ps.publish("auto_active", fac.auto_active)
|
||||
fac.ps.publish("auto_ramping", fac.auto_ramping)
|
||||
fac.ps.publish("auto_scram", fac.auto_scram)
|
||||
fac.ps.publish("auto_scram_cause", fac.auto_scram_cause)
|
||||
fac.ps.publish("status_line_1", fac.status_line_1)
|
||||
fac.ps.publish("status_line_2", fac.status_line_2)
|
||||
|
||||
local group_map = ctl_status[6]
|
||||
|
||||
if (type(group_map) == "table") and (#group_map == fac.num_units) then
|
||||
local names = { "Manual", "Primary", "Secondary", "Tertiary", "Backup" }
|
||||
for i = 1, #group_map do
|
||||
io.units[i].reactor_ps.publish("auto_group", names[group_map[i] + 1])
|
||||
end
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "control status not a table")
|
||||
end
|
||||
@ -556,14 +569,14 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
|
||||
-- annunciator
|
||||
|
||||
local annunciator = status[3] ---@type annunciator
|
||||
unit.annunciator = status[3]
|
||||
|
||||
if type(annunciator) ~= "table" then
|
||||
annunciator = {}
|
||||
if type(unit.annunciator) ~= "table" then
|
||||
unit.annunciator = {}
|
||||
log.debug(log_header .. "annunciator state not a table")
|
||||
end
|
||||
|
||||
for key, val in pairs(annunciator) do
|
||||
for key, val in pairs(unit.annunciator) do
|
||||
if key == "TurbineTrip" then
|
||||
-- split up turbine trip table for all turbines and a general OR combination
|
||||
local trips = val
|
||||
|
@ -19,7 +19,7 @@ local iocontrol = require("coordinator.iocontrol")
|
||||
local renderer = require("coordinator.renderer")
|
||||
local sounder = require("coordinator.sounder")
|
||||
|
||||
local COORDINATOR_VERSION = "beta-v0.8.10"
|
||||
local COORDINATOR_VERSION = "beta-v0.8.11"
|
||||
|
||||
local print = util.print
|
||||
local println = util.println
|
||||
|
@ -160,7 +160,6 @@ local function init(parent, id)
|
||||
local plc_online = IndicatorLight{parent=annunciator,label="PLC Online",colors=cpair(colors.green,colors.red)}
|
||||
local plc_hbeat = IndicatorLight{parent=annunciator,label="PLC Heartbeat",colors=cpair(colors.white,colors.gray)}
|
||||
local r_active = IndicatorLight{parent=annunciator,label="Active",colors=cpair(colors.green,colors.gray)}
|
||||
---@todo auto control as info sent here
|
||||
local r_auto = IndicatorLight{parent=annunciator,label="Automatic Control",colors=cpair(colors.blue,colors.gray)}
|
||||
|
||||
annunciator.line_break()
|
||||
@ -171,6 +170,7 @@ local function init(parent, id)
|
||||
r_ps.subscribe("PLCOnline", plc_online.update)
|
||||
r_ps.subscribe("PLCHeartbeat", plc_hbeat.update)
|
||||
r_ps.subscribe("status", r_active.update)
|
||||
r_ps.subscribe("AutoControl", r_auto.update)
|
||||
|
||||
annunciator.line_break()
|
||||
|
||||
@ -328,18 +328,18 @@ local function init(parent, id)
|
||||
-- reactor controls --
|
||||
----------------------
|
||||
|
||||
local dis_colors = cpair(colors.white, colors.lightGray)
|
||||
|
||||
local burn_control = Div{parent=main,x=12,y=28,width=19,height=3,fg_bg=cpair(colors.gray,colors.white)}
|
||||
local burn_rate = SpinboxNumeric{parent=burn_control,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}
|
||||
TextBox{parent=burn_control,x=9,y=2,text="mB/t"}
|
||||
|
||||
local set_burn = function () unit.set_burn(burn_rate.get_value()) end
|
||||
PushButton{parent=burn_control,x=14,y=2,text="SET",min_width=5,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=set_burn}
|
||||
local set_burn_btn = PushButton{parent=burn_control,x=14,y=2,text="SET",min_width=5,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),dis_fg_bg=dis_colors,callback=set_burn}
|
||||
|
||||
r_ps.subscribe("burn_rate", burn_rate.set_value)
|
||||
r_ps.subscribe("max_burn", burn_rate.set_max)
|
||||
|
||||
local dis_colors = cpair(colors.white, colors.lightGray)
|
||||
|
||||
local start = HazardButton{parent=main,x=2,y=28,text="START",accent=colors.lightBlue,dis_colors=dis_colors,callback=unit.start,fg_bg=hzd_fg_bg}
|
||||
local ack_a = HazardButton{parent=main,x=12,y=32,text="ACK \x13",accent=colors.orange,dis_colors=dis_colors,callback=unit.ack_alarms,fg_bg=hzd_fg_bg}
|
||||
local scram = HazardButton{parent=main,x=2,y=32,text="SCRAM",accent=colors.yellow,dis_colors=dis_colors,callback=unit.scram,fg_bg=hzd_fg_bg}
|
||||
@ -352,7 +352,9 @@ local function init(parent, id)
|
||||
|
||||
local function start_button_en_check()
|
||||
if (unit.reactor_data ~= nil) and (unit.reactor_data.mek_status ~= nil) then
|
||||
local can_start = (not unit.reactor_data.mek_status.status) and (not unit.reactor_data.rps_tripped)
|
||||
local can_start = (not unit.reactor_data.mek_status.status) and
|
||||
(not unit.reactor_data.rps_tripped) and
|
||||
(not unit.annunciator.AutoControl)
|
||||
if can_start then start.enable() else start.disable() end
|
||||
end
|
||||
end
|
||||
@ -455,22 +457,55 @@ local function init(parent, id)
|
||||
|
||||
local ctl_opts = { "Manual", "Primary", "Secondary", "Tertiary", "Backup" }
|
||||
|
||||
RadioButton{parent=auto_div,options=ctl_opts,callback=function()end,radio_colors=cpair(colors.blue,colors.white),radio_bg=colors.gray}
|
||||
local group = RadioButton{parent=auto_div,options=ctl_opts,callback=function()end,radio_colors=cpair(colors.blue,colors.white),radio_bg=colors.gray}
|
||||
|
||||
auto_div.line_break()
|
||||
|
||||
PushButton{parent=auto_div,text="SET",x=4,min_width=5,fg_bg=cpair(colors.black,colors.white),active_fg_bg=cpair(colors.white,colors.gray),callback=function()end}
|
||||
local function set_group() unit.set_group(group.get_value() - 1) end
|
||||
|
||||
local set_grp_btn = PushButton{parent=auto_div,text="SET",x=4,min_width=5,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),dis_fg_bg=cpair(colors.gray,colors.white),callback=set_group}
|
||||
|
||||
auto_div.line_break()
|
||||
|
||||
TextBox{parent=auto_div,text="Prio. Group",height=1,width=11,fg_bg=style.label}
|
||||
local auto_grp = TextBox{parent=auto_div,text="Manual",height=1,width=11,fg_bg=bw_fg_bg}
|
||||
|
||||
r_ps.subscribe("auto_group", auto_grp.set_value)
|
||||
|
||||
auto_div.line_break()
|
||||
|
||||
local a_prm = IndicatorLight{parent=auto_div,label="Active",x=2,colors=cpair(colors.green,colors.gray)}
|
||||
local a_act = IndicatorLight{parent=auto_div,label="Active",x=2,colors=cpair(colors.green,colors.gray)}
|
||||
local a_stb = IndicatorLight{parent=auto_div,label="Standby",x=2,colors=cpair(colors.white,colors.gray)}
|
||||
|
||||
r_ps.subscribe("status", function (active)
|
||||
if unit.annunciator.AutoControl then
|
||||
a_act.update(active)
|
||||
a_stb.update(not active)
|
||||
else
|
||||
a_act.update(false)
|
||||
a_stb.update(false)
|
||||
end
|
||||
end)
|
||||
|
||||
-- enable and disable controls based on auto control state (start button is handled separately)
|
||||
r_ps.subscribe("AutoControl", function (auto_active)
|
||||
start_button_en_check()
|
||||
|
||||
if auto_active then
|
||||
burn_rate.disable()
|
||||
set_burn_btn.disable()
|
||||
set_grp_btn.disable()
|
||||
a_act.update(unit.reactor_data.mek_status.status == true)
|
||||
a_stb.update(unit.reactor_data.mek_status.status == false)
|
||||
else
|
||||
burn_rate.enable()
|
||||
set_burn_btn.enable()
|
||||
set_grp_btn.enable()
|
||||
a_act.update(false)
|
||||
a_stb.update(false)
|
||||
end
|
||||
end)
|
||||
|
||||
return main
|
||||
end
|
||||
|
||||
|
@ -10,6 +10,7 @@ local element = require("graphics.element")
|
||||
---@field callback function function to call on touch
|
||||
---@field min_width? integer text length + 2 if omitted
|
||||
---@field active_fg_bg? cpair foreground/background colors when pressed
|
||||
---@field dis_fg_bg? cpair foreground/background colors when disabled
|
||||
---@field parent graphics_element
|
||||
---@field id? string element id
|
||||
---@field x? integer 1 if omitted
|
||||
@ -61,8 +62,10 @@ local function push_button(args)
|
||||
-- show as unpressed in 0.25 seconds
|
||||
tcd.dispatch(0.25, function ()
|
||||
e.value = false
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
if e.enabled then
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
end
|
||||
draw()
|
||||
end)
|
||||
end
|
||||
@ -78,6 +81,26 @@ local function push_button(args)
|
||||
if val then e.handle_touch(core.events.touch("", 1, 1)) end
|
||||
end
|
||||
|
||||
-- show butten as enabled
|
||||
function e.enable()
|
||||
if args.dis_fg_bg ~= nil then
|
||||
e.value = false
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
draw()
|
||||
end
|
||||
end
|
||||
|
||||
-- show button as disabled
|
||||
function e.disable()
|
||||
if args.dis_fg_bg ~= nil then
|
||||
e.value = false
|
||||
e.window.setTextColor(args.dis_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(args.dis_fg_bg.bkg)
|
||||
draw()
|
||||
end
|
||||
end
|
||||
|
||||
-- initial draw
|
||||
draw()
|
||||
|
||||
|
@ -40,6 +40,7 @@ function facility.new(num_reactors, cooling_conf)
|
||||
units = {},
|
||||
induction = {},
|
||||
redstone = {},
|
||||
status_text = { "IDLE", "control inactive" },
|
||||
-- process control
|
||||
mode = PROCESS.INACTIVE,
|
||||
last_mode = PROCESS.INACTIVE,
|
||||
@ -103,36 +104,42 @@ function facility.new(num_reactors, cooling_conf)
|
||||
local unallocated = math.floor(burn_rate * 10)
|
||||
|
||||
-- go through alll priority groups
|
||||
for i = 1, #self.prio_defs and (unallocated > 0) do
|
||||
for i = 1, #self.prio_defs do
|
||||
local units = self.prio_defs[i]
|
||||
local split = math.floor(unallocated / #units)
|
||||
|
||||
local splits = {}
|
||||
for u = 1, #units do splits[u] = split end
|
||||
splits[#units] = splits[#units] + (unallocated % #units)
|
||||
if #units > 0 then
|
||||
local split = math.floor(unallocated / #units)
|
||||
|
||||
-- go through all reactor units in this group
|
||||
for u = 1, #units do
|
||||
local ctl = units[u].get_control_inf() ---@type unit_control
|
||||
local last = ctl.br10
|
||||
local splits = {}
|
||||
for u = 1, #units do splits[u] = split end
|
||||
splits[#units] = splits[#units] + (unallocated % #units)
|
||||
|
||||
if splits[u] <= ctl.lim_br10 then
|
||||
ctl.br10 = splits[u]
|
||||
else
|
||||
ctl.br10 = ctl.lim_br10
|
||||
-- go through all reactor units in this group
|
||||
for u = 1, #units do
|
||||
local ctl = units[u].get_control_inf() ---@type unit_control
|
||||
local last = ctl.br10
|
||||
|
||||
if u < #units then
|
||||
local remaining = #units - u
|
||||
split = math.floor(unallocated / remaining)
|
||||
for x = (u + 1), #units do splits[x] = split end
|
||||
splits[#units] = splits[#units] + (unallocated % remaining)
|
||||
if splits[u] <= ctl.lim_br10 then
|
||||
ctl.br10 = splits[u]
|
||||
else
|
||||
ctl.br10 = ctl.lim_br10
|
||||
|
||||
if u < #units then
|
||||
local remaining = #units - u
|
||||
split = math.floor(unallocated / remaining)
|
||||
for x = (u + 1), #units do splits[x] = split end
|
||||
splits[#units] = splits[#units] + (unallocated % remaining)
|
||||
end
|
||||
end
|
||||
|
||||
unallocated = unallocated - ctl.br10
|
||||
|
||||
if last ~= ctl.br10 then units[u].a_commit_br10(ramp) end
|
||||
end
|
||||
|
||||
unallocated = unallocated - ctl.br10
|
||||
|
||||
if last ~= ctl.br10 then units[u].a_commit_br10(ramp) end
|
||||
end
|
||||
|
||||
-- stop if fully allocated
|
||||
if unallocated <= 0 then break end
|
||||
end
|
||||
end
|
||||
|
||||
@ -216,19 +223,24 @@ function facility.new(num_reactors, cooling_conf)
|
||||
)
|
||||
|
||||
for _, u in pairs(self.prio_defs[i]) do
|
||||
blade_count = blade_count + u.get_db().blade_count
|
||||
blade_count = blade_count + u.get_control_inf().blade_count
|
||||
u.a_engage()
|
||||
self.max_burn_combined = self.max_burn_combined + (u.get_control_inf().lim_br10 / 10.0)
|
||||
end
|
||||
end
|
||||
|
||||
self.charge_conversion = blade_count * POWER_PER_BLADE
|
||||
|
||||
log.debug(util.c("FAC: starting auto control: chg_conv = ", self.charge_conversion, ", blade_count = ", blade_count, ", max_burn = ", self.max_burn_combined))
|
||||
elseif self.mode == PROCESS.INACTIVE then
|
||||
for i = 1, #self.prio_defs do
|
||||
for _, u in pairs(self.prio_defs[i]) do
|
||||
u.a_disengage()
|
||||
end
|
||||
end
|
||||
|
||||
self.status_text = { "IDLE", "control disengaged" }
|
||||
log.debug("FAC: disengaging auto control (now inactive)")
|
||||
end
|
||||
|
||||
self.initial_ramp = true
|
||||
@ -241,30 +253,43 @@ function facility.new(num_reactors, cooling_conf)
|
||||
-- run units at their last configured set point
|
||||
if state_changed then
|
||||
self.time_start = now
|
||||
---@todo will still need to ramp?
|
||||
log.debug(util.c("FAC: SIMPLE mode first call completed"))
|
||||
end
|
||||
elseif self.mode == PROCESS.BURN_RATE then
|
||||
-- a total aggregate burn rate
|
||||
if state_changed then
|
||||
-- nothing special to do
|
||||
self.status_text = { "BURN RATE MODE", "starting up" }
|
||||
log.debug(util.c("FAC: BURN_RATE mode first call completed"))
|
||||
elseif self.waiting_on_ramp and _all_units_ramped() then
|
||||
self.waiting_on_ramp = false
|
||||
self.time_start = now
|
||||
self.status_text = { "BURN RATE MODE", "running" }
|
||||
log.debug(util.c("FAC: BURN_RATE mode initial ramp completed"))
|
||||
end
|
||||
|
||||
if not self.waiting_on_ramp then
|
||||
_allocate_burn_rate(self.burn_target, self.initial_ramp)
|
||||
|
||||
if self.initial_ramp then
|
||||
self.status_text = { "BURN RATE MODE", "ramping reactors" }
|
||||
self.waiting_on_ramp = true
|
||||
log.debug(util.c("FAC: BURN_RATE mode allocated initial ramp"))
|
||||
end
|
||||
end
|
||||
elseif self.mode == PROCESS.CHARGE then
|
||||
-- target a level of charge
|
||||
local error = (self.charge_target - avg_charge) / self.charge_conversion
|
||||
|
||||
if state_changed then
|
||||
-- nothing special to do
|
||||
log.debug(util.c("FAC: CHARGE mode first call completed"))
|
||||
elseif self.waiting_on_ramp and _all_units_ramped() then
|
||||
self.waiting_on_ramp = false
|
||||
|
||||
self.time_start = now
|
||||
self.accumulator = 0
|
||||
log.debug(util.c("FAC: CHARGE mode initial ramp completed"))
|
||||
end
|
||||
|
||||
if not self.waiting_on_ramp then
|
||||
@ -311,11 +336,13 @@ function facility.new(num_reactors, cooling_conf)
|
||||
local sp_r = util.round(setpoint * 10.0) / 10.0
|
||||
|
||||
_allocate_burn_rate(sp_r, true)
|
||||
log.debug(util.c("FAC: GEN_RATE mode first call completed"))
|
||||
elseif self.waiting_on_ramp and _all_units_ramped() then
|
||||
self.waiting_on_ramp = false
|
||||
|
||||
self.time_start = now
|
||||
self.accumulator = 0
|
||||
log.debug(util.c("FAC: GEN_RATE mode initial ramp completed"))
|
||||
end
|
||||
|
||||
if not self.waiting_on_ramp then
|
||||
@ -346,6 +373,9 @@ function facility.new(num_reactors, cooling_conf)
|
||||
|
||||
_allocate_burn_rate(sp_c, false)
|
||||
end
|
||||
elseif self.mode ~= PROCESS.INACTIVE then
|
||||
log.error(util.c("FAC: unsupported process mode ", self.mode, ", switching to inactive"))
|
||||
self.mode = PROCESS.INACTIVE
|
||||
end
|
||||
|
||||
------------------------------
|
||||
@ -389,6 +419,9 @@ function facility.new(num_reactors, cooling_conf)
|
||||
self.ascram = true
|
||||
end
|
||||
end
|
||||
|
||||
-- update last mode
|
||||
self.last_mode = self.mode
|
||||
end
|
||||
|
||||
-- call the update function of all units in the facility
|
||||
@ -429,8 +462,9 @@ function facility.new(num_reactors, cooling_conf)
|
||||
|
||||
-- only allow changes if not running
|
||||
if self.mode == PROCESS.INACTIVE then
|
||||
if (type(config.mode) == "number") and (config.mode > PROCESS.INACTIVE) and (config.mode <= PROCESS.SIMPLE) then
|
||||
if (type(config.mode) == "number") and (config.mode > PROCESS.INACTIVE) and (config.mode <= PROCESS.GEN_RATE) then
|
||||
self.mode_set = config.mode
|
||||
log.debug("SET MODE " .. config.mode)
|
||||
end
|
||||
|
||||
if (type(config.burn_target) == "number") and config.burn_target >= 0.1 then
|
||||
@ -489,7 +523,7 @@ function facility.new(num_reactors, cooling_conf)
|
||||
util.filter_table(self.prio_defs[old_group], function (u) return u.get_id() ~= unit_id end)
|
||||
end
|
||||
|
||||
self.group_map[unit] = group
|
||||
self.group_map[unit_id] = group
|
||||
|
||||
-- add to group if not independent
|
||||
if group > 0 then
|
||||
@ -519,7 +553,9 @@ function facility.new(num_reactors, cooling_conf)
|
||||
self.mode,
|
||||
self.waiting_on_ramp,
|
||||
self.ascram,
|
||||
self.ascram_reason
|
||||
self.status_text[1],
|
||||
self.status_text[2],
|
||||
self.group_map
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -387,6 +387,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
self.db.annunciator.AutoControl = false
|
||||
if self.plc_i ~= nil then
|
||||
self.plc_i.auto_lock(false)
|
||||
self.db.control.br10 = 0
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -194,7 +194,7 @@ function logic.update_annunciator(self)
|
||||
local max_water_return_rate = 0
|
||||
|
||||
-- recompute blade count on the chance that it may have changed
|
||||
self.db.blade_count = 0
|
||||
self.db.control.blade_count = 0
|
||||
|
||||
-- go through turbines for stats and online
|
||||
for i = 1, #self.turbines do
|
||||
@ -204,7 +204,7 @@ function logic.update_annunciator(self)
|
||||
total_flow_rate = total_flow_rate + turbine.state.flow_rate
|
||||
total_input_rate = total_input_rate + turbine.state.steam_input_rate
|
||||
max_water_return_rate = max_water_return_rate + turbine.build.max_water_output
|
||||
self.db.blade_count = self.db.blade_count + turbine.build.blades
|
||||
self.db.control.blade_count = self.db.control.blade_count + turbine.build.blades
|
||||
|
||||
self.db.annunciator.TurbineOnline[session.get_device_idx()] = true
|
||||
end
|
||||
|
@ -14,7 +14,7 @@ local svsessions = require("supervisor.session.svsessions")
|
||||
local config = require("supervisor.config")
|
||||
local supervisor = require("supervisor.supervisor")
|
||||
|
||||
local SUPERVISOR_VERSION = "beta-v0.9.7"
|
||||
local SUPERVISOR_VERSION = "beta-v0.9.8"
|
||||
|
||||
local print = util.print
|
||||
local println = util.println
|
||||
|
Loading…
Reference in New Issue
Block a user