commit
c6343e5956
@ -28,6 +28,9 @@ def minify(path: str):
|
||||
contents = f.read()
|
||||
f.close()
|
||||
|
||||
# remove --[[@as type]] hints before anything, since it would detect as multiline comments
|
||||
contents = re.sub(r' --+\[.+]]', '', contents)
|
||||
|
||||
if re.search(r'--+\[+', contents) != None:
|
||||
# absolutely not dealing with lua multiline comments
|
||||
# - there are more important things to do
|
||||
|
||||
152
ccmsi.lua
152
ccmsi.lua
@ -15,7 +15,7 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]--
|
||||
|
||||
local CCMSI_VERSION = "v1.19"
|
||||
local CCMSI_VERSION = "v1.20"
|
||||
|
||||
local install_dir = "/.install-cache"
|
||||
local manifest_path = "https://mikaylafischler.github.io/cc-mek-scada/manifests/"
|
||||
@ -149,16 +149,16 @@ local function get_remote_manifest()
|
||||
end
|
||||
|
||||
-- record the local installation manifest
|
||||
local function write_install_manifest(manifest, dependencies)
|
||||
local function write_install_manifest(manifest, deps)
|
||||
local versions = {}
|
||||
for key, value in pairs(manifest.versions) do
|
||||
local is_dependency = false
|
||||
for _, dependency in pairs(dependencies) do
|
||||
if (key == "bootloader" and dependency == "system") or key == dependency then
|
||||
is_dependency = true;break
|
||||
local is_dep = false
|
||||
for _, dep in pairs(deps) do
|
||||
if (key == "bootloader" and dep == "system") or key == dep then
|
||||
is_dep = true;break
|
||||
end
|
||||
end
|
||||
if key == app or key == "comms" or is_dependency then versions[key] = value end
|
||||
if key == app or key == "comms" or is_dep then versions[key] = value end
|
||||
end
|
||||
|
||||
manifest.versions = versions
|
||||
@ -383,8 +383,10 @@ if mode == "check" then
|
||||
yellow();println("\nA different version of the installer is available, it is recommended to update (use 'ccmsi update installer').");white()
|
||||
end
|
||||
elseif mode == "install" or mode == "update" then
|
||||
local ok, r_manifest, l_manifest
|
||||
|
||||
local update_installer = app == "installer"
|
||||
local ok, manifest = get_remote_manifest()
|
||||
ok, r_manifest = get_remote_manifest()
|
||||
if not ok then return end
|
||||
|
||||
local ver = {
|
||||
@ -397,27 +399,27 @@ elseif mode == "install" or mode == "update" then
|
||||
}
|
||||
|
||||
-- try to find local versions
|
||||
local local_ok, lmnf = read_local_manifest()
|
||||
if not local_ok then
|
||||
if mode == "update" then
|
||||
ok, l_manifest = read_local_manifest()
|
||||
if mode == "update" and not update_installer then
|
||||
if not ok then
|
||||
red();println("Failed to load local installation information, cannot update.");white()
|
||||
return
|
||||
end
|
||||
elseif not update_installer then
|
||||
ver.boot.v_local = lmnf.versions.bootloader
|
||||
ver.app.v_local = lmnf.versions[app]
|
||||
ver.comms.v_local = lmnf.versions.comms
|
||||
ver.common.v_local = lmnf.versions.common
|
||||
ver.graphics.v_local = lmnf.versions.graphics
|
||||
ver.lockbox.v_local = lmnf.versions.lockbox
|
||||
else
|
||||
ver.boot.v_local = l_manifest.versions.bootloader
|
||||
ver.app.v_local = l_manifest.versions[app]
|
||||
ver.comms.v_local = l_manifest.versions.comms
|
||||
ver.common.v_local = l_manifest.versions.common
|
||||
ver.graphics.v_local = l_manifest.versions.graphics
|
||||
ver.lockbox.v_local = l_manifest.versions.lockbox
|
||||
|
||||
if lmnf.versions[app] == nil then
|
||||
if l_manifest.versions[app] == nil then
|
||||
red();println("Another application is already installed, please uninstall it before installing a new application.");white()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if manifest.versions.installer ~= CCMSI_VERSION then
|
||||
if r_manifest.versions.installer ~= CCMSI_VERSION then
|
||||
if not update_installer then yellow();println("A different version of the installer is available, it is recommended to update to it.");white() end
|
||||
if update_installer or ask_y_n("Would you like to update now", true) then
|
||||
lgray();println("GET ccmsi.lua")
|
||||
@ -440,12 +442,12 @@ elseif mode == "install" or mode == "update" then
|
||||
return
|
||||
end
|
||||
|
||||
ver.boot.v_remote = manifest.versions.bootloader
|
||||
ver.app.v_remote = manifest.versions[app]
|
||||
ver.comms.v_remote = manifest.versions.comms
|
||||
ver.common.v_remote = manifest.versions.common
|
||||
ver.graphics.v_remote = manifest.versions.graphics
|
||||
ver.lockbox.v_remote = manifest.versions.lockbox
|
||||
ver.boot.v_remote = r_manifest.versions.bootloader
|
||||
ver.app.v_remote = r_manifest.versions[app]
|
||||
ver.comms.v_remote = r_manifest.versions.comms
|
||||
ver.common.v_remote = r_manifest.versions.common
|
||||
ver.graphics.v_remote = r_manifest.versions.graphics
|
||||
ver.lockbox.v_remote = r_manifest.versions.lockbox
|
||||
|
||||
green()
|
||||
if mode == "install" then print("Installing ") else print("Updating ") end
|
||||
@ -461,36 +463,33 @@ elseif mode == "install" or mode == "update" then
|
||||
ver.graphics.changed = show_pkg_change("graphics", ver.graphics)
|
||||
ver.lockbox.changed = show_pkg_change("lockbox", ver.lockbox)
|
||||
|
||||
--------------------------
|
||||
-- START INSTALL/UPDATE --
|
||||
--------------------------
|
||||
-- start install/update
|
||||
|
||||
local space_required = manifest.sizes.manifest
|
||||
local space_available = fs.getFreeSpace("/")
|
||||
local space_req = r_manifest.sizes.manifest
|
||||
local space_avail = fs.getFreeSpace("/")
|
||||
|
||||
local single_file_mode = false
|
||||
local file_list = manifest.files
|
||||
local size_list = manifest.sizes
|
||||
local dependencies = manifest.depends[app]
|
||||
local file_list = r_manifest.files
|
||||
local size_list = r_manifest.sizes
|
||||
local deps = r_manifest.depends[app]
|
||||
|
||||
table.insert(dependencies, app)
|
||||
table.insert(deps, app)
|
||||
|
||||
-- helper function to check if a dependency is unchanged
|
||||
local function unchanged(dependency)
|
||||
if dependency == "system" then return not ver.boot.changed
|
||||
elseif dependency == "graphics" then return not ver.graphics.changed
|
||||
elseif dependency == "lockbox" then return not ver.lockbox.changed
|
||||
elseif dependency == "common" then return not (ver.common.changed or ver.comms.changed)
|
||||
elseif dependency == app then return not ver.app.changed
|
||||
local function unchanged(dep)
|
||||
if dep == "system" then return not ver.boot.changed
|
||||
elseif dep == "graphics" then return not ver.graphics.changed
|
||||
elseif dep == "lockbox" then return not ver.lockbox.changed
|
||||
elseif dep == "common" then return not (ver.common.changed or ver.comms.changed)
|
||||
elseif dep == app then return not ver.app.changed
|
||||
else return true end
|
||||
end
|
||||
|
||||
local any_change = false
|
||||
|
||||
for _, dependency in pairs(dependencies) do
|
||||
local size = size_list[dependency]
|
||||
space_required = space_required + size
|
||||
any_change = any_change or not unchanged(dependency)
|
||||
for _, dep in pairs(deps) do
|
||||
local size = size_list[dep]
|
||||
space_req = space_req + size
|
||||
any_change = any_change or not unchanged(dep)
|
||||
end
|
||||
|
||||
if mode == "update" and not any_change then
|
||||
@ -501,10 +500,7 @@ elseif mode == "install" or mode == "update" then
|
||||
-- ask for confirmation
|
||||
if not ask_y_n("Continue", false) then return end
|
||||
|
||||
-- check space constraints
|
||||
if space_available < space_required then
|
||||
single_file_mode = true
|
||||
end
|
||||
local single_file_mode = space_avail < space_req
|
||||
|
||||
local success = true
|
||||
|
||||
@ -548,7 +544,7 @@ elseif mode == "install" or mode == "update" then
|
||||
success = false
|
||||
return
|
||||
end
|
||||
clean(manifest)
|
||||
clean(r_manifest)
|
||||
sf_install(3)
|
||||
elseif attempt == 3 then
|
||||
yellow()
|
||||
@ -574,30 +570,30 @@ elseif mode == "install" or mode == "update" then
|
||||
local abort_attempt = false
|
||||
success = true
|
||||
|
||||
for _, dependency in pairs(dependencies) do
|
||||
if mode == "update" and unchanged(dependency) then
|
||||
pkg_message("skipping install of unchanged package", dependency)
|
||||
for _, dep in pairs(deps) do
|
||||
if mode == "update" and unchanged(dep) then
|
||||
pkg_message("skipping install of unchanged package", dep)
|
||||
else
|
||||
pkg_message("installing package", dependency)
|
||||
pkg_message("installing package", dep)
|
||||
lgray()
|
||||
|
||||
-- beginning on the second try, delete the directory before starting
|
||||
if attempt >= 2 then
|
||||
if dependency == "system" then
|
||||
elseif dependency == "common" then
|
||||
if dep == "system" then
|
||||
elseif dep == "common" then
|
||||
if fs.exists("/scada-common") then
|
||||
fs.delete("/scada-common")
|
||||
println("deleted /scada-common")
|
||||
end
|
||||
else
|
||||
if fs.exists("/"..dependency) then
|
||||
fs.delete("/"..dependency)
|
||||
println("deleted /"..dependency)
|
||||
if fs.exists("/"..dep) then
|
||||
fs.delete("/"..dep)
|
||||
println("deleted /"..dep)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local files = file_list[dependency]
|
||||
local files = file_list[dep]
|
||||
for _, file in pairs(files) do
|
||||
println("GET "..file)
|
||||
mitigate_case(file)
|
||||
@ -620,14 +616,14 @@ elseif mode == "install" or mode == "update" then
|
||||
if fs.exists(install_dir) then fs.delete(install_dir);fs.makeDir(install_dir) end
|
||||
|
||||
-- download all dependencies
|
||||
for _, dependency in pairs(dependencies) do
|
||||
if mode == "update" and unchanged(dependency) then
|
||||
pkg_message("skipping download of unchanged package", dependency)
|
||||
for _, dep in pairs(deps) do
|
||||
if mode == "update" and unchanged(dep) then
|
||||
pkg_message("skipping download of unchanged package", dep)
|
||||
else
|
||||
pkg_message("downloading package", dependency)
|
||||
pkg_message("downloading package", dep)
|
||||
lgray()
|
||||
|
||||
local files = file_list[dependency]
|
||||
local files = file_list[dep]
|
||||
for _, file in pairs(files) do
|
||||
println("GET "..file)
|
||||
local dl_stat = http_get_file(file, install_dir.."/")
|
||||
@ -650,14 +646,14 @@ elseif mode == "install" or mode == "update" then
|
||||
|
||||
-- copy in downloaded files (installation)
|
||||
if success then
|
||||
for _, dependency in pairs(dependencies) do
|
||||
if mode == "update" and unchanged(dependency) then
|
||||
pkg_message("skipping install of unchanged package", dependency)
|
||||
for _, dep in pairs(deps) do
|
||||
if mode == "update" and unchanged(dep) then
|
||||
pkg_message("skipping install of unchanged package", dep)
|
||||
else
|
||||
pkg_message("installing package", dependency)
|
||||
pkg_message("installing package", dep)
|
||||
lgray()
|
||||
|
||||
local files = file_list[dependency]
|
||||
local files = file_list[dep]
|
||||
for _, file in pairs(files) do
|
||||
local temp_file = install_dir.."/"..file
|
||||
if fs.exists(file) then fs.delete(file) end
|
||||
@ -671,13 +667,13 @@ elseif mode == "install" or mode == "update" then
|
||||
end
|
||||
|
||||
if success then
|
||||
write_install_manifest(manifest, dependencies)
|
||||
write_install_manifest(r_manifest, deps)
|
||||
green()
|
||||
if mode == "install" then
|
||||
println("Installation completed successfully.")
|
||||
else println("Update completed successfully.") end
|
||||
white();println("Ready to clean up unused files, press any key to continue...")
|
||||
any_key();clean(manifest)
|
||||
any_key();clean(r_manifest)
|
||||
white();println("Done.")
|
||||
else
|
||||
red()
|
||||
@ -712,14 +708,14 @@ elseif mode == "uninstall" then
|
||||
clean(manifest)
|
||||
|
||||
local file_list = manifest.files
|
||||
local dependencies = manifest.depends[app]
|
||||
local deps = manifest.depends[app]
|
||||
|
||||
table.insert(dependencies, app)
|
||||
table.insert(deps, app)
|
||||
|
||||
-- delete all installed files
|
||||
lgray()
|
||||
for _, dependency in pairs(dependencies) do
|
||||
local files = file_list[dependency]
|
||||
for _, dep in pairs(deps) do
|
||||
local files = file_list[dep]
|
||||
for _, file in pairs(files) do
|
||||
if fs.exists(file) then fs.delete(file);println("deleted "..file) end
|
||||
end
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
print("CONFIGURE> SCANNING FOR CONFIGURATOR...")
|
||||
|
||||
if fs.exists("reactor-plc/configure.lua") then require("reactor-plc.configure").configure()
|
||||
elseif fs.exists("rtu/configure.lua") then require("rtu.configure").configure()
|
||||
elseif fs.exists("supervisor/configure.lua") then require("supervisor.configure").configure()
|
||||
elseif fs.exists("coordinator/configure.lua") then require("coordinator.configure").configure()
|
||||
elseif fs.exists("pocket/configure.lua") then require("pocket.configure").configure()
|
||||
else
|
||||
print("CONFIGURE> NO CONFIGURATOR FOUND")
|
||||
print("CONFIGURE> EXIT")
|
||||
for _, app in ipairs({ "reactor-plc", "rtu", "supervisor", "coordinator", "pocket" }) do
|
||||
if fs.exists(app .. "/configure.lua") then
|
||||
local _, _, launch = require(app .. ".configure").configure()
|
||||
if launch then shell.execute("/startup") end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
print("CONFIGURE> NO CONFIGURATOR FOUND")
|
||||
print("CONFIGURE> EXIT")
|
||||
|
||||
@ -58,6 +58,7 @@ style.btn_dis_fg_bg = cpair(colors.lightGray,colors.white)
|
||||
local tool_ctl = {
|
||||
sv_cool_conf = nil, ---@type [ integer, integer ][] list of boiler & turbine counts
|
||||
|
||||
launch_startup = false,
|
||||
start_fail = 0,
|
||||
fail_message = "",
|
||||
has_config = false,
|
||||
@ -236,9 +237,17 @@ local function config_view(display)
|
||||
main_pane.set_value(8)
|
||||
end
|
||||
|
||||
local function startup()
|
||||
tool_ctl.launch_startup = true
|
||||
exit()
|
||||
end
|
||||
|
||||
PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg}
|
||||
tool_ctl.color_cfg = PushButton{parent=main_page,x=23,y=17,min_width=15,text="Color Options",callback=jump_color,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(10)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||
local start_btn = PushButton{parent=main_page,x=42,y=17,min_width=9,text="Startup",callback=startup,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
tool_ctl.color_cfg = PushButton{parent=main_page,x=36,y=y_start,min_width=15,text="Color Options",callback=jump_color,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
PushButton{parent=main_page,x=39,y=y_start+2,min_width=12,text="Change Log",callback=function()main_pane.set_value(10)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||
|
||||
if tool_ctl.start_fail ~= 0 then start_btn.disable() end
|
||||
|
||||
if not tool_ctl.has_config then
|
||||
tool_ctl.view_cfg.disable()
|
||||
@ -372,7 +381,7 @@ function configurator.configure(start_code, message)
|
||||
println("configurator error: " .. error)
|
||||
end
|
||||
|
||||
return status, error
|
||||
return status, error, tool_ctl.launch_startup
|
||||
end
|
||||
|
||||
return configurator
|
||||
|
||||
@ -94,7 +94,7 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale)
|
||||
auto_scram = false,
|
||||
---@type ascram_status
|
||||
ascram_status = {
|
||||
matrix_dc = false,
|
||||
matrix_fault = false,
|
||||
matrix_fill = false,
|
||||
crit_alarm = false,
|
||||
radiation = false,
|
||||
@ -105,6 +105,7 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale)
|
||||
auto_current_waste_product = types.WASTE_PRODUCT.PLUTONIUM,
|
||||
auto_pu_fallback_active = false,
|
||||
auto_sps_disabled = false,
|
||||
waste_stats = { 0, 0, 0, 0, 0, 0 }, -- waste in, pu, po, po pellets, am, spent waste
|
||||
|
||||
radiation = types.new_zero_radiation_reading(),
|
||||
|
||||
@ -118,6 +119,7 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale)
|
||||
induction_ps_tbl = {}, ---@type psil[]
|
||||
induction_data_tbl = {}, ---@type imatrix_session_db[]
|
||||
|
||||
sps_status = 1,
|
||||
sps_ps_tbl = {}, ---@type psil[]
|
||||
sps_data_tbl = {}, ---@type sps_session_db[]
|
||||
|
||||
@ -174,6 +176,7 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale)
|
||||
|
||||
waste_mode = types.WASTE_MODE.MANUAL_PLUTONIUM,
|
||||
waste_product = types.WASTE_PRODUCT.PLUTONIUM,
|
||||
waste_stats = { 0, 0, 0 }, -- plutonium, polonium, po pellets
|
||||
|
||||
last_rate_change_ms = 0,
|
||||
turbine_flow_stable = false,
|
||||
@ -540,7 +543,7 @@ function iocontrol.update_facility_status(status)
|
||||
fac.auto_saturated = ctl_status[5]
|
||||
|
||||
fac.auto_scram = ctl_status[6]
|
||||
fac.ascram_status.matrix_dc = ctl_status[7]
|
||||
fac.ascram_status.matrix_fault = ctl_status[7]
|
||||
fac.ascram_status.matrix_fill = ctl_status[8]
|
||||
fac.ascram_status.crit_alarm = ctl_status[9]
|
||||
fac.ascram_status.radiation = ctl_status[10]
|
||||
@ -555,7 +558,7 @@ function iocontrol.update_facility_status(status)
|
||||
fac.ps.publish("auto_ramping", fac.auto_ramping)
|
||||
fac.ps.publish("auto_saturated", fac.auto_saturated)
|
||||
fac.ps.publish("auto_scram", fac.auto_scram)
|
||||
fac.ps.publish("as_matrix_dc", fac.ascram_status.matrix_dc)
|
||||
fac.ps.publish("as_matrix_fault", fac.ascram_status.matrix_fault)
|
||||
fac.ps.publish("as_matrix_fill", fac.ascram_status.matrix_fill)
|
||||
fac.ps.publish("as_crit_alarm", fac.ascram_status.crit_alarm)
|
||||
fac.ps.publish("as_radiation", fac.ascram_status.radiation)
|
||||
@ -662,6 +665,8 @@ function iocontrol.update_facility_status(status)
|
||||
|
||||
-- SPS statuses
|
||||
if type(rtu_statuses.sps) == "table" then
|
||||
local sps_status = 1
|
||||
|
||||
for id = 1, #fac.sps_ps_tbl do
|
||||
if rtu_statuses.sps[id] == nil then
|
||||
-- disconnected
|
||||
@ -677,22 +682,21 @@ function iocontrol.update_facility_status(status)
|
||||
local rtu_faulted = _record_multiblock_status(sps, data, ps)
|
||||
|
||||
if rtu_faulted then
|
||||
ps.publish("computed_status", 3) -- faulted
|
||||
sps_status = 3 -- faulted
|
||||
elseif data.formed then
|
||||
if data.state.process_rate > 0 then
|
||||
ps.publish("computed_status", 5) -- active
|
||||
else
|
||||
ps.publish("computed_status", 4) -- idle
|
||||
end
|
||||
else
|
||||
ps.publish("computed_status", 2) -- not formed
|
||||
end
|
||||
-- active / idle
|
||||
sps_status = util.trinary(data.state.process_rate > 0, 5, 4)
|
||||
else sps_status = 2 end -- not formed
|
||||
|
||||
ps.publish("computed_status", sps_status)
|
||||
|
||||
io.facility.ps.publish("am_rate", data.state.process_rate * 1000)
|
||||
else
|
||||
log.debug(util.c(log_header, "invalid sps id ", id))
|
||||
end
|
||||
end
|
||||
|
||||
io.facility.sps_status = sps_status
|
||||
else
|
||||
log.debug(log_header .. "sps list not a table")
|
||||
valid = false
|
||||
@ -1192,6 +1196,7 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
local u_spent_rate = waste_rate
|
||||
local u_pu_rate = util.trinary(is_pu, waste_rate, 0.0)
|
||||
local u_po_rate = unit.sna_out_rate
|
||||
local u_po_pl_rate = 0
|
||||
|
||||
unit.unit_ps.publish("pu_rate", u_pu_rate)
|
||||
unit.unit_ps.publish("po_rate", u_po_rate)
|
||||
@ -1202,6 +1207,7 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
u_spent_rate = u_po_rate
|
||||
unit.unit_ps.publish("po_pl_rate", u_po_rate)
|
||||
unit.unit_ps.publish("po_am_rate", 0)
|
||||
u_po_pl_rate = u_po_rate
|
||||
po_pl_rate = po_pl_rate + u_po_rate
|
||||
elseif unit.waste_product == types.WASTE_PRODUCT.ANTI_MATTER then
|
||||
u_spent_rate = 0
|
||||
@ -1213,6 +1219,8 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
unit.unit_ps.publish("po_am_rate", 0)
|
||||
end
|
||||
|
||||
unit.waste_stats = { u_pu_rate, u_po_rate, u_po_pl_rate }
|
||||
|
||||
unit.unit_ps.publish("ws_rate", u_spent_rate)
|
||||
|
||||
pu_rate = pu_rate + u_pu_rate
|
||||
@ -1221,6 +1229,8 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
end
|
||||
end
|
||||
|
||||
io.facility.waste_stats = { burn_rate_sum, pu_rate, po_rate, po_pl_rate, po_am_rate, spent_rate }
|
||||
|
||||
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)
|
||||
|
||||
@ -445,36 +445,21 @@ end
|
||||
---@param product WASTE_PRODUCT waste product for auto control
|
||||
function process.set_process_waste(product)
|
||||
pctl.comms.send_fac_command(F_CMD.SET_WASTE_MODE, product)
|
||||
|
||||
log.debug(util.c("PROCESS: SET WASTE ", product))
|
||||
|
||||
-- update config table and save
|
||||
pctl.control_states.process.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)
|
||||
pctl.comms.send_fac_command(F_CMD.SET_PU_FB, enabled)
|
||||
|
||||
log.debug(util.c("PROCESS: SET PU FALLBACK ", enabled))
|
||||
|
||||
-- update config table and save
|
||||
pctl.control_states.process.pu_fallback = enabled
|
||||
_write_auto_config()
|
||||
end
|
||||
|
||||
-- set automatic process control SPS usage at low power
|
||||
---@param enabled boolean whether to enable SPS usage at low power
|
||||
function process.set_sps_low_power(enabled)
|
||||
pctl.comms.send_fac_command(F_CMD.SET_SPS_LP, enabled)
|
||||
|
||||
log.debug(util.c("PROCESS: SET SPS LOW POWER ", enabled))
|
||||
|
||||
-- update config table and save
|
||||
pctl.control_states.process.sps_low_power = enabled
|
||||
_write_auto_config()
|
||||
end
|
||||
|
||||
-- save process control settings
|
||||
@ -527,21 +512,30 @@ end
|
||||
-- record waste product settting after attempting to change it
|
||||
---@param response WASTE_PRODUCT supervisor waste product settting
|
||||
function process.waste_ack_handle(response)
|
||||
-- update config table and save
|
||||
pctl.control_states.process.waste_product = response
|
||||
_write_auto_config()
|
||||
|
||||
pctl.io.facility.ps.publish("process_waste_product", response)
|
||||
end
|
||||
|
||||
-- record plutonium fallback settting after attempting to change it
|
||||
---@param response boolean supervisor plutonium fallback settting
|
||||
function process.pu_fb_ack_handle(response)
|
||||
-- update config table and save
|
||||
pctl.control_states.process.pu_fallback = response
|
||||
_write_auto_config()
|
||||
|
||||
pctl.io.facility.ps.publish("process_pu_fallback", response)
|
||||
end
|
||||
|
||||
-- record SPS low power settting after attempting to change it
|
||||
---@param response boolean supervisor SPS low power settting
|
||||
function process.sps_lp_ack_handle(response)
|
||||
-- update config table and save
|
||||
pctl.control_states.process.sps_low_power = response
|
||||
_write_auto_config()
|
||||
|
||||
pctl.io.facility.ps.publish("process_sps_low_power", response)
|
||||
end
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
local comms = require("scada-common.comms")
|
||||
local log = require("scada-common.log")
|
||||
local mqueue = require("scada-common.mqueue")
|
||||
local types = require("scada-common.types")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local iocontrol = require("coordinator.iocontrol")
|
||||
@ -14,6 +15,9 @@ local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local FAC_COMMAND = comms.FAC_COMMAND
|
||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||
|
||||
local AUTO_GROUP = types.AUTO_GROUP
|
||||
local WASTE_MODE = types.WASTE_MODE
|
||||
|
||||
-- retry time constants in ms
|
||||
-- local INITIAL_WAIT = 1500
|
||||
-- local RETRY_PERIOD = 1000
|
||||
@ -166,8 +170,26 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
||||
log.info(log_tag .. "FAC ACK ALL ALARMS")
|
||||
self.proc_handle.fac_ack_alarms()
|
||||
elseif cmd == FAC_COMMAND.SET_WASTE_MODE then
|
||||
if pkt.length == 2 then
|
||||
log.info(util.c(log_tag, " SET WASTE ", pkt.data[2]))
|
||||
process.set_process_waste(pkt.data[2])
|
||||
else
|
||||
log.debug(log_tag .. "CRDN set waste mode packet length mismatch")
|
||||
end
|
||||
elseif cmd == FAC_COMMAND.SET_PU_FB then
|
||||
if pkt.length == 2 then
|
||||
log.info(util.c(log_tag, " SET PU FALLBACK ", pkt.data[2]))
|
||||
process.set_pu_fallback(pkt.data[2] == true)
|
||||
else
|
||||
log.debug(log_tag .. "CRDN set pu fallback packet length mismatch")
|
||||
end
|
||||
elseif cmd == FAC_COMMAND.SET_SPS_LP then
|
||||
if pkt.length == 2 then
|
||||
log.info(util.c(log_tag, " SET SPS LOW POWER ", pkt.data[2]))
|
||||
process.set_sps_low_power(pkt.data[2] == true)
|
||||
else
|
||||
log.debug(log_tag .. "CRDN set sps low power packet length mismatch")
|
||||
end
|
||||
else
|
||||
log.debug(log_tag .. "CRDN facility command unknown")
|
||||
end
|
||||
@ -192,20 +214,28 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
||||
log.info(util.c(log_tag, "UNIT[", uid, "] RESET RPS"))
|
||||
self.proc_handle.reset_rps(uid)
|
||||
elseif cmd == UNIT_COMMAND.SET_BURN then
|
||||
if pkt.length == 3 then
|
||||
if (pkt.length == 3) and (type(pkt.data[3]) == "number") then
|
||||
log.info(util.c(log_tag, "UNIT[", uid, "] SET BURN ", pkt.data[3]))
|
||||
process.set_rate(uid, pkt.data[3])
|
||||
else
|
||||
log.debug(log_tag .. "CRDN unit command burn rate missing option")
|
||||
end
|
||||
elseif cmd == UNIT_COMMAND.SET_WASTE then
|
||||
if (pkt.length == 3) and (type(pkt.data[3]) == "number") and
|
||||
(pkt.data[3] >= WASTE_MODE.AUTO) and (pkt.data[3] <= WASTE_MODE.MANUAL_ANTI_MATTER) then
|
||||
log.info(util.c(log_tag, "UNIT[", id, "] SET WASTE ", pkt.data[3]))
|
||||
process.set_unit_waste(uid, pkt.data[3])
|
||||
else
|
||||
log.debug(log_tag .. "CRDN unit command set waste missing/invalid option")
|
||||
end
|
||||
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
||||
log.info(util.c(log_tag, "UNIT[", uid, "] ACK ALL ALARMS"))
|
||||
self.proc_handle.ack_all_alarms(uid)
|
||||
elseif cmd == UNIT_COMMAND.ACK_ALARM then
|
||||
elseif cmd == UNIT_COMMAND.RESET_ALARM then
|
||||
elseif cmd == UNIT_COMMAND.SET_GROUP then
|
||||
if pkt.length == 3 then
|
||||
if (pkt.length == 3) and (type(pkt.data[3]) == "number") and
|
||||
(pkt.data[3] >= AUTO_GROUP.MANUAL) and (pkt.data[3] <= AUTO_GROUP.BACKUP) then
|
||||
log.info(util.c(log_tag, "UNIT[", uid, "] SET GROUP ", pkt.data[3]))
|
||||
process.set_group(uid, pkt.data[3])
|
||||
else
|
||||
@ -275,7 +305,6 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
||||
u.annunciator.AutoControl,
|
||||
u.a_group
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
_send(CRDN_TYPE.API_GET_CTRL, data)
|
||||
@ -310,6 +339,47 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
||||
}
|
||||
|
||||
_send(CRDN_TYPE.API_GET_PROC, data)
|
||||
elseif pkt.type == CRDN_TYPE.API_GET_WASTE then
|
||||
local data = {}
|
||||
|
||||
local fac = db.facility
|
||||
local proc = process.get_control_states().process
|
||||
|
||||
-- unit data
|
||||
for i = 1, #db.units do
|
||||
local u = db.units[i]
|
||||
|
||||
data[i] = {
|
||||
u.waste_mode,
|
||||
u.waste_product,
|
||||
u.num_snas,
|
||||
u.sna_peak_rate,
|
||||
u.sna_max_rate,
|
||||
u.sna_out_rate,
|
||||
u.waste_stats
|
||||
}
|
||||
end
|
||||
|
||||
local process_rate = 0
|
||||
|
||||
if fac.sps_data_tbl[1].state then
|
||||
process_rate = fac.sps_data_tbl[1].state.process_rate
|
||||
end
|
||||
|
||||
-- facility data
|
||||
data[#db.units + 1] = {
|
||||
fac.auto_current_waste_product,
|
||||
fac.auto_pu_fallback_active,
|
||||
fac.auto_sps_disabled,
|
||||
proc.waste_product,
|
||||
proc.pu_fallback,
|
||||
proc.sps_low_power,
|
||||
fac.waste_stats,
|
||||
fac.sps_status,
|
||||
process_rate
|
||||
}
|
||||
|
||||
_send(CRDN_TYPE.API_GET_WASTE, data)
|
||||
else
|
||||
log.debug(log_tag .. "handler received unsupported CRDN packet type " .. pkt.type)
|
||||
end
|
||||
|
||||
@ -19,7 +19,7 @@ local renderer = require("coordinator.renderer")
|
||||
local sounder = require("coordinator.sounder")
|
||||
local threads = require("coordinator.threads")
|
||||
|
||||
local COORDINATOR_VERSION = "v1.5.13"
|
||||
local COORDINATOR_VERSION = "v1.5.16"
|
||||
|
||||
local CHUNK_LOAD_DELAY_S = 30.0
|
||||
|
||||
|
||||
@ -94,14 +94,14 @@ local function new_view(root, x, y)
|
||||
main.line_break()
|
||||
|
||||
local auto_scram = IndicatorLight{parent=main,label="Automatic SCRAM",colors=ind_red,flash=true,period=period.BLINK_250_MS}
|
||||
local matrix_dc = IndicatorLight{parent=main,label="Matrix Disconnected",colors=ind_yel,flash=true,period=period.BLINK_500_MS}
|
||||
local matrix_flt = IndicatorLight{parent=main,label="Induction Matrix Fault",colors=ind_yel,flash=true,period=period.BLINK_500_MS}
|
||||
local matrix_fill = IndicatorLight{parent=main,label="Matrix Charge High",colors=ind_red,flash=true,period=period.BLINK_500_MS}
|
||||
local unit_crit = IndicatorLight{parent=main,label="Unit Critical Alarm",colors=ind_red,flash=true,period=period.BLINK_250_MS}
|
||||
local fac_rad_h = IndicatorLight{parent=main,label="Facility Radiation High",colors=ind_red,flash=true,period=period.BLINK_250_MS}
|
||||
local gen_fault = IndicatorLight{parent=main,label="Gen. Control Fault",colors=ind_yel,flash=true,period=period.BLINK_500_MS}
|
||||
|
||||
auto_scram.register(facility.ps, "auto_scram", auto_scram.update)
|
||||
matrix_dc.register(facility.ps, "as_matrix_dc", matrix_dc.update)
|
||||
matrix_flt.register(facility.ps, "as_matrix_fault", matrix_flt.update)
|
||||
matrix_fill.register(facility.ps, "as_matrix_fill", matrix_fill.update)
|
||||
unit_crit.register(facility.ps, "as_crit_alarm", unit_crit.update)
|
||||
fac_rad_h.register(facility.ps, "as_radiation", fac_rad_h.update)
|
||||
|
||||
@ -7,7 +7,7 @@ local flasher = require("graphics.flasher")
|
||||
|
||||
local core = {}
|
||||
|
||||
core.version = "2.4.5"
|
||||
core.version = "2.4.6"
|
||||
|
||||
core.flasher = flasher
|
||||
core.events = events
|
||||
|
||||
@ -6,6 +6,7 @@ local element = require("graphics.element")
|
||||
---@class checkbox_args
|
||||
---@field label string checkbox text
|
||||
---@field box_fg_bg cpair colors for checkbox
|
||||
---@field disable_fg_bg? cpair text colors when disabled
|
||||
---@field default? boolean default value
|
||||
---@field callback? function function to call on press
|
||||
---@field parent graphics_element
|
||||
@ -35,20 +36,27 @@ return function (args)
|
||||
local function draw()
|
||||
e.w_set_cur(1, 1)
|
||||
|
||||
local fgd, bkg = args.box_fg_bg.fgd, args.box_fg_bg.bkg
|
||||
|
||||
if (not e.enabled) and type(args.disable_fg_bg) == "table" then
|
||||
fgd = args.disable_fg_bg.bkg
|
||||
bkg = args.disable_fg_bg.fgd
|
||||
end
|
||||
|
||||
if e.value then
|
||||
-- show as selected
|
||||
e.w_set_fgd(args.box_fg_bg.bkg)
|
||||
e.w_set_bkg(args.box_fg_bg.fgd)
|
||||
e.w_set_fgd(bkg)
|
||||
e.w_set_bkg(fgd)
|
||||
e.w_write("\x88")
|
||||
e.w_set_fgd(args.box_fg_bg.fgd)
|
||||
e.w_set_fgd(fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
e.w_write("\x95")
|
||||
else
|
||||
-- show as unselected
|
||||
e.w_set_fgd(e.fg_bg.bkg)
|
||||
e.w_set_bkg(args.box_fg_bg.bkg)
|
||||
e.w_set_bkg(bkg)
|
||||
e.w_write("\x88")
|
||||
e.w_set_fgd(args.box_fg_bg.bkg)
|
||||
e.w_set_fgd(bkg)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
e.w_write("\x95")
|
||||
end
|
||||
@ -57,16 +65,18 @@ return function (args)
|
||||
-- write label text
|
||||
local function draw_label()
|
||||
if e.enabled and e.is_focused() then
|
||||
e.w_set_cur(3, 1)
|
||||
e.w_set_fgd(e.fg_bg.bkg)
|
||||
e.w_set_bkg(e.fg_bg.fgd)
|
||||
e.w_write(args.label)
|
||||
elseif (not e.enabled) and type(args.disable_fg_bg) == "table" then
|
||||
e.w_set_fgd(args.disable_fg_bg.fgd)
|
||||
e.w_set_bkg(args.disable_fg_bg.bkg)
|
||||
else
|
||||
e.w_set_cur(3, 1)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
e.w_write(args.label)
|
||||
end
|
||||
|
||||
e.w_set_cur(3, 1)
|
||||
e.w_write(args.label)
|
||||
end
|
||||
|
||||
-- handle mouse interaction
|
||||
@ -98,20 +108,20 @@ return function (args)
|
||||
draw()
|
||||
end
|
||||
|
||||
-- handle focus
|
||||
e.on_focused = draw_label
|
||||
e.on_unfocused = draw_label
|
||||
|
||||
-- handle enable
|
||||
e.on_enabled = draw_label
|
||||
e.on_disabled = draw_label
|
||||
|
||||
-- element redraw
|
||||
function e.redraw()
|
||||
draw()
|
||||
draw_label()
|
||||
end
|
||||
|
||||
-- handle focus
|
||||
e.on_focused = draw_label
|
||||
e.on_unfocused = draw_label
|
||||
|
||||
-- handle enable
|
||||
e.on_enabled = e.redraw
|
||||
e.on_disabled = e.redraw
|
||||
|
||||
---@class Checkbox:graphics_element
|
||||
local Checkbox, id = e.complete(true)
|
||||
|
||||
|
||||
@ -50,6 +50,7 @@ style.btn_dis_fg_bg = cpair(colors.lightGray, colors.white)
|
||||
|
||||
---@class _pkt_cfg_tool_ctl
|
||||
local tool_ctl = {
|
||||
launch_startup = false,
|
||||
ask_config = false,
|
||||
has_config = false,
|
||||
viewing_config = false,
|
||||
@ -162,8 +163,16 @@ local function config_view(display)
|
||||
|
||||
if not tool_ctl.has_config then tool_ctl.view_cfg.disable() end
|
||||
|
||||
local function startup()
|
||||
tool_ctl.launch_startup = true
|
||||
exit()
|
||||
end
|
||||
|
||||
PushButton{parent=main_page,x=2,y=18,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg}
|
||||
PushButton{parent=main_page,x=14,y=18,min_width=12,text="Change Log",callback=function()main_pane.set_value(6)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||
local start_btn = PushButton{parent=main_page,x=17,y=18,min_width=9,text="Startup",callback=startup,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
PushButton{parent=main_page,x=2,y=y_start+4,min_width=12,text="Change Log",callback=function()main_pane.set_value(6)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||
|
||||
if tool_ctl.ask_config then start_btn.disable() end
|
||||
|
||||
--#endregion
|
||||
|
||||
@ -254,7 +263,7 @@ function configurator.configure(ask_config)
|
||||
println("configurator error: " .. error)
|
||||
end
|
||||
|
||||
return status, error
|
||||
return status, error, tool_ctl.launch_startup
|
||||
end
|
||||
|
||||
return configurator
|
||||
|
||||
@ -94,7 +94,8 @@ function iocontrol.init_core(pkt_comms, nav, cfg)
|
||||
io.api = {
|
||||
get_unit = function (unit) comms.api__get_unit(unit) end,
|
||||
get_ctrl = function () comms.api__get_control() end,
|
||||
get_proc = function () comms.api__get_process() end
|
||||
get_proc = function () comms.api__get_process() end,
|
||||
get_waste = function () comms.api__get_waste() end
|
||||
}
|
||||
end
|
||||
|
||||
@ -148,7 +149,7 @@ function iocontrol.init_fac(conf)
|
||||
auto_scram = false,
|
||||
---@type ascram_status
|
||||
ascram_status = {
|
||||
matrix_dc = false,
|
||||
matrix_fault = false,
|
||||
matrix_fill = false,
|
||||
crit_alarm = false,
|
||||
radiation = false,
|
||||
@ -158,6 +159,8 @@ function iocontrol.init_fac(conf)
|
||||
---@type WASTE_PRODUCT
|
||||
auto_current_waste_product = types.WASTE_PRODUCT.PLUTONIUM,
|
||||
auto_pu_fallback_active = false,
|
||||
auto_sps_disabled = false,
|
||||
waste_stats = { 0, 0, 0, 0, 0, 0 }, -- waste in, pu, po, po pellets, am, spent waste
|
||||
|
||||
radiation = types.new_zero_radiation_reading(),
|
||||
|
||||
@ -217,6 +220,7 @@ function iocontrol.init_fac(conf)
|
||||
|
||||
last_rate_change_ms = 0,
|
||||
turbine_flow_stable = false,
|
||||
waste_stats = { 0, 0, 0 }, -- plutonium, polonium, po pellets
|
||||
|
||||
-- auto control group
|
||||
a_group = types.AUTO_GROUP.MANUAL,
|
||||
@ -908,7 +912,7 @@ function iocontrol.record_process_data(data)
|
||||
fac.ps.publish("auto_saturated", fac.auto_saturated)
|
||||
|
||||
fac.ps.publish("auto_scram", fac.auto_scram)
|
||||
fac.ps.publish("as_matrix_dc", fac.ascram_status.matrix_dc)
|
||||
fac.ps.publish("as_matrix_fault", fac.ascram_status.matrix_fault)
|
||||
fac.ps.publish("as_matrix_fill", fac.ascram_status.matrix_fill)
|
||||
fac.ps.publish("as_crit_alarm", fac.ascram_status.crit_alarm)
|
||||
fac.ps.publish("as_radiation", fac.ascram_status.radiation)
|
||||
@ -920,6 +924,65 @@ function iocontrol.record_process_data(data)
|
||||
fac.ps.publish("process_gen_target", f_data[5][4])
|
||||
end
|
||||
|
||||
-- update waste app with unit data from API_GET_WASTE
|
||||
---@param data table
|
||||
function iocontrol.record_waste_data(data)
|
||||
-- get unit data
|
||||
for u_id = 1, #io.units do
|
||||
local unit = io.units[u_id]
|
||||
local u_data = data[u_id]
|
||||
|
||||
unit.waste_mode = u_data[1]
|
||||
unit.waste_product = u_data[2]
|
||||
unit.num_snas = u_data[3]
|
||||
unit.sna_peak_rate = u_data[4]
|
||||
unit.sna_max_rate = u_data[5]
|
||||
unit.sna_out_rate = u_data[6]
|
||||
unit.waste_stats = u_data[7]
|
||||
|
||||
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)
|
||||
|
||||
unit.unit_ps.publish("sna_count", unit.num_snas)
|
||||
unit.unit_ps.publish("sna_peak_rate", unit.sna_peak_rate)
|
||||
unit.unit_ps.publish("sna_max_rate", unit.sna_max_rate)
|
||||
unit.unit_ps.publish("sna_out_rate", unit.sna_out_rate)
|
||||
|
||||
unit.unit_ps.publish("pu_rate", unit.waste_stats[1])
|
||||
unit.unit_ps.publish("po_rate", unit.waste_stats[2])
|
||||
unit.unit_ps.publish("po_pl_rate", unit.waste_stats[3])
|
||||
end
|
||||
|
||||
-- get facility data
|
||||
local fac = io.facility
|
||||
local f_data = data[#io.units + 1]
|
||||
|
||||
fac.auto_current_waste_product = f_data[1]
|
||||
fac.auto_pu_fallback_active = f_data[2]
|
||||
fac.auto_sps_disabled = f_data[3]
|
||||
|
||||
fac.ps.publish("current_waste_product", fac.auto_current_waste_product)
|
||||
fac.ps.publish("pu_fallback_active", fac.auto_pu_fallback_active)
|
||||
fac.ps.publish("sps_disabled_low_power", fac.auto_sps_disabled)
|
||||
|
||||
fac.ps.publish("process_waste_product", f_data[4])
|
||||
fac.ps.publish("process_pu_fallback", f_data[5])
|
||||
fac.ps.publish("process_sps_low_power", f_data[6])
|
||||
|
||||
fac.waste_stats = f_data[7]
|
||||
|
||||
fac.ps.publish("burn_sum", fac.waste_stats[1])
|
||||
fac.ps.publish("pu_rate", fac.waste_stats[2])
|
||||
fac.ps.publish("po_rate", fac.waste_stats[3])
|
||||
fac.ps.publish("po_pl_rate", fac.waste_stats[4])
|
||||
fac.ps.publish("po_am_rate", fac.waste_stats[5])
|
||||
fac.ps.publish("spent_waste_rate", fac.waste_stats[6])
|
||||
|
||||
fac.ps.publish("sps_computed_status", f_data[8])
|
||||
fac.ps.publish("sps_process_rate", f_data[9])
|
||||
end
|
||||
|
||||
-- get the IO controller database
|
||||
function iocontrol.get_db() return io end
|
||||
|
||||
|
||||
@ -89,13 +89,14 @@ local APP_ID = {
|
||||
UNITS = 3,
|
||||
CONTROL = 4,
|
||||
PROCESS = 5,
|
||||
GUIDE = 6,
|
||||
ABOUT = 7,
|
||||
WASTE = 6,
|
||||
GUIDE = 7,
|
||||
ABOUT = 8,
|
||||
-- diagnostic app pages
|
||||
ALARMS = 8,
|
||||
ALARMS = 9,
|
||||
-- other
|
||||
DUMMY = 9,
|
||||
NUM_APPS = 9
|
||||
DUMMY = 10,
|
||||
NUM_APPS = 10
|
||||
}
|
||||
|
||||
pocket.APP_ID = APP_ID
|
||||
@ -264,7 +265,8 @@ function pocket.init_nav(smem)
|
||||
|
||||
-- open an app
|
||||
---@param app_id POCKET_APP_ID
|
||||
function nav.open_app(app_id)
|
||||
---@param on_loaded? function
|
||||
function nav.open_app(app_id, on_loaded)
|
||||
-- reset help return on navigating out of an app
|
||||
if app_id == APP_ID.ROOT then self.help_return = nil end
|
||||
|
||||
@ -277,7 +279,7 @@ function pocket.init_nav(smem)
|
||||
app = self.apps[app_id]
|
||||
else self.loader_return = nil end
|
||||
|
||||
if not app.loaded then smem.q.mq_render.push_data(MQ__RENDER_DATA.LOAD_APP, app_id) end
|
||||
if not app.loaded then smem.q.mq_render.push_data(MQ__RENDER_DATA.LOAD_APP, { app_id, on_loaded }) end
|
||||
|
||||
self.cur_app = app_id
|
||||
self.pane.set_value(app_id)
|
||||
@ -360,10 +362,10 @@ function pocket.init_nav(smem)
|
||||
function nav.open_help(key)
|
||||
self.help_return = self.cur_app
|
||||
|
||||
nav.open_app(APP_ID.GUIDE)
|
||||
|
||||
local load = self.help_map[key]
|
||||
if load then load() end
|
||||
nav.open_app(APP_ID.GUIDE, function ()
|
||||
local show = self.help_map[key]
|
||||
if show then show() end
|
||||
end)
|
||||
end
|
||||
|
||||
-- link the help map from the guide app
|
||||
@ -565,6 +567,11 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav)
|
||||
if self.api.linked then _send_api(CRDN_TYPE.API_GET_PROC, {}) end
|
||||
end
|
||||
|
||||
-- coordinator get waste app data
|
||||
function public.api__get_waste()
|
||||
if self.api.linked then _send_api(CRDN_TYPE.API_GET_WASTE, {}) end
|
||||
end
|
||||
|
||||
-- send a facility command
|
||||
---@param cmd FAC_COMMAND command
|
||||
---@param option any? optional option options for the optional options (like waste mode)
|
||||
@ -733,6 +740,10 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav)
|
||||
if _check_length(packet, #iocontrol.get_db().units + 1) then
|
||||
iocontrol.record_process_data(packet.data)
|
||||
end
|
||||
elseif packet.type == CRDN_TYPE.API_GET_WASTE then
|
||||
if _check_length(packet, #iocontrol.get_db().units + 1) then
|
||||
iocontrol.record_waste_data(packet.data)
|
||||
end
|
||||
else _fail_type(packet) end
|
||||
else
|
||||
log.debug("discarding coordinator SCADA_CRDN packet before linked")
|
||||
|
||||
@ -85,6 +85,14 @@ function process.set_group(unit_id, group_id)
|
||||
log.debug(util.c("PROCESS: UNIT[", unit_id, "] SET GROUP ", group_id))
|
||||
end
|
||||
|
||||
-- set waste mode
|
||||
---@param id integer unit ID
|
||||
---@param mode integer waste mode
|
||||
function process.set_unit_waste(id, mode)
|
||||
self.comms.send_unit_command(U_CMD.SET_WASTE, id, mode)
|
||||
log.debug(util.c("PROCESS: UNIT[", id, "] SET WASTE ", mode))
|
||||
end
|
||||
|
||||
-- acknowledge all alarms
|
||||
---@param id integer unit ID
|
||||
function process.ack_all_alarms(id)
|
||||
@ -131,6 +139,27 @@ function process.process_stop()
|
||||
log.debug("PROCESS: STOP AUTO CTRL")
|
||||
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(F_CMD.SET_WASTE_MODE, product)
|
||||
log.debug(util.c("PROCESS: SET WASTE ", product))
|
||||
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(F_CMD.SET_PU_FB, enabled)
|
||||
log.debug(util.c("PROCESS: SET PU FALLBACK ", enabled))
|
||||
end
|
||||
|
||||
-- set automatic process control SPS usage at low power
|
||||
---@param enabled boolean whether to enable SPS usage at low power
|
||||
function process.set_sps_low_power(enabled)
|
||||
self.comms.send_fac_command(F_CMD.SET_SPS_LP, enabled)
|
||||
log.debug(util.c("PROCESS: SET SPS LOW POWER ", enabled))
|
||||
end
|
||||
|
||||
-- #endregion
|
||||
---------------------------------
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ local pocket = require("pocket.pocket")
|
||||
local renderer = require("pocket.renderer")
|
||||
local threads = require("pocket.threads")
|
||||
|
||||
local POCKET_VERSION = "v0.12.7-alpha"
|
||||
local POCKET_VERSION = "v0.12.10-alpha"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
||||
@ -165,15 +165,18 @@ function threads.thread__render(smem)
|
||||
local cmd = msg.message ---@type queue_data
|
||||
|
||||
if cmd.key == MQ__RENDER_DATA.LOAD_APP then
|
||||
log.debug("RENDER: load app " .. cmd.val)
|
||||
log.debug("RENDER: load app " .. cmd.val[1])
|
||||
|
||||
local draw_start = util.time_ms()
|
||||
|
||||
pkt_state.ui_ok, pkt_state.ui_error = pcall(function () nav.load_app(cmd.val) end)
|
||||
pkt_state.ui_ok, pkt_state.ui_error = pcall(function () nav.load_app(cmd.val[1]) end)
|
||||
if not pkt_state.ui_ok then
|
||||
log.fatal(util.c("RENDER: app load failed with error ", pkt_state.ui_error))
|
||||
else
|
||||
log.debug("RENDER: app loaded in " .. (util.time_ms() - draw_start) .. "ms")
|
||||
|
||||
-- call the on loaded function if provided
|
||||
if type(cmd.val[2]) == "function" then cmd.val[2]() end
|
||||
end
|
||||
end
|
||||
elseif msg.qtype == mqueue.TYPE.PACKET then
|
||||
|
||||
@ -269,7 +269,7 @@ local function new_view(root)
|
||||
local auto_scram = IconIndicator{parent=a_div,y=3,label="Automatic SCRAM",states=red_ind_s}
|
||||
|
||||
TextBox{parent=a_div,y=5,text="Induction Matrix",fg_bg=label_fg_bg}
|
||||
local matrix_dc = IconIndicator{parent=a_div,label="Disconnected",states=yel_ind_s}
|
||||
local matrix_flt = IconIndicator{parent=a_div,label="Matrix Fault",states=yel_ind_s}
|
||||
local matrix_fill = IconIndicator{parent=a_div,label="Charge High",states=red_ind_s}
|
||||
|
||||
TextBox{parent=a_div,y=9,text="Assigned Units",fg_bg=label_fg_bg}
|
||||
@ -282,7 +282,7 @@ local function new_view(root)
|
||||
local gen_fault = IconIndicator{parent=a_div,label="Control Fault",states=yel_ind_s}
|
||||
|
||||
auto_scram.register(f_ps, "auto_scram", auto_scram.update)
|
||||
matrix_dc.register(f_ps, "as_matrix_dc", matrix_dc.update)
|
||||
matrix_flt.register(f_ps, "as_matrix_fault", matrix_flt.update)
|
||||
matrix_fill.register(f_ps, "as_matrix_fill", matrix_fill.update)
|
||||
unit_crit.register(f_ps, "as_crit_alarm", unit_crit.update)
|
||||
fac_rad_h.register(f_ps, "as_radiation", fac_rad_h.update)
|
||||
|
||||
310
pocket/ui/apps/waste.lua
Normal file
310
pocket/ui/apps/waste.lua
Normal file
@ -0,0 +1,310 @@
|
||||
--
|
||||
-- Waste Control Page
|
||||
--
|
||||
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local iocontrol = require("pocket.iocontrol")
|
||||
local pocket = require("pocket.pocket")
|
||||
local process = require("pocket.process")
|
||||
|
||||
local style = require("pocket.ui.style")
|
||||
|
||||
local core = require("graphics.core")
|
||||
|
||||
local Div = require("graphics.elements.Div")
|
||||
local MultiPane = require("graphics.elements.MultiPane")
|
||||
local TextBox = require("graphics.elements.TextBox")
|
||||
|
||||
local WaitingAnim = require("graphics.elements.animations.Waiting")
|
||||
|
||||
local Checkbox = require("graphics.elements.controls.Checkbox")
|
||||
local PushButton = require("graphics.elements.controls.PushButton")
|
||||
local RadioButton = require("graphics.elements.controls.RadioButton")
|
||||
|
||||
local DataIndicator = require("graphics.elements.indicators.DataIndicator")
|
||||
local IconIndicator = require("graphics.elements.indicators.IconIndicator")
|
||||
local StateIndicator = require("graphics.elements.indicators.StateIndicator")
|
||||
|
||||
local ALIGN = core.ALIGN
|
||||
local cpair = core.cpair
|
||||
|
||||
local APP_ID = pocket.APP_ID
|
||||
|
||||
local label_fg_bg = style.label
|
||||
local text_fg = style.text_fg
|
||||
|
||||
local lu_col = style.label_unit_pair
|
||||
|
||||
local yel_ind_s = style.icon_states.yel_ind_s
|
||||
local wht_ind_s = style.icon_states.wht_ind_s
|
||||
|
||||
-- new waste control page view
|
||||
---@param root Container parent
|
||||
local function new_view(root)
|
||||
local db = iocontrol.get_db()
|
||||
|
||||
local frame = Div{parent=root,x=1,y=1}
|
||||
|
||||
local app = db.nav.register_app(APP_ID.WASTE, frame, nil, false, true)
|
||||
|
||||
local load_div = Div{parent=frame,x=1,y=1}
|
||||
local main = Div{parent=frame,x=1,y=1}
|
||||
|
||||
TextBox{parent=load_div,y=12,text="Loading...",alignment=ALIGN.CENTER}
|
||||
WaitingAnim{parent=load_div,x=math.floor(main.get_width()/2)-1,y=8,fg_bg=cpair(colors.brown,colors._INHERIT)}
|
||||
|
||||
local load_pane = MultiPane{parent=main,x=1,y=1,panes={load_div,main}}
|
||||
|
||||
app.set_sidebar({ { label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = db.nav.go_home } })
|
||||
|
||||
local page_div = nil ---@type Div|nil
|
||||
|
||||
-- load the app (create the elements)
|
||||
local function load()
|
||||
local f_ps = db.facility.ps
|
||||
|
||||
page_div = Div{parent=main,y=2,width=main.get_width()}
|
||||
|
||||
local panes = {} ---@type Div[]
|
||||
local u_pages = {} ---@type nav_tree_page[]
|
||||
|
||||
local last_update = 0
|
||||
-- refresh data callback, every 500ms it will re-send the query
|
||||
local function update()
|
||||
if util.time_ms() - last_update >= 500 then
|
||||
db.api.get_waste()
|
||||
last_update = util.time_ms()
|
||||
end
|
||||
end
|
||||
|
||||
--#region unit waste options/statistics
|
||||
|
||||
for i = 1, db.facility.num_units do
|
||||
local u_pane = Div{parent=page_div}
|
||||
local u_div = Div{parent=u_pane,x=2,width=main.get_width()-2}
|
||||
local unit = db.units[i]
|
||||
local u_ps = unit.unit_ps
|
||||
|
||||
table.insert(panes, u_div)
|
||||
|
||||
local u_page = app.new_page(nil, #panes)
|
||||
u_page.tasks = { update }
|
||||
|
||||
table.insert(u_pages, u_page)
|
||||
|
||||
TextBox{parent=u_div,y=1,text="Reactor Unit #"..i,alignment=ALIGN.CENTER}
|
||||
|
||||
local function set_waste(mode) process.set_unit_waste(i, mode) end
|
||||
|
||||
local waste_prod = StateIndicator{parent=u_div,x=16,y=3,states=style.waste.states_abbrv,value=1,min_width=6}
|
||||
local waste_mode = RadioButton{parent=u_div,y=3,options=style.waste.unit_opts,callback=set_waste,radio_colors=cpair(colors.lightGray,colors.gray),select_color=colors.white}
|
||||
|
||||
waste_prod.register(u_ps, "U_WasteProduct", waste_prod.update)
|
||||
waste_mode.register(u_ps, "U_WasteMode", waste_mode.set_value)
|
||||
|
||||
TextBox{parent=u_div,y=8,text="Plutonium (Pellets)",fg_bg=label_fg_bg}
|
||||
local pu = DataIndicator{parent=u_div,label="",format="%16.3f",value=0,unit="mB/t",lu_colors=lu_col,width=21,fg_bg=text_fg}
|
||||
TextBox{parent=u_div,y=11,text="Polonium",fg_bg=label_fg_bg}
|
||||
local po = DataIndicator{parent=u_div,label="",format="%16.3f",value=0,unit="mB/t",lu_colors=lu_col,width=21,fg_bg=text_fg}
|
||||
TextBox{parent=u_div,y=14,text="Polonium (Pellets)",fg_bg=label_fg_bg}
|
||||
local popl = DataIndicator{parent=u_div,label="",format="%16.3f",value=0,unit="mB/t",lu_colors=lu_col,width=21,fg_bg=text_fg}
|
||||
|
||||
pu.register(u_ps, "pu_rate", pu.update)
|
||||
po.register(u_ps, "po_rate", po.update)
|
||||
popl.register(u_ps, "po_pl_rate", popl.update)
|
||||
|
||||
local sna_div = Div{parent=u_pane,x=2,width=page_div.get_width()-2}
|
||||
table.insert(panes, sna_div)
|
||||
|
||||
local sps_page = app.new_page(u_page, #panes)
|
||||
sps_page.tasks = { update }
|
||||
|
||||
PushButton{parent=u_div,x=6,y=18,text="SNA DATA",min_width=12,fg_bg=cpair(colors.lightGray,colors.gray),active_fg_bg=cpair(colors.gray,colors.lightGray),callback=sps_page.nav_to}
|
||||
PushButton{parent=sna_div,x=9,y=18,text="BACK",min_width=6,fg_bg=cpair(colors.lightGray,colors.gray),active_fg_bg=cpair(colors.gray,colors.lightGray),callback=u_page.nav_to}
|
||||
|
||||
TextBox{parent=sna_div,y=1,text="Unit "..i.." SNAs",alignment=ALIGN.CENTER}
|
||||
TextBox{parent=sna_div,y=3,text="Connected",fg_bg=label_fg_bg}
|
||||
local count = DataIndicator{parent=sna_div,x=20,y=3,label="",format="%2d",value=0,unit="",lu_colors=lu_col,width=2,fg_bg=text_fg}
|
||||
|
||||
TextBox{parent=sna_div,y=5,text="Peak Possible Rate\n In\n Out",fg_bg=label_fg_bg}
|
||||
local peak_i = DataIndicator{parent=sna_div,x=6,y=6,label="",format="%11.2f",value=0,unit="mB/t",lu_colors=lu_col,width=17,fg_bg=text_fg}
|
||||
local peak_o = DataIndicator{parent=sna_div,x=6,label="",format="%11.2f",value=0,unit="mB/t",lu_colors=lu_col,width=17,fg_bg=text_fg}
|
||||
|
||||
TextBox{parent=sna_div,y=9,text="Current Maximum Rate\n In\n Out",fg_bg=label_fg_bg}
|
||||
local max_i = DataIndicator{parent=sna_div,x=6,y=10,label="",format="%11.2f",value=0,unit="mB/t",lu_colors=lu_col,width=17,fg_bg=text_fg}
|
||||
local max_o = DataIndicator{parent=sna_div,x=6,label="",format="%11.2f",value=0,unit="mB/t",lu_colors=lu_col,width=17,fg_bg=text_fg}
|
||||
|
||||
TextBox{parent=sna_div,y=13,text="Current Rate\n In\n Out",fg_bg=label_fg_bg}
|
||||
local cur_i = DataIndicator{parent=sna_div,x=6,y=14,label="",format="%11.2f",value=0,unit="mB/t",lu_colors=lu_col,width=17,fg_bg=text_fg}
|
||||
local cur_o = DataIndicator{parent=sna_div,x=6,label="",format="%11.2f",value=0,unit="mB/t",lu_colors=lu_col,width=17,fg_bg=text_fg}
|
||||
|
||||
count.register(u_ps, "sna_count", count.update)
|
||||
peak_i.register(u_ps, "sna_peak_rate", function (x) peak_i.update(x * 10) end)
|
||||
peak_o.register(u_ps, "sna_peak_rate", peak_o.update)
|
||||
max_i.register(u_ps, "sna_max_rate", function (x) max_i.update(x * 10) end)
|
||||
max_o.register(u_ps, "sna_max_rate", max_o.update)
|
||||
cur_i.register(u_ps, "sna_out_rate", function (x) cur_i.update(x * 10) end)
|
||||
cur_o.register(u_ps, "sna_out_rate", cur_o.update)
|
||||
end
|
||||
|
||||
--#endregion
|
||||
|
||||
--#region waste control page
|
||||
|
||||
local c_pane = Div{parent=page_div}
|
||||
local c_div = Div{parent=c_pane,x=2,width=main.get_width()-2}
|
||||
table.insert(panes, c_div)
|
||||
|
||||
local wst_ctrl = app.new_page(nil, #panes)
|
||||
wst_ctrl.tasks = { update }
|
||||
|
||||
TextBox{parent=c_div,y=1,text="Waste Control",alignment=ALIGN.CENTER}
|
||||
|
||||
local status = StateIndicator{parent=c_div,x=3,y=3,states=style.waste.states,value=1,min_width=17}
|
||||
local waste_prod = RadioButton{parent=c_div,y=5,options=style.waste.options,callback=process.set_process_waste,radio_colors=cpair(colors.lightGray,colors.gray),select_color=colors.white}
|
||||
|
||||
status.register(f_ps, "current_waste_product", status.update)
|
||||
waste_prod.register(f_ps, "process_waste_product", waste_prod.set_value)
|
||||
|
||||
local fb_active = IconIndicator{parent=c_div,y=9,label="Fallback Active",states=wht_ind_s}
|
||||
local sps_disabled = IconIndicator{parent=c_div,y=10,label="SPS Disabled LC",states=yel_ind_s}
|
||||
|
||||
fb_active.register(f_ps, "pu_fallback_active", fb_active.update)
|
||||
sps_disabled.register(f_ps, "sps_disabled_low_power", sps_disabled.update)
|
||||
|
||||
TextBox{parent=c_div,y=12,text="Nuclear Waste In",fg_bg=label_fg_bg}
|
||||
local sum_raw_waste = DataIndicator{parent=c_div,label="",format="%16.3f",value=0,unit="mB/t",lu_colors=lu_col,width=21,fg_bg=text_fg}
|
||||
|
||||
sum_raw_waste.register(f_ps, "burn_sum", sum_raw_waste.update)
|
||||
|
||||
TextBox{parent=c_div,y=15,text="Spent Waste Out",fg_bg=label_fg_bg}
|
||||
local sum_sp_waste = DataIndicator{parent=c_div,label="",format="%16.3f",value=0,unit="mB/t",lu_colors=lu_col,width=21,fg_bg=text_fg}
|
||||
|
||||
sum_sp_waste.register(f_ps, "spent_waste_rate", sum_sp_waste.update)
|
||||
|
||||
local stats_div = Div{parent=c_pane,x=2,width=page_div.get_width()-2}
|
||||
table.insert(panes, stats_div)
|
||||
|
||||
local stats_page = app.new_page(wst_ctrl, #panes)
|
||||
stats_page.tasks = { update }
|
||||
|
||||
PushButton{parent=c_div,x=6,y=18,text="PROD RATES",min_width=12,fg_bg=cpair(colors.lightGray,colors.gray),active_fg_bg=cpair(colors.gray,colors.lightGray),callback=stats_page.nav_to}
|
||||
PushButton{parent=stats_div,x=9,y=18,text="BACK",min_width=6,fg_bg=cpair(colors.lightGray,colors.gray),active_fg_bg=cpair(colors.gray,colors.lightGray),callback=wst_ctrl.nav_to}
|
||||
|
||||
TextBox{parent=stats_div,y=1,text="Production Rates",alignment=ALIGN.CENTER}
|
||||
|
||||
TextBox{parent=stats_div,y=3,text="Plutonium (Pellets)",fg_bg=label_fg_bg}
|
||||
local pu = DataIndicator{parent=stats_div,label="",format="%16.3f",value=0,unit="mB/t",lu_colors=lu_col,width=21,fg_bg=text_fg}
|
||||
TextBox{parent=stats_div,y=6,text="Polonium",fg_bg=label_fg_bg}
|
||||
local po = DataIndicator{parent=stats_div,label="",format="%16.3f",value=0,unit="mB/t",lu_colors=lu_col,width=21,fg_bg=text_fg}
|
||||
TextBox{parent=stats_div,y=9,text="Polonium (Pellets)",fg_bg=label_fg_bg}
|
||||
local popl = DataIndicator{parent=stats_div,label="",format="%16.3f",value=0,unit="mB/t",lu_colors=lu_col,width=21,fg_bg=text_fg}
|
||||
|
||||
pu.register(f_ps, "pu_rate", pu.update)
|
||||
po.register(f_ps, "po_rate", po.update)
|
||||
popl.register(f_ps, "po_pl_rate", popl.update)
|
||||
|
||||
TextBox{parent=stats_div,y=12,text="Antimatter",fg_bg=label_fg_bg}
|
||||
local am = DataIndicator{parent=stats_div,label="",format="%16d",value=0,unit="\xb5B/t",lu_colors=lu_col,width=21,fg_bg=text_fg}
|
||||
|
||||
am.register(f_ps, "sps_process_rate", function (r) am.update(r * 1000) end)
|
||||
|
||||
--#endregion
|
||||
|
||||
--#region waste options page
|
||||
|
||||
local o_pane = Div{parent=page_div}
|
||||
local o_div = Div{parent=o_pane,x=2,width=main.get_width()-2}
|
||||
table.insert(panes, o_pane)
|
||||
|
||||
local opt_page = app.new_page(nil, #panes)
|
||||
opt_page.tasks = { update }
|
||||
|
||||
TextBox{parent=o_div,y=1,text="Waste Options",alignment=ALIGN.CENTER}
|
||||
|
||||
local pu_fallback = Checkbox{parent=o_div,x=2,y=3,label="Pu Fallback",callback=process.set_pu_fallback,box_fg_bg=cpair(colors.white,colors.gray)}
|
||||
|
||||
TextBox{parent=o_div,x=2,y=5,height=3,text="Switch to Pu when SNAs cannot keep up with waste.",fg_bg=label_fg_bg}
|
||||
|
||||
local lc_sps = Checkbox{parent=o_div,x=2,y=9,label="Low Charge SPS",callback=process.set_sps_low_power,box_fg_bg=cpair(colors.white,colors.gray)}
|
||||
|
||||
TextBox{parent=o_div,x=2,y=11,height=3,text="Use SPS at low charge, otherwise switches to Po.",fg_bg=label_fg_bg}
|
||||
|
||||
pu_fallback.register(f_ps, "process_pu_fallback", pu_fallback.set_value)
|
||||
lc_sps.register(f_ps, "process_sps_low_power", lc_sps.set_value)
|
||||
|
||||
--#endregion
|
||||
|
||||
--#region SPS page
|
||||
|
||||
local s_pane = Div{parent=page_div}
|
||||
local s_div = Div{parent=s_pane,x=2,width=main.get_width()-2}
|
||||
table.insert(panes, s_pane)
|
||||
|
||||
local sps_page = app.new_page(nil, #panes)
|
||||
sps_page.tasks = { update }
|
||||
|
||||
TextBox{parent=s_div,y=1,text="Facility SPS",alignment=ALIGN.CENTER}
|
||||
|
||||
local sps_status = StateIndicator{parent=s_div,x=5,y=3,states=style.sps.states,value=1,min_width=12}
|
||||
|
||||
sps_status.register(f_ps, "sps_computed_status", sps_status.update)
|
||||
|
||||
TextBox{parent=s_div,y=5,text="Input Rate",width=10,fg_bg=label_fg_bg}
|
||||
local sps_in = DataIndicator{parent=s_div,label="",format="%16.2f",value=0,unit="mB/t",lu_colors=lu_col,width=21,fg_bg=text_fg}
|
||||
|
||||
sps_in.register(f_ps, "po_am_rate", sps_in.update)
|
||||
|
||||
TextBox{parent=s_div,y=8,text="Production Rate",width=15,fg_bg=label_fg_bg}
|
||||
local sps_rate = DataIndicator{parent=s_div,label="",format="%16d",value=0,unit="\xb5B/t",lu_colors=lu_col,width=21,fg_bg=text_fg}
|
||||
|
||||
sps_rate.register(f_ps, "sps_process_rate", function (r) sps_rate.update(r * 1000) end)
|
||||
|
||||
--#endregion
|
||||
|
||||
-- setup multipane
|
||||
local u_pane = MultiPane{parent=page_div,x=1,y=1,panes=panes}
|
||||
app.set_root_pane(u_pane)
|
||||
|
||||
-- setup sidebar
|
||||
|
||||
local list = {
|
||||
{ label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = db.nav.go_home },
|
||||
{ label = "WST", color = core.cpair(colors.black, colors.brown), callback = wst_ctrl.nav_to },
|
||||
{ label = "OPT", color = core.cpair(colors.black, colors.white), callback = opt_page.nav_to },
|
||||
{ label = "SPS", color = core.cpair(colors.black, colors.purple), callback = sps_page.nav_to }
|
||||
}
|
||||
|
||||
for i = 1, db.facility.num_units do
|
||||
table.insert(list, { label = "U-" .. i, color = core.cpair(colors.black, colors.lightGray), callback = u_pages[i].nav_to })
|
||||
end
|
||||
|
||||
app.set_sidebar(list)
|
||||
|
||||
-- done, show the app
|
||||
wst_ctrl.nav_to()
|
||||
load_pane.set_value(2)
|
||||
end
|
||||
|
||||
-- delete the elements and switch back to the loading screen
|
||||
local function unload()
|
||||
if page_div then
|
||||
page_div.delete()
|
||||
page_div = nil
|
||||
end
|
||||
|
||||
app.set_sidebar({ { label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = db.nav.go_home } })
|
||||
app.delete_pages()
|
||||
|
||||
-- show loading screen
|
||||
load_pane.set_value(1)
|
||||
end
|
||||
|
||||
app.set_load(load)
|
||||
app.set_unload(unload)
|
||||
|
||||
return main
|
||||
end
|
||||
|
||||
return new_view
|
||||
@ -148,7 +148,7 @@ doc("auto_ramping", "Process Ramping", "Automatic process control is performing
|
||||
doc("auto_saturated", "Min/Max Burn Rate", "Auto control has either commanded 0 mB/t or the maximum total burn rate available (from assigned units).")
|
||||
sect("Automatic SCRAM")
|
||||
doc("auto_scram", "Automatic SCRAM", "Automatic control system SCRAM'ed the assigned reactors due to a safety hazard, shown by the below indicators.")
|
||||
doc("as_matrix_dc", "Matrix Disconnected", "Automatic SCRAM occurred due to loss of induction matrix connection.")
|
||||
doc("as_matrix_fault", "Matrix Fault", "Automatic SCRAM occurred due to the loss of the induction matrix connection, or the matrix being unformed or faulted.")
|
||||
doc("as_matrix_fill", "Matrix Charge High", "Automatic SCRAM occurred due to induction matrix charge exceeding acceptable limit.")
|
||||
doc("as_crit_alarm", "Unit Critical Alarm", "Automatic SCRAM occurred due to critical level unit alarm(s).")
|
||||
doc("as_radiation", "Facility Radiation High", "Automatic SCRAM occurred due to high facility radiation levels.")
|
||||
|
||||
@ -15,6 +15,7 @@ local loader_app = require("pocket.ui.apps.loader")
|
||||
local process_app = require("pocket.ui.apps.process")
|
||||
local sys_apps = require("pocket.ui.apps.sys_apps")
|
||||
local unit_app = require("pocket.ui.apps.unit")
|
||||
local waste_app = require("pocket.ui.apps.waste")
|
||||
|
||||
local home_page = require("pocket.ui.pages.home_page")
|
||||
|
||||
@ -66,6 +67,7 @@ local function init(main)
|
||||
unit_app(page_div)
|
||||
control_app(page_div)
|
||||
process_app(page_div)
|
||||
waste_app(page_div)
|
||||
guide_app(page_div)
|
||||
loader_app(page_div)
|
||||
sys_apps(page_div)
|
||||
|
||||
@ -49,7 +49,7 @@ local function new_view(root)
|
||||
App{parent=apps_1,x=9,y=2,text="F",title="Facil",callback=function()open(APP_ID.DUMMY)end,app_fg_bg=cpair(colors.black,colors.orange),active_fg_bg=active_fg_bg}
|
||||
App{parent=apps_1,x=16,y=2,text="\x15",title="Control",callback=function()open(APP_ID.CONTROL)end,app_fg_bg=cpair(colors.black,colors.green),active_fg_bg=active_fg_bg}
|
||||
App{parent=apps_1,x=2,y=7,text="\x17",title="Process",callback=function()open(APP_ID.PROCESS)end,app_fg_bg=cpair(colors.black,colors.purple),active_fg_bg=active_fg_bg}
|
||||
App{parent=apps_1,x=9,y=7,text="\x7f",title="Waste",callback=function()open(APP_ID.DUMMY)end,app_fg_bg=cpair(colors.black,colors.brown),active_fg_bg=active_fg_bg}
|
||||
App{parent=apps_1,x=9,y=7,text="\x7f",title="Waste",callback=function()open(APP_ID.WASTE)end,app_fg_bg=cpair(colors.black,colors.brown),active_fg_bg=active_fg_bg}
|
||||
App{parent=apps_1,x=16,y=7,text="\x08",title="Devices",callback=function()open(APP_ID.DUMMY)end,app_fg_bg=cpair(colors.black,colors.lightGray),active_fg_bg=active_fg_bg}
|
||||
App{parent=apps_1,x=2,y=12,text="\xb6",title="Guide",callback=function()open(APP_ID.GUIDE)end,app_fg_bg=cpair(colors.black,colors.cyan),active_fg_bg=active_fg_bg}
|
||||
App{parent=apps_1,x=9,y=12,text="?",title="About",callback=function()open(APP_ID.ABOUT)end,app_fg_bg=cpair(colors.black,colors.white),active_fg_bg=active_fg_bg}
|
||||
|
||||
@ -214,4 +214,66 @@ style.imatrix = {
|
||||
}
|
||||
}
|
||||
|
||||
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.white, 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 = { "Auto", "Plutonium", "Polonium", "Antimatter" }
|
||||
}
|
||||
|
||||
return style
|
||||
|
||||
@ -53,6 +53,7 @@ style.btn_dis_fg_bg = cpair(colors.lightGray, colors.white)
|
||||
|
||||
---@class _plc_cfg_tool_ctl
|
||||
local tool_ctl = {
|
||||
launch_startup = false,
|
||||
ask_config = false,
|
||||
has_config = false,
|
||||
viewing_config = false,
|
||||
@ -184,10 +185,18 @@ local function config_view(display)
|
||||
main_pane.set_value(5)
|
||||
end
|
||||
|
||||
local function startup()
|
||||
tool_ctl.launch_startup = true
|
||||
exit()
|
||||
end
|
||||
|
||||
PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg}
|
||||
PushButton{parent=main_page,x=10,y=17,min_width=12,text="Self-Check",callback=function()main_pane.set_value(8)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
tool_ctl.color_cfg = PushButton{parent=main_page,x=23,y=17,min_width=15,text="Color Options",callback=jump_color,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(7)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||
local start_btn = PushButton{parent=main_page,x=42,y=17,min_width=9,text="Startup",callback=startup,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
PushButton{parent=main_page,x=39,y=y_start,min_width=12,text="Self-Check",callback=function()main_pane.set_value(8)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
tool_ctl.color_cfg = PushButton{parent=main_page,x=36,y=y_start+2,min_width=15,text="Color Options",callback=jump_color,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
PushButton{parent=main_page,x=39,y=y_start+4,min_width=12,text="Change Log",callback=function()main_pane.set_value(7)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||
|
||||
if tool_ctl.ask_config then start_btn.disable() end
|
||||
|
||||
if not tool_ctl.has_config then
|
||||
tool_ctl.view_cfg.disable()
|
||||
@ -293,7 +302,7 @@ function configurator.configure(ask_config)
|
||||
println("configurator error: " .. error)
|
||||
end
|
||||
|
||||
return status, error
|
||||
return status, error, tool_ctl.launch_startup
|
||||
end
|
||||
|
||||
return configurator
|
||||
|
||||
@ -18,7 +18,7 @@ local plc = require("reactor-plc.plc")
|
||||
local renderer = require("reactor-plc.renderer")
|
||||
local threads = require("reactor-plc.threads")
|
||||
|
||||
local R_PLC_VERSION = "v1.8.12"
|
||||
local R_PLC_VERSION = "v1.8.13"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
||||
@ -39,6 +39,7 @@ local self = {
|
||||
rs_cfg_unit_l = nil, ---@type TextBox
|
||||
rs_cfg_unit = nil, ---@type NumberField
|
||||
rs_cfg_side_l = nil, ---@type TextBox
|
||||
rs_cfg_bundled = nil, ---@type Checkbox
|
||||
rs_cfg_color = nil, ---@type Radio2D
|
||||
rs_cfg_shortcut = nil ---@type TextBox
|
||||
}
|
||||
@ -195,6 +196,15 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
|
||||
local io_mode = rsio.get_io_mode(port)
|
||||
local inv = tri(rsio.digital_is_active(port, IO_LVL.LOW) == true, "inverted ", "")
|
||||
|
||||
if rsio.is_analog(port) then
|
||||
self.rs_cfg_bundled.set_value(false)
|
||||
self.rs_cfg_bundled.disable()
|
||||
self.rs_cfg_color.disable()
|
||||
else
|
||||
self.rs_cfg_bundled.enable()
|
||||
if self.rs_cfg_bundled.get_value() then self.rs_cfg_color.enable() else self.rs_cfg_color.disable() end
|
||||
end
|
||||
|
||||
if io_mode == IO_MODE.DIGITAL_IN then
|
||||
io_type = inv .. "digital input "
|
||||
elseif io_mode == IO_MODE.DIGITAL_OUT then
|
||||
@ -263,7 +273,7 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
|
||||
self.rs_cfg_shortcut = TextBox{parent=rs_c_3,x=1,y=9,height=4,text="This shortcut will add entries for each of the 4 waste outputs. If you select bundled, 4 colors will be assigned to the selected side. Otherwise, 4 default sides will be used."}
|
||||
self.rs_cfg_shortcut.hide(true)
|
||||
|
||||
local bundled = Checkbox{parent=rs_c_3,x=1,y=7,label="Is Bundled?",default=false,box_fg_bg=cpair(colors.red,colors.black),callback=set_bundled}
|
||||
self.rs_cfg_bundled = Checkbox{parent=rs_c_3,x=1,y=7,label="Is Bundled?",default=false,box_fg_bg=cpair(colors.red,colors.black),callback=set_bundled,disable_fg_bg=g_lg_fg_bg}
|
||||
self.rs_cfg_color = Radio2D{parent=rs_c_3,x=1,y=9,rows=4,columns=4,default=1,options=color_options,radio_colors=cpair(colors.lightGray,colors.black),color_map=color_options_map,disable_color=colors.gray,disable_fg_bg=g_lg_fg_bg}
|
||||
self.rs_cfg_color.disable()
|
||||
|
||||
@ -288,7 +298,7 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
|
||||
unit = tri(PORT_DSGN[port] == 1, u, nil),
|
||||
port = port,
|
||||
side = side_options_map[side.get_value()],
|
||||
color = tri(bundled.get_value(), color_options_map[self.rs_cfg_color.get_value()], nil)
|
||||
color = tri(self.rs_cfg_bundled.get_value() and rsio.is_digital(port), color_options_map[self.rs_cfg_color.get_value()], nil)
|
||||
}
|
||||
|
||||
if self.rs_cfg_editing == false then
|
||||
@ -304,8 +314,8 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
|
||||
table.insert(tmp_cfg.Redstone, {
|
||||
unit = tri(PORT_DSGN[IO.WASTE_PU + i] == 1, u, nil),
|
||||
port = IO.WASTE_PU + i,
|
||||
side = tri(bundled.get_value(), side_options_map[side.get_value()], default_sides[i + 1]),
|
||||
color = tri(bundled.get_value(), default_colors[i + 1], nil)
|
||||
side = tri(self.rs_cfg_bundled.get_value(), side_options_map[side.get_value()], default_sides[i + 1]),
|
||||
color = tri(self.rs_cfg_bundled.get_value(), default_colors[i + 1], nil)
|
||||
})
|
||||
end
|
||||
end
|
||||
@ -314,7 +324,7 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
|
||||
tool_ctl.gen_rs_summary()
|
||||
|
||||
side.set_value(1)
|
||||
bundled.set_value(false)
|
||||
self.rs_cfg_bundled.set_value(false)
|
||||
self.rs_cfg_color.set_value(1)
|
||||
self.rs_cfg_color.disable()
|
||||
else rs_err.show() end
|
||||
@ -356,6 +366,14 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
|
||||
text = text .. "the facility)."
|
||||
end
|
||||
|
||||
if rsio.is_analog(def.port) then
|
||||
self.rs_cfg_bundled.set_value(false)
|
||||
self.rs_cfg_bundled.disable()
|
||||
else
|
||||
self.rs_cfg_bundled.enable()
|
||||
self.rs_cfg_bundled.set_value(def.color ~= nil)
|
||||
end
|
||||
|
||||
local value = 1
|
||||
if def.color ~= nil then
|
||||
value = color_to_idx(def.color)
|
||||
@ -367,7 +385,6 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
|
||||
self.rs_cfg_selection.set_value(text)
|
||||
self.rs_cfg_side_l.set_value(tri(rsio.get_io_dir(def.port) == rsio.IO_DIR.IN, "Input Side", "Output Side"))
|
||||
side.set_value(side_to_idx(def.side))
|
||||
bundled.set_value(def.color ~= nil)
|
||||
self.rs_cfg_color.set_value(value)
|
||||
rs_pane.set_value(3)
|
||||
end
|
||||
|
||||
@ -55,6 +55,7 @@ style.btn_dis_fg_bg = cpair(colors.lightGray, colors.white)
|
||||
|
||||
---@class _rtu_cfg_tool_ctl
|
||||
local tool_ctl = {
|
||||
launch_startup = false,
|
||||
ask_config = false,
|
||||
has_config = false,
|
||||
viewing_config = false,
|
||||
@ -218,9 +219,17 @@ local function config_view(display)
|
||||
main_pane.set_value(5)
|
||||
end
|
||||
|
||||
local function startup()
|
||||
tool_ctl.launch_startup = true
|
||||
exit()
|
||||
end
|
||||
|
||||
PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg}
|
||||
tool_ctl.color_cfg = PushButton{parent=main_page,x=23,y=17,min_width=15,text="Color Options",callback=jump_color,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(7)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||
local start_btn = PushButton{parent=main_page,x=42,y=17,min_width=9,text="Startup",callback=startup,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
tool_ctl.color_cfg = PushButton{parent=main_page,x=36,y=y_start,min_width=15,text="Color Options",callback=jump_color,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
PushButton{parent=main_page,x=39,y=y_start+2,min_width=12,text="Change Log",callback=function()main_pane.set_value(7)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||
|
||||
if tool_ctl.ask_config then start_btn.disable() end
|
||||
|
||||
if not tool_ctl.has_config then
|
||||
tool_ctl.view_gw_cfg.disable()
|
||||
@ -346,7 +355,7 @@ function configurator.configure(ask_config)
|
||||
println("configurator error: " .. error)
|
||||
end
|
||||
|
||||
return status, error
|
||||
return status, error, tool_ctl.launch_startup
|
||||
end
|
||||
|
||||
return configurator
|
||||
|
||||
@ -31,7 +31,7 @@ local sna_rtu = require("rtu.dev.sna_rtu")
|
||||
local sps_rtu = require("rtu.dev.sps_rtu")
|
||||
local turbinev_rtu = require("rtu.dev.turbinev_rtu")
|
||||
|
||||
local RTU_VERSION = "v1.10.14"
|
||||
local RTU_VERSION = "v1.10.16"
|
||||
|
||||
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
|
||||
local RTU_HW_STATE = databus.RTU_HW_STATE
|
||||
|
||||
@ -17,8 +17,8 @@ local max_distance = nil
|
||||
local comms = {}
|
||||
|
||||
-- protocol/data versions (protocol/data independent changes tracked by util.lua version)
|
||||
comms.version = "3.0.1"
|
||||
comms.api_version = "0.0.6"
|
||||
comms.version = "3.0.2"
|
||||
comms.api_version = "0.0.7"
|
||||
|
||||
---@enum PROTOCOL
|
||||
local PROTOCOL = {
|
||||
@ -68,8 +68,9 @@ local CRDN_TYPE = {
|
||||
UNIT_CMD = 6, -- command a reactor unit
|
||||
API_GET_FAC = 7, -- API: get all the facility data
|
||||
API_GET_UNIT = 8, -- API: get reactor unit data
|
||||
API_GET_CTRL = 9, -- API: get data used for the control app
|
||||
API_GET_PROC = 10 -- API: get data used for the process app
|
||||
API_GET_CTRL = 9, -- API: get data for the control app
|
||||
API_GET_PROC = 10, -- API: get data for the process app
|
||||
API_GET_WASTE = 11 -- API: get data for the waste app
|
||||
}
|
||||
|
||||
---@enum ESTABLISH_ACK
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
local BOOTLOADER_VERSION = "1.1"
|
||||
local BOOTLOADER_VERSION = "1.2"
|
||||
|
||||
print("SCADA BOOTLOADER V" .. BOOTLOADER_VERSION)
|
||||
print("BOOT> SCANNING FOR APPLICATIONS...")
|
||||
|
||||
@ -51,6 +51,7 @@ style.btn_dis_fg_bg = cpair(colors.lightGray, colors.white)
|
||||
|
||||
---@class _svr_cfg_tool_ctl
|
||||
local tool_ctl = {
|
||||
launch_startup = false,
|
||||
ask_config = false,
|
||||
has_config = false,
|
||||
viewing_config = false,
|
||||
@ -201,9 +202,17 @@ local function config_view(display)
|
||||
main_pane.set_value(5)
|
||||
end
|
||||
|
||||
local function startup()
|
||||
tool_ctl.launch_startup = true
|
||||
exit()
|
||||
end
|
||||
|
||||
PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg}
|
||||
tool_ctl.color_cfg = PushButton{parent=main_page,x=23,y=17,min_width=15,text="Color Options",callback=jump_color,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(7)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||
local start_btn = PushButton{parent=main_page,x=42,y=17,min_width=9,text="Startup",callback=startup,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
tool_ctl.color_cfg = PushButton{parent=main_page,x=36,y=y_start,min_width=15,text="Color Options",callback=jump_color,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
|
||||
PushButton{parent=main_page,x=39,y=y_start+2,min_width=12,text="Change Log",callback=function()main_pane.set_value(7)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
|
||||
|
||||
if tool_ctl.ask_config then start_btn.disable() end
|
||||
|
||||
if not tool_ctl.has_config then
|
||||
tool_ctl.view_cfg.disable()
|
||||
@ -308,7 +317,7 @@ function configurator.configure(ask_config)
|
||||
println("configurator error: " .. error)
|
||||
end
|
||||
|
||||
return status, error
|
||||
return status, error, tool_ctl.launch_startup
|
||||
end
|
||||
|
||||
return configurator
|
||||
|
||||
@ -17,7 +17,7 @@ local WASTE = types.WASTE_PRODUCT
|
||||
---@enum AUTO_SCRAM
|
||||
local AUTO_SCRAM = {
|
||||
NONE = 0,
|
||||
MATRIX_DC = 1,
|
||||
MATRIX_FAULT = 1,
|
||||
MATRIX_FILL = 2,
|
||||
CRIT_ALARM = 3,
|
||||
RADIATION = 4,
|
||||
@ -81,7 +81,7 @@ function facility.new(config)
|
||||
ascram_reason = AUTO_SCRAM.NONE,
|
||||
---@class ascram_status
|
||||
ascram_status = {
|
||||
matrix_dc = false,
|
||||
matrix_fault = false,
|
||||
matrix_fill = false,
|
||||
crit_alarm = false,
|
||||
radiation = false,
|
||||
@ -91,8 +91,8 @@ function facility.new(config)
|
||||
charge_conversion = 1.0,
|
||||
time_start = 0.0,
|
||||
initial_ramp = true,
|
||||
waiting_on_ramp = false,
|
||||
waiting_on_stable = false,
|
||||
waiting_on_ramp = false, -- waiting on auto ramping
|
||||
waiting_on_stable = false, -- waiting on gen rate stabilization
|
||||
accumulator = 0.0,
|
||||
saturated = false,
|
||||
last_update = 0,
|
||||
@ -599,7 +599,7 @@ function facility.new(config)
|
||||
self.waiting_on_ramp or self.waiting_on_stable,
|
||||
self.at_max_burn or self.saturated,
|
||||
self.ascram,
|
||||
astat.matrix_dc,
|
||||
astat.matrix_fault,
|
||||
astat.matrix_fill,
|
||||
astat.crit_alarm,
|
||||
astat.radiation,
|
||||
|
||||
@ -341,9 +341,17 @@ function update.auto_control(ExtChargeIdling)
|
||||
if state_changed then
|
||||
self.time_start = now
|
||||
self.saturated = true
|
||||
self.waiting_on_ramp = true
|
||||
|
||||
self.status_text = { "MONITORED MODE", "ramping reactors to limit" }
|
||||
log.info("FAC: MAX_BURN process mode started")
|
||||
elseif self.waiting_on_ramp then
|
||||
if all_units_ramped() then
|
||||
self.waiting_on_ramp = false
|
||||
|
||||
self.status_text = { "MONITORED MODE", "running reactors at limit" }
|
||||
log.info("FAC: MAX_BURN process mode started")
|
||||
log.info("FAC: MAX_BURN process mode initial ramp completed")
|
||||
end
|
||||
end
|
||||
|
||||
allocate_burn_rate(self.max_burn_combined, true)
|
||||
@ -351,8 +359,17 @@ function update.auto_control(ExtChargeIdling)
|
||||
-- a total aggregate burn rate
|
||||
if state_changed then
|
||||
self.time_start = now
|
||||
self.status_text = { "BURN RATE MODE", "running" }
|
||||
self.waiting_on_ramp = true
|
||||
|
||||
self.status_text = { "BURN RATE MODE", "ramping to target" }
|
||||
log.info("FAC: BURN_RATE process mode started")
|
||||
elseif self.waiting_on_ramp then
|
||||
if all_units_ramped() then
|
||||
self.waiting_on_ramp = false
|
||||
|
||||
self.status_text = { "BURN RATE MODE", "running" }
|
||||
log.info("FAC: BURN_RATE process mode initial ramp completed")
|
||||
end
|
||||
end
|
||||
|
||||
local unallocated = allocate_burn_rate(self.burn_target, true)
|
||||
@ -511,13 +528,19 @@ function update.auto_safety()
|
||||
|
||||
local astatus = self.ascram_status
|
||||
|
||||
-- matrix related checks
|
||||
if self.induction[1] ~= nil then
|
||||
local db = self.induction[1].get_db()
|
||||
|
||||
-- clear matrix disconnected
|
||||
if astatus.matrix_dc then
|
||||
astatus.matrix_dc = false
|
||||
log.info("FAC: induction matrix reconnected, clearing ASCRAM condition")
|
||||
-- check for unformed or faulted state
|
||||
local i_ok = db.formed and not self.induction[1].is_faulted()
|
||||
|
||||
-- clear matrix fault if ok again
|
||||
if astatus.matrix_fault and i_ok then
|
||||
astatus.matrix_fault = false
|
||||
log.info("FAC: induction matrix OK, clearing ASCRAM condition")
|
||||
else
|
||||
astatus.matrix_fault = not i_ok
|
||||
end
|
||||
|
||||
-- check matrix fill too high
|
||||
@ -528,6 +551,13 @@ function update.auto_safety()
|
||||
log.info(util.c("FAC: charge state of induction matrix entered acceptable range <= ", ALARM_LIMS.CHARGE_RE_ENABLE * 100, "%"))
|
||||
end
|
||||
|
||||
-- system not ready, will need to restart GEN_RATE mode
|
||||
-- clears when we enter the fault waiting state
|
||||
astatus.gen_fault = self.mode == PROCESS.GEN_RATE and not self.units_ready
|
||||
else
|
||||
astatus.matrix_fault = true
|
||||
end
|
||||
|
||||
-- check for critical unit alarms
|
||||
astatus.crit_alarm = false
|
||||
for i = 1, #self.units do
|
||||
@ -555,15 +585,8 @@ function update.auto_safety()
|
||||
-- operator can restart the system or hit the stop/reset button
|
||||
end
|
||||
|
||||
-- system not ready, will need to restart GEN_RATE mode
|
||||
-- clears when we enter the fault waiting state
|
||||
astatus.gen_fault = self.mode == PROCESS.GEN_RATE and not self.units_ready
|
||||
else
|
||||
astatus.matrix_dc = true
|
||||
end
|
||||
|
||||
if (self.mode ~= PROCESS.INACTIVE) and (self.mode ~= PROCESS.SYSTEM_ALARM_IDLE) then
|
||||
local scram = astatus.matrix_dc or astatus.matrix_fill or astatus.crit_alarm or astatus.gen_fault
|
||||
local scram = astatus.matrix_fault or astatus.matrix_fill or astatus.crit_alarm or astatus.gen_fault
|
||||
|
||||
if scram and not self.ascram then
|
||||
-- SCRAM all units
|
||||
@ -587,14 +610,14 @@ function update.auto_safety()
|
||||
self.status_text = { "AUTOMATIC SCRAM", "facility radiation high" }
|
||||
|
||||
log.info("FAC: automatic SCRAM due to high facility radiation")
|
||||
elseif astatus.matrix_dc then
|
||||
elseif astatus.matrix_fault then
|
||||
next_mode = PROCESS.MATRIX_FAULT_IDLE
|
||||
self.ascram_reason = AUTO_SCRAM.MATRIX_DC
|
||||
self.status_text = { "AUTOMATIC SCRAM", "induction matrix disconnected" }
|
||||
self.ascram_reason = AUTO_SCRAM.MATRIX_FAULT
|
||||
self.status_text = { "AUTOMATIC SCRAM", "induction matrix fault" }
|
||||
|
||||
if self.mode ~= PROCESS.MATRIX_FAULT_IDLE then self.return_mode = self.mode end
|
||||
|
||||
log.info("FAC: automatic SCRAM due to induction matrix disconnection")
|
||||
log.info("FAC: automatic SCRAM due to induction matrix disconnected, unformed, or faulted")
|
||||
elseif astatus.matrix_fill then
|
||||
next_mode = PROCESS.MATRIX_FAULT_IDLE
|
||||
self.ascram_reason = AUTO_SCRAM.MATRIX_FILL
|
||||
|
||||
@ -278,13 +278,13 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim
|
||||
end
|
||||
elseif cmd == FAC_COMMAND.SET_PU_FB then
|
||||
if pkt.length == 2 then
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, facility.set_pu_fallback(pkt.data[2]) })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, facility.set_pu_fallback(pkt.data[2] == true) })
|
||||
else
|
||||
log.debug(log_tag .. "CRDN set pu fallback packet length mismatch")
|
||||
end
|
||||
elseif cmd == FAC_COMMAND.SET_SPS_LP then
|
||||
if pkt.length == 2 then
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, facility.set_sps_low_power(pkt.data[2]) })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, facility.set_sps_low_power(pkt.data[2] == true) })
|
||||
else
|
||||
log.debug(log_tag .. "CRDN set sps low power packet length mismatch")
|
||||
end
|
||||
|
||||
@ -22,7 +22,7 @@ local supervisor = require("supervisor.supervisor")
|
||||
|
||||
local svsessions = require("supervisor.session.svsessions")
|
||||
|
||||
local SUPERVISOR_VERSION = "v1.5.10"
|
||||
local SUPERVISOR_VERSION = "v1.5.17"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
||||
@ -986,7 +986,8 @@ function unit.new(reactor_id, num_boilers, num_turbines, ext_idle)
|
||||
local db = self.snas[i].get_db()
|
||||
total_peak = total_peak + db.state.peak_production
|
||||
total_avail = total_avail + db.state.production_rate
|
||||
total_out = total_out + math.min(db.tanks.input.amount / 10, db.state.production_rate)
|
||||
local out_from_in = util.trinary(db.tanks.input.amount >= 10, db.tanks.input.amount / 10, 0)
|
||||
total_out = total_out + math.min(out_from_in, db.state.production_rate)
|
||||
end
|
||||
status.sna = { #self.snas, total_peak, total_avail, total_out }
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user