mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
fixed process controller assuming ramp complete if burn rate setpoint was identical to setpoint before process control start
This commit is contained in:
parent
ba8bfb6e14
commit
b5c70b0d37
@ -23,6 +23,8 @@ local io = {}
|
||||
function iocontrol.init(conf, comms)
|
||||
---@class ioctl_facility
|
||||
io.facility = {
|
||||
all_sys_ok = false,
|
||||
|
||||
auto_ready = false,
|
||||
auto_active = false,
|
||||
auto_ramping = false,
|
||||
@ -273,13 +275,15 @@ function iocontrol.update_facility_status(status)
|
||||
local ctl_status = status[1]
|
||||
|
||||
if type(ctl_status) == "table" then
|
||||
fac.auto_ready = ctl_status[1]
|
||||
fac.auto_active = ctl_status[2] > 0
|
||||
fac.auto_ramping = ctl_status[3]
|
||||
fac.auto_scram = ctl_status[4]
|
||||
fac.status_line_1 = ctl_status[5]
|
||||
fac.status_line_2 = ctl_status[6]
|
||||
fac.all_sys_ok = ctl_status[1]
|
||||
fac.auto_ready = ctl_status[2]
|
||||
fac.auto_active = ctl_status[3] > 0
|
||||
fac.auto_ramping = ctl_status[4]
|
||||
fac.auto_scram = ctl_status[5]
|
||||
fac.status_line_1 = ctl_status[6]
|
||||
fac.status_line_2 = ctl_status[7]
|
||||
|
||||
fac.ps.publish("all_sys_ok", fac.all_sys_ok)
|
||||
fac.ps.publish("auto_ready", fac.auto_ready)
|
||||
fac.ps.publish("auto_active", fac.auto_active)
|
||||
fac.ps.publish("auto_ramping", fac.auto_ramping)
|
||||
@ -287,12 +291,13 @@ function iocontrol.update_facility_status(status)
|
||||
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[7]
|
||||
local group_map = ctl_status[8]
|
||||
|
||||
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].unit_ps.publish("auto_group_id", group_map[i] + 1)
|
||||
io.units[i].a_group = group_map[i]
|
||||
io.units[i].unit_ps.publish("auto_group_id", group_map[i])
|
||||
io.units[i].unit_ps.publish("auto_group", names[group_map[i] + 1])
|
||||
end
|
||||
end
|
||||
|
@ -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.16"
|
||||
local COORDINATOR_VERSION = "beta-v0.8.17"
|
||||
|
||||
local print = util.print
|
||||
local println = util.println
|
||||
|
@ -50,10 +50,21 @@ local function new_view(root, x, y)
|
||||
|
||||
facility.scram_ack = scram.on_response
|
||||
|
||||
local auto_act = IndicatorLight{parent=main,y=5,label="Auto Active",colors=cpair(colors.green,colors.gray)}
|
||||
local auto_ramp = IndicatorLight{parent=main,label="Auto Ramping",colors=cpair(colors.white,colors.gray),flash=true,period=period.BLINK_250_MS}
|
||||
local auto_scram = IndicatorLight{parent=main,label="Auto SCRAM",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS}
|
||||
local all_ok = IndicatorLight{parent=main,y=5,label="Unit Systems Online",colors=cpair(colors.green,colors.red)}
|
||||
local ind_mat = IndicatorLight{parent=main,label="Induction Matrix",colors=cpair(colors.green,colors.gray)}
|
||||
local rad_mon = IndicatorLight{parent=main,label="Radiation Monitor",colors=cpair(colors.green,colors.gray)}
|
||||
|
||||
facility.ps.subscribe("all_sys_ok", all_ok.update)
|
||||
facility.induction_ps_tbl[1].subscribe("computed_status", function (status) ind_mat.update(status > 1) end)
|
||||
|
||||
main.line_break()
|
||||
|
||||
local auto_ready = IndicatorLight{parent=main,label="Configured Units Ready",colors=cpair(colors.green,colors.red)}
|
||||
local auto_act = IndicatorLight{parent=main,label="Process Active",colors=cpair(colors.green,colors.gray)}
|
||||
local auto_ramp = IndicatorLight{parent=main,label="Process Ramping",colors=cpair(colors.white,colors.gray),flash=true,period=period.BLINK_250_MS}
|
||||
local auto_scram = IndicatorLight{parent=main,label="Automatic SCRAM",colors=cpair(colors.red,colors.gray),flash=true,period=period.BLINK_250_MS}
|
||||
|
||||
facility.ps.subscribe("auto_ready", auto_ready.update)
|
||||
facility.ps.subscribe("auto_active", auto_act.update)
|
||||
facility.ps.subscribe("auto_ramping", auto_ramp.update)
|
||||
facility.ps.subscribe("auto_scram", auto_scram.update)
|
||||
|
@ -354,7 +354,7 @@ local function init(parent, id)
|
||||
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) and
|
||||
(not unit.annunciator.AutoControl)
|
||||
(unit.a_group == 0)
|
||||
if can_start then start.enable() else start.disable() end
|
||||
end
|
||||
end
|
||||
@ -459,7 +459,7 @@ local function init(parent, id)
|
||||
|
||||
local group = RadioButton{parent=auto_div,options=ctl_opts,callback=function()end,radio_colors=cpair(colors.blue,colors.white),radio_bg=colors.gray}
|
||||
|
||||
u_ps.subscribe("auto_group_id", group.set_value)
|
||||
u_ps.subscribe("auto_group_id", function (gid) group.set_value(gid + 1) end)
|
||||
|
||||
auto_div.line_break()
|
||||
|
||||
@ -485,18 +485,27 @@ local function init(parent, id)
|
||||
a_stb.update(unit.annunciator.AutoControl and (not active))
|
||||
end)
|
||||
|
||||
-- enable and disable controls based on group assignment
|
||||
u_ps.subscribe("auto_group_id", function (gid)
|
||||
start_button_en_check()
|
||||
|
||||
if gid == 0 then
|
||||
burn_rate.enable()
|
||||
set_burn_btn.enable()
|
||||
else
|
||||
burn_rate.disable()
|
||||
set_burn_btn.disable()
|
||||
end
|
||||
end)
|
||||
|
||||
-- enable and disable controls based on auto control state (start button is handled separately)
|
||||
u_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_stb.update(unit.reactor_data.mek_status.status == false)
|
||||
else
|
||||
burn_rate.enable()
|
||||
set_burn_btn.enable()
|
||||
set_grp_btn.enable()
|
||||
a_stb.update(false)
|
||||
end
|
||||
|
@ -88,33 +88,33 @@ local function init(monitor)
|
||||
-- testing
|
||||
---@fixme remove test code
|
||||
|
||||
ColorMap{parent=main,x=132,y=(main.height()-1)}
|
||||
ColorMap{parent=main,x=98,y=(main.height()-1)}
|
||||
|
||||
local audio = Div{parent=main,width=34,height=15,x=95,y=cnc_y_start}
|
||||
local audio = Div{parent=main,width=23,height=23,x=107,y=cnc_y_start}
|
||||
|
||||
PushButton{parent=audio,x=1,y=1,text="TEST 1",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_1}
|
||||
PushButton{parent=audio,x=1,text="TEST 2",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_2}
|
||||
PushButton{parent=audio,x=1,text="TEST 3",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_3}
|
||||
PushButton{parent=audio,x=1,text="TEST 4",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_4}
|
||||
PushButton{parent=audio,x=1,text="TEST 5",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_5}
|
||||
PushButton{parent=audio,x=1,text="TEST 6",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_6}
|
||||
PushButton{parent=audio,x=1,text="TEST 7",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_7}
|
||||
PushButton{parent=audio,x=1,text="TEST 8",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_8}
|
||||
PushButton{parent=audio,x=1,text="STOP",min_width=8,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.stop}
|
||||
PushButton{parent=audio,x=1,text="PSCALE",min_width=8,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_power_scale}
|
||||
PushButton{parent=audio,x=16,y=1,text="TEST 1",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_1}
|
||||
PushButton{parent=audio,x=16,text="TEST 2",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_2}
|
||||
PushButton{parent=audio,x=16,text="TEST 3",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_3}
|
||||
PushButton{parent=audio,x=16,text="TEST 4",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_4}
|
||||
PushButton{parent=audio,x=16,text="TEST 5",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_5}
|
||||
PushButton{parent=audio,x=16,text="TEST 6",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_6}
|
||||
PushButton{parent=audio,x=16,text="TEST 7",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_7}
|
||||
PushButton{parent=audio,x=16,text="TEST 8",min_width=8,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_8}
|
||||
PushButton{parent=audio,x=16,text="STOP",min_width=8,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.stop}
|
||||
PushButton{parent=audio,x=16,text="PSCALE",min_width=8,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_power_scale}
|
||||
|
||||
SwitchButton{parent=audio,x=11,y=1,text="CONTAINMENT BREACH",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_breach}
|
||||
SwitchButton{parent=audio,x=11,text="CONTAINMENT RADIATION",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_rad}
|
||||
SwitchButton{parent=audio,x=11,text="REACTOR LOST",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_lost}
|
||||
SwitchButton{parent=audio,x=11,text="CRITICAL DAMAGE",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_crit}
|
||||
SwitchButton{parent=audio,x=11,text="REACTOR DAMAGE",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_dmg}
|
||||
SwitchButton{parent=audio,x=11,text="REACTOR OVER TEMP",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_overtemp}
|
||||
SwitchButton{parent=audio,x=11,text="REACTOR HIGH TEMP",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_hightemp}
|
||||
SwitchButton{parent=audio,x=11,text="REACTOR WASTE LEAK",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_wasteleak}
|
||||
SwitchButton{parent=audio,x=11,text="REACTOR WASTE HIGH",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_highwaste}
|
||||
SwitchButton{parent=audio,x=11,text="RPS TRANSIENT",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_rps}
|
||||
SwitchButton{parent=audio,x=11,text="RCS TRANSIENT",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_rcs}
|
||||
SwitchButton{parent=audio,x=11,text="TURBINE TRIP",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_turbinet}
|
||||
SwitchButton{parent=audio,x=1,y=12,text="CONTAINMENT BREACH",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_breach}
|
||||
SwitchButton{parent=audio,x=1,text="CONTAINMENT RADIATION",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_rad}
|
||||
SwitchButton{parent=audio,x=1,text="REACTOR LOST",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_lost}
|
||||
SwitchButton{parent=audio,x=1,text="CRITICAL DAMAGE",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_crit}
|
||||
SwitchButton{parent=audio,x=1,text="REACTOR DAMAGE",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_dmg}
|
||||
SwitchButton{parent=audio,x=1,text="REACTOR OVER TEMP",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_overtemp}
|
||||
SwitchButton{parent=audio,x=1,text="REACTOR HIGH TEMP",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_hightemp}
|
||||
SwitchButton{parent=audio,x=1,text="REACTOR WASTE LEAK",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_wasteleak}
|
||||
SwitchButton{parent=audio,x=1,text="REACTOR WASTE HIGH",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_highwaste}
|
||||
SwitchButton{parent=audio,x=1,text="RPS TRANSIENT",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_rps}
|
||||
SwitchButton{parent=audio,x=1,text="RCS TRANSIENT",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_rcs}
|
||||
SwitchButton{parent=audio,x=1,text="TURBINE TRIP",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_turbinet}
|
||||
|
||||
local imatrix_1 = imatrix(main, 131, cnc_y_start, facility.induction_data_tbl[1], facility.induction_ps_tbl[1])
|
||||
|
||||
|
@ -68,7 +68,7 @@ function plc.rps_init(reactor, is_formed)
|
||||
formed = is_formed,
|
||||
force_disabled = false,
|
||||
tripped = false,
|
||||
trip_cause = "" ---@type rps_trip_cause
|
||||
trip_cause = "ok" ---@type rps_trip_cause
|
||||
}
|
||||
|
||||
---@class rps
|
||||
@ -410,6 +410,7 @@ function plc.comms(id, version, modem, local_port, server_port, reactor, rps, co
|
||||
scrammed = false,
|
||||
linked = false,
|
||||
resend_build = false,
|
||||
auto_ack_token = 0,
|
||||
status_cache = nil,
|
||||
max_burn_rate = nil
|
||||
}
|
||||
@ -656,6 +657,7 @@ function plc.comms(id, version, modem, local_port, server_port, reactor, rps, co
|
||||
(not self.scrammed), -- requested control state
|
||||
no_reactor, -- no reactor peripheral connected
|
||||
formed, -- reactor formed
|
||||
self.auto_ack_token, -- token to indicate auto command has been received before this status update
|
||||
heating_rate, -- heating rate
|
||||
mek_data -- mekanism status data
|
||||
}
|
||||
@ -808,10 +810,11 @@ function plc.comms(id, version, modem, local_port, server_port, reactor, rps, co
|
||||
_send_ack(packet.type, true)
|
||||
elseif packet.type == RPLC_TYPES.AUTO_BURN_RATE then
|
||||
-- automatic control requested a new burn rate
|
||||
if (packet.length == 2) and (type(packet.data[1]) == "number") then
|
||||
if (packet.length == 3) and (type(packet.data[1]) == "number") and (type(packet.data[3]) == "number") then
|
||||
local ack = AUTO_ACK.FAIL
|
||||
local burn_rate = math.floor(packet.data[1] * 10) / 10
|
||||
local ramp = packet.data[2]
|
||||
self.auto_ack_token = packet.data[3]
|
||||
|
||||
-- if no known max burn rate, check again
|
||||
if self.max_burn_rate == nil then
|
||||
|
@ -14,7 +14,7 @@ local config = require("reactor-plc.config")
|
||||
local plc = require("reactor-plc.plc")
|
||||
local threads = require("reactor-plc.threads")
|
||||
|
||||
local R_PLC_VERSION = "beta-v0.10.3"
|
||||
local R_PLC_VERSION = "beta-v0.10.4"
|
||||
|
||||
local print = util.print
|
||||
local println = util.println
|
||||
@ -169,6 +169,7 @@ local function main()
|
||||
log.debug("init> running without networking")
|
||||
end
|
||||
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
util.push_event("clock_start")
|
||||
|
||||
println("boot> completed")
|
||||
|
@ -25,7 +25,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 = "beta-v0.9.11"
|
||||
local RTU_VERSION = "beta-v0.9.12"
|
||||
|
||||
local rtu_t = types.rtu_t
|
||||
|
||||
@ -362,6 +362,10 @@ local function main()
|
||||
|
||||
table.insert(units, rtu_unit)
|
||||
|
||||
if not formed then
|
||||
log.debug(util.c("configure> device '", name, "' is not formed"))
|
||||
end
|
||||
|
||||
local for_message = "facility"
|
||||
if for_reactor > 0 then
|
||||
for_message = util.c("reactor ", for_reactor)
|
||||
|
@ -12,7 +12,7 @@ local rtu_t = types.rtu_t
|
||||
|
||||
local insert = table.insert
|
||||
|
||||
comms.version = "1.1.2"
|
||||
comms.version = "1.2.0"
|
||||
|
||||
---@alias PROTOCOLS integer
|
||||
local PROTOCOLS = {
|
||||
@ -140,11 +140,11 @@ function comms.scada_packet()
|
||||
local self = {
|
||||
modem_msg_in = nil,
|
||||
valid = false,
|
||||
raw = nil,
|
||||
seq_num = nil,
|
||||
protocol = nil,
|
||||
length = nil,
|
||||
payload = nil
|
||||
raw = { -1, -1, {} },
|
||||
seq_num = -1,
|
||||
protocol = -1,
|
||||
length = 0,
|
||||
payload = {}
|
||||
}
|
||||
|
||||
---@class scada_packet
|
||||
|
@ -110,73 +110,40 @@ function log.dmesg(msg, tag, tag_color)
|
||||
|
||||
local t_stamp = string.format("%12.2f", os.clock())
|
||||
local out = _log_sys.dmesg_out
|
||||
local out_w, out_h = out.getSize()
|
||||
|
||||
local lines = { msg }
|
||||
if out ~= nil then
|
||||
local out_w, out_h = out.getSize()
|
||||
|
||||
-- wrap if needed
|
||||
if string.len(msg) > out_w then
|
||||
local remaining = true
|
||||
local s_start = 1
|
||||
local s_end = out_w
|
||||
local i = 1
|
||||
local lines = { msg }
|
||||
|
||||
lines = {}
|
||||
-- wrap if needed
|
||||
if string.len(msg) > out_w then
|
||||
local remaining = true
|
||||
local s_start = 1
|
||||
local s_end = out_w
|
||||
local i = 1
|
||||
|
||||
while remaining do
|
||||
local line = string.sub(msg, s_start, s_end)
|
||||
lines = {}
|
||||
|
||||
if line == "" then
|
||||
remaining = false
|
||||
else
|
||||
lines[i] = line
|
||||
while remaining do
|
||||
local line = string.sub(msg, s_start, s_end)
|
||||
|
||||
s_start = s_end + 1
|
||||
s_end = s_end + out_w
|
||||
i = i + 1
|
||||
if line == "" then
|
||||
remaining = false
|
||||
else
|
||||
lines[i] = line
|
||||
|
||||
s_start = s_end + 1
|
||||
s_end = s_end + out_w
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- start output with tag and time, assuming we have enough width for this to be on one line
|
||||
local cur_x, cur_y = out.getCursorPos()
|
||||
-- start output with tag and time, assuming we have enough width for this to be on one line
|
||||
local cur_x, cur_y = out.getCursorPos()
|
||||
|
||||
if cur_x > 1 then
|
||||
if cur_y == out_h then
|
||||
out.scroll(1)
|
||||
out.setCursorPos(1, cur_y)
|
||||
else
|
||||
out.setCursorPos(1, cur_y + 1)
|
||||
end
|
||||
end
|
||||
|
||||
-- colored time
|
||||
local initial_color = out.getTextColor()
|
||||
out.setTextColor(colors.white)
|
||||
out.write("[")
|
||||
out.setTextColor(colors.lightGray)
|
||||
out.write(t_stamp)
|
||||
ts_coord.x2, ts_coord.y = out.getCursorPos()
|
||||
ts_coord.x2 = ts_coord.x2 - 1
|
||||
out.setTextColor(colors.white)
|
||||
out.write("] ")
|
||||
|
||||
-- print optionally colored tag
|
||||
if tag ~= "" then
|
||||
out.write("[")
|
||||
if tag_color then out.setTextColor(tag_color) end
|
||||
out.write(tag)
|
||||
out.setTextColor(colors.white)
|
||||
out.write("] ")
|
||||
end
|
||||
|
||||
out.setTextColor(initial_color)
|
||||
|
||||
-- output message
|
||||
for i = 1, #lines do
|
||||
cur_x, cur_y = out.getCursorPos()
|
||||
|
||||
if i > 1 and cur_x > 1 then
|
||||
if cur_x > 1 then
|
||||
if cur_y == out_h then
|
||||
out.scroll(1)
|
||||
out.setCursorPos(1, cur_y)
|
||||
@ -185,10 +152,46 @@ function log.dmesg(msg, tag, tag_color)
|
||||
end
|
||||
end
|
||||
|
||||
out.write(lines[i])
|
||||
end
|
||||
-- colored time
|
||||
local initial_color = out.getTextColor()
|
||||
out.setTextColor(colors.white)
|
||||
out.write("[")
|
||||
out.setTextColor(colors.lightGray)
|
||||
out.write(t_stamp)
|
||||
ts_coord.x2, ts_coord.y = out.getCursorPos()
|
||||
ts_coord.x2 = ts_coord.x2 - 1
|
||||
out.setTextColor(colors.white)
|
||||
out.write("] ")
|
||||
|
||||
_log(util.c("[", t_stamp, "] [", tag, "] ", msg))
|
||||
-- print optionally colored tag
|
||||
if tag ~= "" then
|
||||
out.write("[")
|
||||
if tag_color then out.setTextColor(tag_color) end
|
||||
out.write(tag)
|
||||
out.setTextColor(colors.white)
|
||||
out.write("] ")
|
||||
end
|
||||
|
||||
out.setTextColor(initial_color)
|
||||
|
||||
-- output message
|
||||
for i = 1, #lines do
|
||||
cur_x, cur_y = out.getCursorPos()
|
||||
|
||||
if i > 1 and cur_x > 1 then
|
||||
if cur_y == out_h then
|
||||
out.scroll(1)
|
||||
out.setCursorPos(1, cur_y)
|
||||
else
|
||||
out.setCursorPos(1, cur_y + 1)
|
||||
end
|
||||
end
|
||||
|
||||
out.write(lines[i])
|
||||
end
|
||||
|
||||
_log(util.c("[", t_stamp, "] [", tag, "] ", msg))
|
||||
end
|
||||
|
||||
return ts_coord
|
||||
end
|
||||
@ -204,52 +207,56 @@ function log.dmesg_working(msg, tag, tag_color)
|
||||
local out = _log_sys.dmesg_out
|
||||
local width = (ts_coord.x2 - ts_coord.x1) + 1
|
||||
|
||||
local initial_color = out.getTextColor()
|
||||
if out ~= nil then
|
||||
local initial_color = out.getTextColor()
|
||||
|
||||
local counter = 0
|
||||
local counter = 0
|
||||
|
||||
local function update(sec_remaining)
|
||||
local time = util.sprintf("%ds", sec_remaining)
|
||||
local available = width - (string.len(time) + 2)
|
||||
local progress = ""
|
||||
local function update(sec_remaining)
|
||||
local time = util.sprintf("%ds", sec_remaining)
|
||||
local available = width - (string.len(time) + 2)
|
||||
local progress = ""
|
||||
|
||||
out.setCursorPos(ts_coord.x1, ts_coord.y)
|
||||
out.write(" ")
|
||||
out.setCursorPos(ts_coord.x1, ts_coord.y)
|
||||
out.write(" ")
|
||||
|
||||
if counter % 4 == 0 then
|
||||
progress = "|"
|
||||
elseif counter % 4 == 1 then
|
||||
progress = "/"
|
||||
elseif counter % 4 == 2 then
|
||||
progress = "-"
|
||||
elseif counter % 4 == 3 then
|
||||
progress = "\\"
|
||||
if counter % 4 == 0 then
|
||||
progress = "|"
|
||||
elseif counter % 4 == 1 then
|
||||
progress = "/"
|
||||
elseif counter % 4 == 2 then
|
||||
progress = "-"
|
||||
elseif counter % 4 == 3 then
|
||||
progress = "\\"
|
||||
end
|
||||
|
||||
out.setTextColor(colors.blue)
|
||||
out.write(progress)
|
||||
out.setTextColor(colors.lightGray)
|
||||
out.write(util.spaces(available) .. time)
|
||||
out.setTextColor(initial_color)
|
||||
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
out.setTextColor(colors.blue)
|
||||
out.write(progress)
|
||||
out.setTextColor(colors.lightGray)
|
||||
out.write(util.spaces(available) .. time)
|
||||
out.setTextColor(initial_color)
|
||||
local function done(ok)
|
||||
out.setCursorPos(ts_coord.x1, ts_coord.y)
|
||||
|
||||
counter = counter + 1
|
||||
end
|
||||
if ok or ok == nil then
|
||||
out.setTextColor(colors.green)
|
||||
out.write(util.pad("DONE", width))
|
||||
else
|
||||
out.setTextColor(colors.red)
|
||||
out.write(util.pad("FAIL", width))
|
||||
end
|
||||
|
||||
local function done(ok)
|
||||
out.setCursorPos(ts_coord.x1, ts_coord.y)
|
||||
|
||||
if ok or ok == nil then
|
||||
out.setTextColor(colors.green)
|
||||
out.write(util.pad("DONE", width))
|
||||
else
|
||||
out.setTextColor(colors.red)
|
||||
out.write(util.pad("FAIL", width))
|
||||
out.setTextColor(initial_color)
|
||||
end
|
||||
|
||||
out.setTextColor(initial_color)
|
||||
return update, done
|
||||
else
|
||||
return function () end, function () end
|
||||
end
|
||||
|
||||
return update, done
|
||||
end
|
||||
|
||||
-- log debug messages
|
||||
|
@ -41,6 +41,7 @@ function facility.new(num_reactors, cooling_conf)
|
||||
induction = {},
|
||||
redstone = {},
|
||||
status_text = { "START UP", "initializing..." },
|
||||
all_sys_ok = false,
|
||||
-- process control
|
||||
units_ready = false,
|
||||
mode = PROCESS.INACTIVE,
|
||||
@ -199,6 +200,11 @@ function facility.new(num_reactors, cooling_conf)
|
||||
self.im_stat_init = false
|
||||
end
|
||||
|
||||
self.all_sys_ok = true
|
||||
for i = 1, #self.units do
|
||||
self.all_sys_ok = self.all_sys_ok and not self.units[i].get_control_inf().degraded
|
||||
end
|
||||
|
||||
-------------------------
|
||||
-- Run Process Control --
|
||||
-------------------------
|
||||
@ -570,6 +576,7 @@ function facility.new(num_reactors, cooling_conf)
|
||||
-- get automatic process control status
|
||||
function public.get_control_status()
|
||||
return {
|
||||
self.all_sys_ok,
|
||||
self.units_ready,
|
||||
self.mode,
|
||||
self.waiting_on_ramp,
|
||||
|
@ -59,6 +59,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
|
||||
out_q = out_queue,
|
||||
commanded_state = false,
|
||||
commanded_burn_rate = 0.0,
|
||||
auto_cmd_token = 0,
|
||||
ramping_rate = false,
|
||||
auto_scram = false,
|
||||
auto_lock = false,
|
||||
@ -92,6 +93,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
|
||||
-- session database
|
||||
---@class reactor_db
|
||||
sDB = {
|
||||
auto_ack_token = 0,
|
||||
last_status_update = 0,
|
||||
control_state = false,
|
||||
no_reactor = false,
|
||||
@ -305,18 +307,19 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
|
||||
-- handle packet by type
|
||||
if pkt.type == RPLC_TYPES.STATUS then
|
||||
-- status packet received, update data
|
||||
if pkt.length >= 4 then
|
||||
if pkt.length >= 5 then
|
||||
self.sDB.last_status_update = pkt.data[1]
|
||||
self.sDB.control_state = pkt.data[2]
|
||||
self.sDB.no_reactor = pkt.data[3]
|
||||
self.sDB.formed = pkt.data[4]
|
||||
self.sDB.auto_ack_token = pkt.data[5]
|
||||
|
||||
if not self.sDB.no_reactor and self.sDB.formed then
|
||||
self.sDB.mek_status.heating_rate = pkt.data[5] or 0.0
|
||||
self.sDB.mek_status.heating_rate = pkt.data[6] or 0.0
|
||||
|
||||
-- attempt to read mek_data table
|
||||
if pkt.data[6] ~= nil then
|
||||
local status = pcall(_copy_status, pkt.data[6])
|
||||
if pkt.data[7] ~= nil then
|
||||
local status = pcall(_copy_status, pkt.data[7])
|
||||
if status then
|
||||
-- copied in status data OK
|
||||
self.received_status_cache = true
|
||||
@ -496,6 +499,11 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
|
||||
-- get the session database
|
||||
function public.get_db() return self.sDB end
|
||||
|
||||
-- check if ramping is completed by first verifying auto command token ack
|
||||
function public.is_ramp_complete()
|
||||
return (self.sDB.auto_ack_token == self.auto_cmd_token) and (self.commanded_burn_rate == self.sDB.mek_status.act_burn_rate)
|
||||
end
|
||||
|
||||
-- get the reactor structure
|
||||
function public.get_struct()
|
||||
if self.received_struct then
|
||||
@ -618,6 +626,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
|
||||
cmd.val = math.floor(cmd.val * 10) / 10 -- round to 10ths place
|
||||
if cmd.val > 0 and cmd.val <= self.sDB.mek_struct.max_burn then
|
||||
self.commanded_burn_rate = cmd.val
|
||||
self.auto_cmd_token = 0
|
||||
self.ramping_rate = false
|
||||
self.acks.burn_rate = false
|
||||
self.retry_times.burn_rate_req = util.time() + INITIAL_WAIT
|
||||
@ -630,6 +639,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
|
||||
cmd.val = math.floor(cmd.val * 10) / 10 -- round to 10ths place
|
||||
if cmd.val > 0 and cmd.val <= self.sDB.mek_struct.max_burn then
|
||||
self.commanded_burn_rate = cmd.val
|
||||
self.auto_cmd_token = 0
|
||||
self.ramping_rate = true
|
||||
self.acks.burn_rate = false
|
||||
self.retry_times.burn_rate_req = util.time() + INITIAL_WAIT
|
||||
@ -640,14 +650,15 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
|
||||
-- set automatic burn rate
|
||||
if self.auto_lock then
|
||||
cmd.val = math.floor(cmd.val * 10) / 10 -- round to 10ths place
|
||||
if cmd.val > 0 and cmd.val <= self.sDB.mek_struct.max_burn then
|
||||
if cmd.val >= 0 and cmd.val <= self.sDB.mek_struct.max_burn then
|
||||
self.auto_cmd_token = util.time_ms()
|
||||
self.commanded_burn_rate = cmd.val
|
||||
|
||||
-- this is only for manual control, only retry auto ramps
|
||||
self.acks.burn_rate = not self.ramping_rate
|
||||
self.retry_times.burn_rate_req = util.time() + INITIAL_AUTO_WAIT
|
||||
|
||||
_send(RPLC_TYPES.AUTO_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate })
|
||||
_send(RPLC_TYPES.AUTO_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate, self.auto_cmd_token })
|
||||
end
|
||||
end
|
||||
else
|
||||
@ -717,10 +728,19 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
|
||||
|
||||
if not self.acks.burn_rate then
|
||||
if rtimes.burn_rate_req - util.time() <= 0 then
|
||||
if self.auto_lock then
|
||||
_send(RPLC_TYPES.AUTO_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate })
|
||||
else
|
||||
if self.auto_cmd_token > 0 then
|
||||
if self.auto_lock then
|
||||
_send(RPLC_TYPES.AUTO_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate, self.auto_cmd_token })
|
||||
log.debug("retried auto burn rate?")
|
||||
else
|
||||
-- would have been an auto command, but disengaged, so stop retrying
|
||||
self.acks.burn_rate = true
|
||||
end
|
||||
elseif not self.auto_lock then
|
||||
_send(RPLC_TYPES.MEK_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate })
|
||||
else
|
||||
-- shouldn't be in this state, just pretend it was acknowledged
|
||||
self.acks.burn_rate = true
|
||||
end
|
||||
|
||||
rtimes.burn_rate_req = util.time() + RETRY_PERIOD
|
||||
|
@ -409,8 +409,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
---@return boolean complete
|
||||
function public.a_ramp_complete()
|
||||
if self.plc_i ~= nil then
|
||||
local cur_rate = math.floor(self.plc_i.get_db().mek_status.burn_rate * 10)
|
||||
return (cur_rate == self.ramp_target_br10) or (self.ramp_target_br10 == 0)
|
||||
return self.plc_i.is_ramp_complete()
|
||||
else return true end
|
||||
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.11"
|
||||
local SUPERVISOR_VERSION = "beta-v0.9.12"
|
||||
|
||||
local print = util.print
|
||||
local println = util.println
|
||||
|
Loading…
Reference in New Issue
Block a user