Merge pull request #560 from MikaylaFischler/pocket-alpha-dev
Pocket Process Control
This commit is contained in:
commit
620fa362f6
@ -387,10 +387,14 @@ function coordinator.comms(version, nic, sv_watchdog)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- send the auto process control configuration with a start command
|
-- send the auto process control configuration with a start command
|
||||||
---@param auto_cfg sys_auto_config configuration
|
---@param mode PROCESS process control mode
|
||||||
function public.send_auto_start(auto_cfg)
|
---@param burn_target number burn rate target
|
||||||
|
---@param charge_target number charge level target
|
||||||
|
---@param gen_target number generation rate target
|
||||||
|
---@param limits number[] unit burn rate limits
|
||||||
|
function public.send_auto_start(mode, burn_target, charge_target, gen_target, limits)
|
||||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.FAC_CMD, {
|
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.FAC_CMD, {
|
||||||
FAC_COMMAND.START, auto_cfg.mode, auto_cfg.burn_target, auto_cfg.charge_target, auto_cfg.gen_target, auto_cfg.limits
|
FAC_COMMAND.START, mode, burn_target, charge_target, gen_target, limits
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -578,7 +582,7 @@ function coordinator.comms(version, nic, sv_watchdog)
|
|||||||
if cmd == FAC_COMMAND.SCRAM_ALL then
|
if cmd == FAC_COMMAND.SCRAM_ALL then
|
||||||
process.fac_ack(cmd, ack)
|
process.fac_ack(cmd, ack)
|
||||||
elseif cmd == FAC_COMMAND.STOP then
|
elseif cmd == FAC_COMMAND.STOP then
|
||||||
iocontrol.get_db().facility.stop_ack(ack)
|
process.fac_ack(cmd, ack)
|
||||||
elseif cmd == FAC_COMMAND.START then
|
elseif cmd == FAC_COMMAND.START then
|
||||||
if packet.length == 7 then
|
if packet.length == 7 then
|
||||||
process.start_ack_handle({ table.unpack(packet.data, 2) })
|
process.start_ack_handle({ table.unpack(packet.data, 2) })
|
||||||
|
|||||||
@ -84,6 +84,8 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale)
|
|||||||
all_sys_ok = false,
|
all_sys_ok = false,
|
||||||
rtu_count = 0,
|
rtu_count = 0,
|
||||||
|
|
||||||
|
status_lines = { "", "" },
|
||||||
|
|
||||||
auto_ready = false,
|
auto_ready = false,
|
||||||
auto_active = false,
|
auto_active = false,
|
||||||
auto_ramping = false,
|
auto_ramping = false,
|
||||||
@ -107,8 +109,6 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale)
|
|||||||
radiation = types.new_zero_radiation_reading(),
|
radiation = types.new_zero_radiation_reading(),
|
||||||
|
|
||||||
save_cfg_ack = nil, ---@type fun(success: boolean)
|
save_cfg_ack = nil, ---@type fun(success: boolean)
|
||||||
start_ack = nil, ---@type fun(success: boolean)
|
|
||||||
stop_ack = nil, ---@type fun(success: boolean)
|
|
||||||
|
|
||||||
---@type { [TONE]: boolean }
|
---@type { [TONE]: boolean }
|
||||||
alarm_tones = { false, false, false, false, false, false, false, false },
|
alarm_tones = { false, false, false, false, false, false, false, false },
|
||||||
@ -159,6 +159,11 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale)
|
|||||||
num_snas = 0,
|
num_snas = 0,
|
||||||
has_tank = conf.cooling.r_cool[i].TankConnection,
|
has_tank = conf.cooling.r_cool[i].TankConnection,
|
||||||
|
|
||||||
|
status_lines = { "", "" },
|
||||||
|
|
||||||
|
auto_ready = false,
|
||||||
|
auto_degraded = false,
|
||||||
|
|
||||||
control_state = false,
|
control_state = false,
|
||||||
burn_rate_cmd = 0.0,
|
burn_rate_cmd = 0.0,
|
||||||
radiation = types.new_zero_radiation_reading(),
|
radiation = types.new_zero_radiation_reading(),
|
||||||
@ -541,8 +546,8 @@ function iocontrol.update_facility_status(status)
|
|||||||
fac.ascram_status.radiation = ctl_status[10]
|
fac.ascram_status.radiation = ctl_status[10]
|
||||||
fac.ascram_status.gen_fault = ctl_status[11]
|
fac.ascram_status.gen_fault = ctl_status[11]
|
||||||
|
|
||||||
fac.status_line_1 = ctl_status[12]
|
fac.status_lines[1] = ctl_status[12]
|
||||||
fac.status_line_2 = ctl_status[13]
|
fac.status_lines[2] = ctl_status[13]
|
||||||
|
|
||||||
fac.ps.publish("all_sys_ok", fac.all_sys_ok)
|
fac.ps.publish("all_sys_ok", fac.all_sys_ok)
|
||||||
fac.ps.publish("auto_ready", fac.auto_ready)
|
fac.ps.publish("auto_ready", fac.auto_ready)
|
||||||
@ -555,8 +560,8 @@ function iocontrol.update_facility_status(status)
|
|||||||
fac.ps.publish("as_crit_alarm", fac.ascram_status.crit_alarm)
|
fac.ps.publish("as_crit_alarm", fac.ascram_status.crit_alarm)
|
||||||
fac.ps.publish("as_radiation", fac.ascram_status.radiation)
|
fac.ps.publish("as_radiation", fac.ascram_status.radiation)
|
||||||
fac.ps.publish("as_gen_fault", fac.ascram_status.gen_fault)
|
fac.ps.publish("as_gen_fault", fac.ascram_status.gen_fault)
|
||||||
fac.ps.publish("status_line_1", fac.status_line_1)
|
fac.ps.publish("status_line_1", fac.status_lines[1])
|
||||||
fac.ps.publish("status_line_2", fac.status_line_2)
|
fac.ps.publish("status_line_2", fac.status_lines[2])
|
||||||
|
|
||||||
local group_map = ctl_status[14]
|
local group_map = ctl_status[14]
|
||||||
|
|
||||||
@ -1130,15 +1135,19 @@ function iocontrol.update_unit_statuses(statuses)
|
|||||||
|
|
||||||
if type(unit_state) == "table" then
|
if type(unit_state) == "table" then
|
||||||
if #unit_state == 8 then
|
if #unit_state == 8 then
|
||||||
|
unit.status_lines[1] = unit_state[1]
|
||||||
|
unit.status_lines[2] = unit_state[2]
|
||||||
|
unit.auto_ready = unit_state[3]
|
||||||
|
unit.auto_degraded = unit_state[4]
|
||||||
unit.waste_mode = unit_state[5]
|
unit.waste_mode = unit_state[5]
|
||||||
unit.waste_product = unit_state[6]
|
unit.waste_product = unit_state[6]
|
||||||
unit.last_rate_change_ms = unit_state[7]
|
unit.last_rate_change_ms = unit_state[7]
|
||||||
unit.turbine_flow_stable = unit_state[8]
|
unit.turbine_flow_stable = unit_state[8]
|
||||||
|
|
||||||
unit.unit_ps.publish("U_StatusLine1", unit_state[1])
|
unit.unit_ps.publish("U_StatusLine1", unit.status_lines[1])
|
||||||
unit.unit_ps.publish("U_StatusLine2", unit_state[2])
|
unit.unit_ps.publish("U_StatusLine2", unit.status_lines[2])
|
||||||
unit.unit_ps.publish("U_AutoReady", unit_state[3])
|
unit.unit_ps.publish("U_AutoReady", unit.auto_ready)
|
||||||
unit.unit_ps.publish("U_AutoDegraded", unit_state[4])
|
unit.unit_ps.publish("U_AutoDegraded", unit.auto_degraded)
|
||||||
unit.unit_ps.publish("U_AutoWaste", unit.waste_mode == types.WASTE_MODE.AUTO)
|
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_WasteMode", unit.waste_mode)
|
||||||
unit.unit_ps.publish("U_WasteProduct", unit.waste_product)
|
unit.unit_ps.publish("U_WasteProduct", unit.waste_product)
|
||||||
|
|||||||
@ -25,12 +25,12 @@ local pctl = {
|
|||||||
control_states = {
|
control_states = {
|
||||||
---@class sys_auto_config
|
---@class sys_auto_config
|
||||||
process = {
|
process = {
|
||||||
mode = PROCESS.INACTIVE,
|
mode = PROCESS.INACTIVE, ---@type PROCESS
|
||||||
burn_target = 0.0,
|
burn_target = 0.0,
|
||||||
charge_target = 0.0,
|
charge_target = 0.0,
|
||||||
gen_target = 0.0,
|
gen_target = 0.0,
|
||||||
limits = {}, ---@type number[]
|
limits = {}, ---@type number[]
|
||||||
waste_product = PRODUCT.PLUTONIUM,
|
waste_product = PRODUCT.PLUTONIUM, ---@type WASTE_PRODUCT
|
||||||
pu_fallback = false,
|
pu_fallback = false,
|
||||||
sps_low_power = false
|
sps_low_power = false
|
||||||
},
|
},
|
||||||
@ -49,6 +49,7 @@ local pctl = {
|
|||||||
---@field requestors function[] list of callbacks from the requestors
|
---@field requestors function[] list of callbacks from the requestors
|
||||||
|
|
||||||
-- write auto process control to config file
|
-- write auto process control to config file
|
||||||
|
---@return boolean saved
|
||||||
local function _write_auto_config()
|
local function _write_auto_config()
|
||||||
-- save config
|
-- save config
|
||||||
settings.set("ControlStates", pctl.control_states)
|
settings.set("ControlStates", pctl.control_states)
|
||||||
@ -60,6 +61,8 @@ local function _write_auto_config()
|
|||||||
return saved
|
return saved
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--#region Core
|
||||||
|
|
||||||
-- initialize the process controller
|
-- initialize the process controller
|
||||||
---@param iocontrol ioctl iocontrl system
|
---@param iocontrol ioctl iocontrl system
|
||||||
---@param coord_comms coord_comms coordinator communications
|
---@param coord_comms coord_comms coordinator communications
|
||||||
@ -180,6 +183,36 @@ function process.create_handle()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- start automatic process control with current settings
|
||||||
|
function handle.process_start()
|
||||||
|
if f_request(F_CMD.START, handle.fac_ack.on_start) then
|
||||||
|
local p = pctl.control_states.process
|
||||||
|
pctl.comms.send_auto_start(p.mode, p.burn_target, p.charge_target, p.gen_target, p.limits)
|
||||||
|
log.debug("PROCESS: START AUTO CTRL")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- start automatic process control with remote settings that haven't been set on the coordinator
|
||||||
|
---@param mode PROCESS process control mode
|
||||||
|
---@param burn_target number burn rate target
|
||||||
|
---@param charge_target number charge level target
|
||||||
|
---@param gen_target number generation rate target
|
||||||
|
---@param limits number[] unit burn rate limits
|
||||||
|
function handle.process_start_remote(mode, burn_target, charge_target, gen_target, limits)
|
||||||
|
if f_request(F_CMD.START, handle.fac_ack.on_start) then
|
||||||
|
pctl.comms.send_auto_start(mode, burn_target, charge_target, gen_target, limits)
|
||||||
|
log.debug("PROCESS: START AUTO CTRL")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- stop process control
|
||||||
|
function handle.process_stop()
|
||||||
|
if f_request(F_CMD.STOP, handle.fac_ack.on_stop) then
|
||||||
|
pctl.comms.send_fac_command(F_CMD.STOP)
|
||||||
|
log.debug("PROCESS: STOP AUTO CTRL")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
handle.fac_ack = {}
|
handle.fac_ack = {}
|
||||||
|
|
||||||
-- luacheck: no unused args
|
-- luacheck: no unused args
|
||||||
@ -194,6 +227,16 @@ function process.create_handle()
|
|||||||
---@diagnostic disable-next-line: unused-local
|
---@diagnostic disable-next-line: unused-local
|
||||||
function handle.fac_ack.on_ack_alarms(success) end
|
function handle.fac_ack.on_ack_alarms(success) end
|
||||||
|
|
||||||
|
-- facility auto control start ack, override to implement
|
||||||
|
---@param success boolean
|
||||||
|
---@diagnostic disable-next-line: unused-local
|
||||||
|
function handle.fac_ack.on_start(success) end
|
||||||
|
|
||||||
|
-- facility auto control stop ack, override to implement
|
||||||
|
---@param success boolean
|
||||||
|
---@diagnostic disable-next-line: unused-local
|
||||||
|
function handle.fac_ack.on_stop(success) end
|
||||||
|
|
||||||
-- luacheck: unused args
|
-- luacheck: unused args
|
||||||
|
|
||||||
--#endregion
|
--#endregion
|
||||||
@ -294,6 +337,14 @@ function process.clear_timed_out()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- get the control states table
|
||||||
|
---@nodiscard
|
||||||
|
function process.get_control_states() return pctl.control_states end
|
||||||
|
|
||||||
|
--#endregion
|
||||||
|
|
||||||
|
--#region Command Handling
|
||||||
|
|
||||||
-- handle a command acknowledgement
|
-- handle a command acknowledgement
|
||||||
---@param cmd_state process_command_state
|
---@param cmd_state process_command_state
|
||||||
---@param success boolean if the command was successful
|
---@param success boolean if the command was successful
|
||||||
@ -335,6 +386,21 @@ function process.set_rate(id, rate)
|
|||||||
log.debug(util.c("PROCESS: UNIT[", id, "] SET BURN ", rate))
|
log.debug(util.c("PROCESS: UNIT[", id, "] SET BURN ", rate))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- assign a unit to a group
|
||||||
|
---@param unit_id integer unit ID
|
||||||
|
---@param group_id integer|0 group ID or 0 for independent
|
||||||
|
function process.set_group(unit_id, group_id)
|
||||||
|
pctl.comms.send_unit_command(U_CMD.SET_GROUP, unit_id, group_id)
|
||||||
|
log.debug(util.c("PROCESS: UNIT[", unit_id, "] SET GROUP ", group_id))
|
||||||
|
|
||||||
|
pctl.control_states.priority_groups[unit_id] = group_id
|
||||||
|
settings.set("ControlStates", pctl.control_states)
|
||||||
|
|
||||||
|
if not settings.save("/coordinator.settings") then
|
||||||
|
log.error("process.set_group(): failed to save coordinator settings file")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- set waste mode
|
-- set waste mode
|
||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
---@param mode integer waste mode
|
---@param mode integer waste mode
|
||||||
@ -369,39 +435,12 @@ function process.reset_alarm(id, alarm)
|
|||||||
log.debug(util.c("PROCESS: UNIT[", id, "] RESET ALARM ", alarm))
|
log.debug(util.c("PROCESS: UNIT[", id, "] RESET ALARM ", alarm))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- assign a unit to a group
|
|
||||||
---@param unit_id integer unit ID
|
|
||||||
---@param group_id integer|0 group ID or 0 for independent
|
|
||||||
function process.set_group(unit_id, group_id)
|
|
||||||
pctl.comms.send_unit_command(U_CMD.SET_GROUP, unit_id, group_id)
|
|
||||||
log.debug(util.c("PROCESS: UNIT[", unit_id, "] SET GROUP ", group_id))
|
|
||||||
|
|
||||||
pctl.control_states.priority_groups[unit_id] = group_id
|
|
||||||
settings.set("ControlStates", pctl.control_states)
|
|
||||||
|
|
||||||
if not settings.save("/coordinator.settings") then
|
|
||||||
log.error("process.set_group(): failed to save coordinator settings file")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--#endregion
|
--#endregion
|
||||||
|
|
||||||
--------------------------
|
--------------------------
|
||||||
-- AUTO PROCESS CONTROL --
|
-- AUTO PROCESS CONTROL --
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
-- start automatic process control
|
|
||||||
function process.start_auto()
|
|
||||||
pctl.comms.send_auto_start(pctl.control_states.process)
|
|
||||||
log.debug("PROCESS: START AUTO CTL")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- stop automatic process control
|
|
||||||
function process.stop_auto()
|
|
||||||
pctl.comms.send_fac_command(F_CMD.STOP)
|
|
||||||
log.debug("PROCESS: STOP AUTO CTL")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- set automatic process control waste mode
|
-- set automatic process control waste mode
|
||||||
---@param product WASTE_PRODUCT waste product for auto control
|
---@param product WASTE_PRODUCT waste product for auto control
|
||||||
function process.set_process_waste(product)
|
function process.set_process_waste(product)
|
||||||
@ -439,9 +478,9 @@ function process.set_sps_low_power(enabled)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- save process control settings
|
-- save process control settings
|
||||||
---@param mode PROCESS control mode
|
---@param mode PROCESS process control mode
|
||||||
---@param burn_target number burn rate target
|
---@param burn_target number burn rate target
|
||||||
---@param charge_target number charge target
|
---@param charge_target number charge level target
|
||||||
---@param gen_target number generation rate target
|
---@param gen_target number generation rate target
|
||||||
---@param limits number[] unit burn rate limits
|
---@param limits number[] unit burn rate limits
|
||||||
function process.save(mode, burn_target, charge_target, gen_target, limits)
|
function process.save(mode, burn_target, charge_target, gen_target, limits)
|
||||||
@ -472,9 +511,7 @@ function process.start_ack_handle(response)
|
|||||||
|
|
||||||
for i = 1, math.min(#response[6], pctl.io.facility.num_units) do
|
for i = 1, math.min(#response[6], pctl.io.facility.num_units) do
|
||||||
ctl_proc.limits[i] = response[6][i]
|
ctl_proc.limits[i] = response[6][i]
|
||||||
|
pctl.io.units[i].unit_ps.publish("burn_limit", ctl_proc.limits[i])
|
||||||
local unit = pctl.io.units[i]
|
|
||||||
unit.unit_ps.publish("burn_limit", ctl_proc.limits[i])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
pctl.io.facility.ps.publish("process_mode", ctl_proc.mode)
|
pctl.io.facility.ps.publish("process_mode", ctl_proc.mode)
|
||||||
@ -482,7 +519,9 @@ function process.start_ack_handle(response)
|
|||||||
pctl.io.facility.ps.publish("process_charge_target", pctl.io.energy_convert_from_fe(ctl_proc.charge_target))
|
pctl.io.facility.ps.publish("process_charge_target", pctl.io.energy_convert_from_fe(ctl_proc.charge_target))
|
||||||
pctl.io.facility.ps.publish("process_gen_target", pctl.io.energy_convert_from_fe(ctl_proc.gen_target))
|
pctl.io.facility.ps.publish("process_gen_target", pctl.io.energy_convert_from_fe(ctl_proc.gen_target))
|
||||||
|
|
||||||
pctl.io.facility.start_ack(ack)
|
_write_auto_config()
|
||||||
|
|
||||||
|
process.fac_ack(F_CMD.START, ack)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- record waste product settting after attempting to change it
|
-- record waste product settting after attempting to change it
|
||||||
@ -506,4 +545,6 @@ function process.sps_lp_ack_handle(response)
|
|||||||
pctl.io.facility.ps.publish("process_sps_low_power", response)
|
pctl.io.facility.ps.publish("process_sps_low_power", response)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--#endregion
|
||||||
|
|
||||||
return process
|
return process
|
||||||
|
|||||||
@ -108,14 +108,20 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
|
|
||||||
-- link callback transmissions
|
-- link callback transmissions
|
||||||
|
|
||||||
self.proc_handle.fac_ack.on_scram = function (success) _send(CRDN_TYPE.FAC_CMD, { FAC_COMMAND.SCRAM_ALL, success }) end
|
local f_ack = self.proc_handle.fac_ack
|
||||||
self.proc_handle.fac_ack.on_ack_alarms = function (success) _send(CRDN_TYPE.FAC_CMD, { FAC_COMMAND.ACK_ALL_ALARMS, success }) end
|
|
||||||
|
f_ack.on_scram = function (success) _send(CRDN_TYPE.FAC_CMD, { FAC_COMMAND.SCRAM_ALL, success }) end
|
||||||
|
f_ack.on_ack_alarms = function (success) _send(CRDN_TYPE.FAC_CMD, { FAC_COMMAND.ACK_ALL_ALARMS, success }) end
|
||||||
|
|
||||||
|
f_ack.on_start = function (success) _send(CRDN_TYPE.FAC_CMD, { FAC_COMMAND.START, success }) end
|
||||||
|
f_ack.on_stop = function (success) _send(CRDN_TYPE.FAC_CMD, { FAC_COMMAND.STOP, success }) end
|
||||||
|
|
||||||
for u = 1, iocontrol.get_db().facility.num_units do
|
for u = 1, iocontrol.get_db().facility.num_units do
|
||||||
self.proc_handle.unit_ack[u].on_start = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.START, u, success }) end
|
local u_ack = self.proc_handle.unit_ack[u]
|
||||||
self.proc_handle.unit_ack[u].on_scram = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.SCRAM, u, success }) end
|
u_ack.on_start = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.START, u, success }) end
|
||||||
self.proc_handle.unit_ack[u].on_rps_reset = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.RESET_RPS, u, success }) end
|
u_ack.on_scram = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.SCRAM, u, success }) end
|
||||||
self.proc_handle.unit_ack[u].on_ack_alarms = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.ACK_ALL_ALARMS, u, success }) end
|
u_ack.on_rps_reset = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.RESET_RPS, u, success }) end
|
||||||
|
u_ack.on_ack_alarms = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.ACK_ALL_ALARMS, u, success }) end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- handle a packet
|
-- handle a packet
|
||||||
@ -147,7 +153,15 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
log.info(log_tag .. "FAC SCRAM ALL")
|
log.info(log_tag .. "FAC SCRAM ALL")
|
||||||
self.proc_handle.fac_scram()
|
self.proc_handle.fac_scram()
|
||||||
elseif cmd == FAC_COMMAND.STOP then
|
elseif cmd == FAC_COMMAND.STOP then
|
||||||
|
log.info(log_tag .. "STOP PROCESS CTRL")
|
||||||
|
self.proc_handle.process_stop()
|
||||||
elseif cmd == FAC_COMMAND.START then
|
elseif cmd == FAC_COMMAND.START then
|
||||||
|
if pkt.length == 6 then
|
||||||
|
log.info(log_tag .. "START PROCESS CTRL")
|
||||||
|
self.proc_handle.process_start_remote(pkt.data[2], pkt.data[3], pkt.data[4], pkt.data[5], pkt.data[6])
|
||||||
|
else
|
||||||
|
log.debug(log_tag .. "CRDN auto start (with configuration) packet length mismatch")
|
||||||
|
end
|
||||||
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
||||||
log.info(log_tag .. "FAC ACK ALL ALARMS")
|
log.info(log_tag .. "FAC ACK ALL ALARMS")
|
||||||
self.proc_handle.fac_ack_alarms()
|
self.proc_handle.fac_ack_alarms()
|
||||||
@ -191,6 +205,12 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
elseif cmd == UNIT_COMMAND.ACK_ALARM then
|
elseif cmd == UNIT_COMMAND.ACK_ALARM then
|
||||||
elseif cmd == UNIT_COMMAND.RESET_ALARM then
|
elseif cmd == UNIT_COMMAND.RESET_ALARM then
|
||||||
elseif cmd == UNIT_COMMAND.SET_GROUP then
|
elseif cmd == UNIT_COMMAND.SET_GROUP then
|
||||||
|
if pkt.length == 3 then
|
||||||
|
log.info(util.c(log_tag, "UNIT[", uid, "] SET GROUP ", pkt.data[3]))
|
||||||
|
process.set_group(uid, pkt.data[3])
|
||||||
|
else
|
||||||
|
log.debug(log_tag .. "CRDN unit set group missing option")
|
||||||
|
end
|
||||||
else
|
else
|
||||||
log.debug(log_tag .. "CRDN unit command unknown")
|
log.debug(log_tag .. "CRDN unit command unknown")
|
||||||
end
|
end
|
||||||
@ -259,6 +279,37 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
end
|
end
|
||||||
|
|
||||||
_send(CRDN_TYPE.API_GET_CTRL, data)
|
_send(CRDN_TYPE.API_GET_CTRL, data)
|
||||||
|
elseif pkt.type == CRDN_TYPE.API_GET_PROC 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.reactor_data.mek_status.status,
|
||||||
|
u.reactor_data.mek_struct.max_burn,
|
||||||
|
proc.limits[i],
|
||||||
|
u.auto_ready,
|
||||||
|
u.auto_degraded,
|
||||||
|
u.annunciator.AutoControl,
|
||||||
|
u.a_group
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- facility data
|
||||||
|
data[#db.units + 1] = {
|
||||||
|
fac.status_lines,
|
||||||
|
{ fac.auto_ready, fac.auto_active, fac.auto_ramping, fac.auto_saturated },
|
||||||
|
fac.auto_scram,
|
||||||
|
fac.ascram_status,
|
||||||
|
{ proc.mode, proc.burn_target, proc.charge_target, proc.gen_target }
|
||||||
|
}
|
||||||
|
|
||||||
|
_send(CRDN_TYPE.API_GET_PROC, data)
|
||||||
else
|
else
|
||||||
log.debug(log_tag .. "handler received unsupported CRDN packet type " .. pkt.type)
|
log.debug(log_tag .. "handler received unsupported CRDN packet type " .. pkt.type)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -264,24 +264,22 @@ local function new_view(root, x, y)
|
|||||||
local limits = {}
|
local limits = {}
|
||||||
for i = 1, #rate_limits do limits[i] = rate_limits[i].get_value() end
|
for i = 1, #rate_limits do limits[i] = rate_limits[i].get_value() end
|
||||||
|
|
||||||
process.save(mode.get_value(), b_target.get_value(),
|
process.save(mode.get_value(), b_target.get_value(), db.energy_convert_to_fe(c_target.get_value()),
|
||||||
db.energy_convert_to_fe(c_target.get_value()),
|
db.energy_convert_to_fe(g_target.get_value()), limits)
|
||||||
db.energy_convert_to_fe(g_target.get_value()),
|
|
||||||
limits)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- start automatic control after saving process control settings
|
-- start automatic control after saving process control settings
|
||||||
local function _start_auto()
|
local function _start_auto()
|
||||||
_save_cfg()
|
_save_cfg()
|
||||||
process.start_auto()
|
db.process.process_start()
|
||||||
end
|
end
|
||||||
|
|
||||||
local save = HazardButton{parent=auto_controls,x=2,y=2,text="SAVE",accent=colors.purple,dis_colors=dis_colors,callback=_save_cfg,fg_bg=hzd_fg_bg}
|
local save = HazardButton{parent=auto_controls,x=2,y=2,text="SAVE",accent=colors.purple,dis_colors=dis_colors,callback=_save_cfg,fg_bg=hzd_fg_bg}
|
||||||
local start = HazardButton{parent=auto_controls,x=13,y=2,text="START",accent=colors.lightBlue,dis_colors=dis_colors,callback=_start_auto,fg_bg=hzd_fg_bg}
|
local start = HazardButton{parent=auto_controls,x=13,y=2,text="START",accent=colors.lightBlue,dis_colors=dis_colors,callback=_start_auto,fg_bg=hzd_fg_bg}
|
||||||
local stop = HazardButton{parent=auto_controls,x=23,y=2,text="STOP",accent=colors.red,dis_colors=dis_colors,callback=process.stop_auto,fg_bg=hzd_fg_bg}
|
local stop = HazardButton{parent=auto_controls,x=23,y=2,text="STOP",accent=colors.red,dis_colors=dis_colors,callback=db.process.process_stop,fg_bg=hzd_fg_bg}
|
||||||
|
|
||||||
facility.start_ack = start.on_response
|
db.process.fac_ack.on_start = start.on_response
|
||||||
facility.stop_ack = stop.on_response
|
db.process.fac_ack.on_stop = stop.on_response
|
||||||
|
|
||||||
function facility.save_cfg_ack(ack)
|
function facility.save_cfg_ack(ack)
|
||||||
tcd.dispatch(0.2, function () save.on_response(ack) end)
|
tcd.dispatch(0.2, function () save.on_response(ack) end)
|
||||||
|
|||||||
@ -7,7 +7,7 @@ local flasher = require("graphics.flasher")
|
|||||||
|
|
||||||
local core = {}
|
local core = {}
|
||||||
|
|
||||||
core.version = "2.4.3"
|
core.version = "2.4.5"
|
||||||
|
|
||||||
core.flasher = flasher
|
core.flasher = flasher
|
||||||
core.events = events
|
core.events = events
|
||||||
|
|||||||
@ -11,6 +11,7 @@ local KEY_CLICK = core.events.KEY_CLICK
|
|||||||
---@field options table button options
|
---@field options table button options
|
||||||
---@field radio_colors cpair radio button colors (inner & outer)
|
---@field radio_colors cpair radio button colors (inner & outer)
|
||||||
---@field select_color color color for radio button border when selected
|
---@field select_color color color for radio button border when selected
|
||||||
|
---@field dis_fg_bg? cpair foreground/background colors when disabled
|
||||||
---@field default? integer default state, defaults to options[1]
|
---@field default? integer default state, defaults to options[1]
|
||||||
---@field min_width? integer text length + 2 if omitted
|
---@field min_width? integer text length + 2 if omitted
|
||||||
---@field callback? function function to call on touch
|
---@field callback? function function to call on touch
|
||||||
@ -64,6 +65,10 @@ return function (args)
|
|||||||
local inner_color = util.trinary(e.value == i, args.radio_colors.color_b, args.radio_colors.color_a)
|
local inner_color = util.trinary(e.value == i, args.radio_colors.color_b, args.radio_colors.color_a)
|
||||||
local outer_color = util.trinary(e.value == i, args.select_color, args.radio_colors.color_b)
|
local outer_color = util.trinary(e.value == i, args.select_color, args.radio_colors.color_b)
|
||||||
|
|
||||||
|
if e.value == i and args.dis_fg_bg and not e.enabled then
|
||||||
|
outer_color = args.radio_colors.color_a
|
||||||
|
end
|
||||||
|
|
||||||
e.w_set_cur(1, i)
|
e.w_set_cur(1, i)
|
||||||
|
|
||||||
e.w_set_fgd(inner_color)
|
e.w_set_fgd(inner_color)
|
||||||
@ -75,9 +80,14 @@ return function (args)
|
|||||||
e.w_write("\x95")
|
e.w_write("\x95")
|
||||||
|
|
||||||
-- write button text
|
-- write button text
|
||||||
if i == focused_opt and e.is_focused() and e.enabled then
|
if args.dis_fg_bg and not e.enabled then
|
||||||
|
e.w_set_fgd(args.dis_fg_bg.fgd)
|
||||||
|
e.w_set_bkg(args.dis_fg_bg.bkg)
|
||||||
|
elseif i == focused_opt and e.is_focused() then
|
||||||
|
if e.enabled then
|
||||||
e.w_set_fgd(e.fg_bg.bkg)
|
e.w_set_fgd(e.fg_bg.bkg)
|
||||||
e.w_set_bkg(e.fg_bg.fgd)
|
e.w_set_bkg(e.fg_bg.fgd)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
e.w_set_fgd(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.w_set_bkg(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
|
|||||||
@ -44,8 +44,47 @@ return function (args)
|
|||||||
|
|
||||||
args.max_chars = args.max_chars or e.frame.w
|
args.max_chars = args.max_chars or e.frame.w
|
||||||
|
|
||||||
|
-- determine the format to convert the number to a string
|
||||||
|
local format = "%d"
|
||||||
|
if args.allow_decimal then
|
||||||
|
if args.max_frac_digits then
|
||||||
|
format = "%."..args.max_frac_digits.."f"
|
||||||
|
else format = "%f" end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- set the value to a formatted numeric string<br>
|
||||||
|
-- trims trailing zeros from floating point numbers
|
||||||
|
---@param num number
|
||||||
|
local function _set_value(num)
|
||||||
|
local str = util.sprintf(format, num)
|
||||||
|
|
||||||
|
if args.allow_decimal then
|
||||||
|
local found_nonzero = false
|
||||||
|
local str_table = {}
|
||||||
|
|
||||||
|
for i = #str, 1, -1 do
|
||||||
|
local c = string.sub(str, i, i)
|
||||||
|
|
||||||
|
if found_nonzero then
|
||||||
|
str_table[i] = c
|
||||||
|
else
|
||||||
|
if c == "." then
|
||||||
|
found_nonzero = true
|
||||||
|
elseif c ~= "0" then
|
||||||
|
str_table[i] = c
|
||||||
|
found_nonzero = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
e.value = table.concat(str_table)
|
||||||
|
else
|
||||||
|
e.value = str
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- set initial value
|
-- set initial value
|
||||||
e.value = "" .. (args.default or 0)
|
_set_value(args.default or 0)
|
||||||
|
|
||||||
-- make an interactive field manager
|
-- make an interactive field manager
|
||||||
local ifield = core.new_ifield(e, args.max_chars, args.fg_bg, args.dis_fg_bg, args.align_right)
|
local ifield = core.new_ifield(e, args.max_chars, args.fg_bg, args.dis_fg_bg, args.align_right)
|
||||||
@ -107,7 +146,17 @@ return function (args)
|
|||||||
-- set the value (must be a number)
|
-- set the value (must be a number)
|
||||||
---@param val number number to show
|
---@param val number number to show
|
||||||
function e.set_value(val)
|
function e.set_value(val)
|
||||||
if tonumber(val) then ifield.set_value("" .. tonumber(val)) end
|
local num, max, min = tonumber(val), tonumber(args.max), tonumber(args.min)
|
||||||
|
|
||||||
|
if max and num > max then
|
||||||
|
_set_value(max)
|
||||||
|
elseif min and num < min then
|
||||||
|
_set_value(min)
|
||||||
|
elseif num then
|
||||||
|
_set_value(num)
|
||||||
|
end
|
||||||
|
|
||||||
|
ifield.set_value(e.value)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set minimum input value
|
-- set minimum input value
|
||||||
@ -136,11 +185,9 @@ return function (args)
|
|||||||
|
|
||||||
-- handle unfocused
|
-- handle unfocused
|
||||||
function e.on_unfocused()
|
function e.on_unfocused()
|
||||||
local val = tonumber(e.value)
|
local val, max, min = tonumber(e.value), tonumber(args.max), tonumber(args.min)
|
||||||
local max = tonumber(args.max)
|
|
||||||
local min = tonumber(args.min)
|
|
||||||
|
|
||||||
if type(val) == "number" then
|
if val then
|
||||||
if args.max_int_digits or args.max_frac_digits then
|
if args.max_int_digits or args.max_frac_digits then
|
||||||
local str = e.value
|
local str = e.value
|
||||||
local ceil = false
|
local ceil = false
|
||||||
@ -169,17 +216,17 @@ return function (args)
|
|||||||
|
|
||||||
if parts[2] then parts[2] = "." .. parts[2] else parts[2] = "" end
|
if parts[2] then parts[2] = "." .. parts[2] else parts[2] = "" end
|
||||||
|
|
||||||
val = tonumber((parts[1] or "") .. parts[2])
|
val = tonumber((parts[1] or "") .. parts[2]) or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(args.max) == "number" and val > max then
|
if max and val > max then
|
||||||
e.value = "" .. max
|
_set_value(max)
|
||||||
ifield.nav_start()
|
ifield.nav_start()
|
||||||
elseif type(args.min) == "number" and val < min then
|
elseif min and val < min then
|
||||||
e.value = "" .. min
|
_set_value(min)
|
||||||
ifield.nav_start()
|
ifield.nav_start()
|
||||||
else
|
else
|
||||||
e.value = "" .. val
|
_set_value(val)
|
||||||
ifield.nav_end()
|
ifield.nav_end()
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -198,5 +245,11 @@ return function (args)
|
|||||||
---@class NumberField:graphics_element
|
---@class NumberField:graphics_element
|
||||||
local NumberField, id = e.complete(true)
|
local NumberField, id = e.complete(true)
|
||||||
|
|
||||||
|
-- get the numeric value of this field
|
||||||
|
---@return number value the value, or 0 if not a valid number
|
||||||
|
function NumberField.get_numeric()
|
||||||
|
return tonumber(e.value) or 0
|
||||||
|
end
|
||||||
|
|
||||||
return NumberField, id
|
return NumberField, id
|
||||||
end
|
end
|
||||||
|
|||||||
@ -6,7 +6,6 @@ local const = require("scada-common.constants")
|
|||||||
local psil = require("scada-common.psil")
|
local psil = require("scada-common.psil")
|
||||||
local types = require("scada-common.types")
|
local types = require("scada-common.types")
|
||||||
local util = require("scada-common.util")
|
local util = require("scada-common.util")
|
||||||
local log = require("scada-common.log")
|
|
||||||
|
|
||||||
local process = require("pocket.process")
|
local process = require("pocket.process")
|
||||||
|
|
||||||
@ -94,7 +93,8 @@ function iocontrol.init_core(pkt_comms, nav, cfg)
|
|||||||
---@class pocket_ioctl_api
|
---@class pocket_ioctl_api
|
||||||
io.api = {
|
io.api = {
|
||||||
get_unit = function (unit) comms.api__get_unit(unit) end,
|
get_unit = function (unit) comms.api__get_unit(unit) end,
|
||||||
get_ctrl = function () comms.api__get_control() end
|
get_ctrl = function () comms.api__get_control() end,
|
||||||
|
get_proc = function () comms.api__get_process() end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -138,6 +138,8 @@ function iocontrol.init_fac(conf)
|
|||||||
all_sys_ok = false,
|
all_sys_ok = false,
|
||||||
rtu_count = 0,
|
rtu_count = 0,
|
||||||
|
|
||||||
|
status_lines = { "", "" },
|
||||||
|
|
||||||
auto_ready = false,
|
auto_ready = false,
|
||||||
auto_active = false,
|
auto_active = false,
|
||||||
auto_ramping = false,
|
auto_ramping = false,
|
||||||
@ -197,6 +199,11 @@ function iocontrol.init_fac(conf)
|
|||||||
num_snas = 0,
|
num_snas = 0,
|
||||||
has_tank = conf.cooling.r_cool[i].TankConnection,
|
has_tank = conf.cooling.r_cool[i].TankConnection,
|
||||||
|
|
||||||
|
status_lines = { "", "" },
|
||||||
|
|
||||||
|
auto_ready = false,
|
||||||
|
auto_degraded = false,
|
||||||
|
|
||||||
control_state = false,
|
control_state = false,
|
||||||
burn_rate_cmd = 0.0,
|
burn_rate_cmd = 0.0,
|
||||||
radiation = types.new_zero_radiation_reading(),
|
radiation = types.new_zero_radiation_reading(),
|
||||||
@ -817,9 +824,6 @@ function iocontrol.record_control_data(data)
|
|||||||
local unit = io.units[u_id]
|
local unit = io.units[u_id]
|
||||||
local u_data = data[u_id]
|
local u_data = data[u_id]
|
||||||
|
|
||||||
if type(u_data) ~= "table" then
|
|
||||||
log.debug(util.c("iocontrol.record_control_data: unit ", u_id, " data invalid"))
|
|
||||||
else
|
|
||||||
unit.connected = u_data[1]
|
unit.connected = u_data[1]
|
||||||
|
|
||||||
unit.reactor_data.rps_tripped = u_data[2]
|
unit.reactor_data.rps_tripped = u_data[2]
|
||||||
@ -856,7 +860,64 @@ function iocontrol.record_control_data(data)
|
|||||||
|
|
||||||
unit.unit_ps.publish("U_ControlStatus", control_status)
|
unit.unit_ps.publish("U_ControlStatus", control_status)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- update process app with unit data from API_GET_PROC
|
||||||
|
---@param data table
|
||||||
|
function iocontrol.record_process_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.reactor_data.mek_status.status = u_data[1]
|
||||||
|
unit.reactor_data.mek_struct.max_burn = u_data[2]
|
||||||
|
unit.annunciator.AutoControl = u_data[6]
|
||||||
|
unit.a_group = u_data[7]
|
||||||
|
|
||||||
|
unit.unit_ps.publish("status", u_data[1])
|
||||||
|
unit.unit_ps.publish("max_burn", u_data[2])
|
||||||
|
unit.unit_ps.publish("burn_limit", u_data[3])
|
||||||
|
unit.unit_ps.publish("U_AutoReady", u_data[4])
|
||||||
|
unit.unit_ps.publish("U_AutoDegraded", u_data[5])
|
||||||
|
unit.unit_ps.publish("AutoControl", u_data[6])
|
||||||
|
unit.unit_ps.publish("auto_group_id", unit.a_group)
|
||||||
|
unit.unit_ps.publish("auto_group", types.AUTO_GROUP_NAMES[unit.a_group + 1])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- get facility data
|
||||||
|
local fac = io.facility
|
||||||
|
local f_data = data[#io.units + 1]
|
||||||
|
|
||||||
|
fac.status_lines = f_data[1]
|
||||||
|
|
||||||
|
fac.auto_ready = f_data[2][1]
|
||||||
|
fac.auto_active = f_data[2][2]
|
||||||
|
fac.auto_ramping = f_data[2][3]
|
||||||
|
fac.auto_saturated = f_data[2][4]
|
||||||
|
|
||||||
|
fac.auto_scram = f_data[3]
|
||||||
|
fac.ascram_status = f_data[4]
|
||||||
|
|
||||||
|
fac.ps.publish("status_line_1", fac.status_lines[1])
|
||||||
|
fac.ps.publish("status_line_2", fac.status_lines[2])
|
||||||
|
|
||||||
|
fac.ps.publish("auto_ready", fac.auto_ready)
|
||||||
|
fac.ps.publish("auto_active", fac.auto_active)
|
||||||
|
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_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)
|
||||||
|
fac.ps.publish("as_gen_fault", fac.ascram_status.gen_fault)
|
||||||
|
|
||||||
|
fac.ps.publish("process_mode", f_data[5][1])
|
||||||
|
fac.ps.publish("process_burn_target", f_data[5][2])
|
||||||
|
fac.ps.publish("process_charge_target", f_data[5][3])
|
||||||
|
fac.ps.publish("process_gen_target", f_data[5][4])
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get the IO controller database
|
-- get the IO controller database
|
||||||
|
|||||||
@ -82,18 +82,20 @@ end
|
|||||||
|
|
||||||
---@enum POCKET_APP_ID
|
---@enum POCKET_APP_ID
|
||||||
local APP_ID = {
|
local APP_ID = {
|
||||||
|
-- core UI
|
||||||
ROOT = 1,
|
ROOT = 1,
|
||||||
LOADER = 2,
|
LOADER = 2,
|
||||||
-- main app pages
|
-- main app pages
|
||||||
UNITS = 3,
|
UNITS = 3,
|
||||||
CONTROL = 4,
|
CONTROL = 4,
|
||||||
GUIDE = 5,
|
PROCESS = 5,
|
||||||
ABOUT = 6,
|
GUIDE = 6,
|
||||||
-- diag app page
|
ABOUT = 7,
|
||||||
ALARMS = 7,
|
-- diagnostic app pages
|
||||||
|
ALARMS = 8,
|
||||||
-- other
|
-- other
|
||||||
DUMMY = 8,
|
DUMMY = 9,
|
||||||
NUM_APPS = 8
|
NUM_APPS = 9
|
||||||
}
|
}
|
||||||
|
|
||||||
pocket.APP_ID = APP_ID
|
pocket.APP_ID = APP_ID
|
||||||
@ -167,9 +169,9 @@ function pocket.init_nav(smem)
|
|||||||
-- configure the sidebar
|
-- configure the sidebar
|
||||||
---@param items sidebar_entry[]
|
---@param items sidebar_entry[]
|
||||||
function app.set_sidebar(items)
|
function app.set_sidebar(items)
|
||||||
|
app.sidebar_items = items
|
||||||
-- only modify the sidebar if this app is still open
|
-- only modify the sidebar if this app is still open
|
||||||
if self.cur_app == app_id then
|
if self.cur_app == app_id then
|
||||||
app.sidebar_items = items
|
|
||||||
if self.sidebar then self.sidebar.update(items) end
|
if self.sidebar then self.sidebar.update(items) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -178,8 +180,8 @@ function pocket.init_nav(smem)
|
|||||||
---@param on_load function callback
|
---@param on_load function callback
|
||||||
function app.set_load(on_load)
|
function app.set_load(on_load)
|
||||||
app.load = function ()
|
app.load = function ()
|
||||||
|
app.loaded = true -- must flag first so it can't be repeatedly attempted
|
||||||
on_load()
|
on_load()
|
||||||
app.loaded = true
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -187,8 +189,8 @@ function pocket.init_nav(smem)
|
|||||||
---@param on_unload function callback
|
---@param on_unload function callback
|
||||||
function app.set_unload(on_unload)
|
function app.set_unload(on_unload)
|
||||||
app.unload = function ()
|
app.unload = function ()
|
||||||
on_unload()
|
|
||||||
app.loaded = false
|
app.loaded = false
|
||||||
|
on_unload()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -288,6 +290,9 @@ function pocket.init_nav(smem)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- go home (open the home screen app)
|
||||||
|
function nav.go_home() nav.open_app(APP_ID.ROOT) end
|
||||||
|
|
||||||
-- open the app that was blocked on connecting
|
-- open the app that was blocked on connecting
|
||||||
function nav.on_loader_connected()
|
function nav.on_loader_connected()
|
||||||
if self.loader_return then
|
if self.loader_return then
|
||||||
@ -555,6 +560,11 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav)
|
|||||||
if self.api.linked then _send_api(CRDN_TYPE.API_GET_CTRL, {}) end
|
if self.api.linked then _send_api(CRDN_TYPE.API_GET_CTRL, {}) end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- coordinator get process app data
|
||||||
|
function public.api__get_process()
|
||||||
|
if self.api.linked then _send_api(CRDN_TYPE.API_GET_PROC, {}) end
|
||||||
|
end
|
||||||
|
|
||||||
-- send a facility command
|
-- send a facility command
|
||||||
---@param cmd FAC_COMMAND command
|
---@param cmd FAC_COMMAND command
|
||||||
---@param option any? optional option options for the optional options (like waste mode)
|
---@param option any? optional option options for the optional options (like waste mode)
|
||||||
@ -562,6 +572,12 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav)
|
|||||||
_send_api(CRDN_TYPE.FAC_CMD, { cmd, option })
|
_send_api(CRDN_TYPE.FAC_CMD, { cmd, option })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- send the auto process control configuration with a start command
|
||||||
|
---@param auto_cfg [ PROCESS, number, number, number, number[] ]
|
||||||
|
function public.send_auto_start(auto_cfg)
|
||||||
|
_send_api(CRDN_TYPE.FAC_CMD, { FAC_COMMAND.START, table.unpack(auto_cfg) })
|
||||||
|
end
|
||||||
|
|
||||||
-- send a unit command
|
-- send a unit command
|
||||||
---@param cmd UNIT_COMMAND command
|
---@param cmd UNIT_COMMAND command
|
||||||
---@param unit integer unit ID
|
---@param unit integer unit ID
|
||||||
@ -664,7 +680,9 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav)
|
|||||||
if cmd == FAC_COMMAND.SCRAM_ALL then
|
if cmd == FAC_COMMAND.SCRAM_ALL then
|
||||||
iocontrol.get_db().facility.scram_ack(ack)
|
iocontrol.get_db().facility.scram_ack(ack)
|
||||||
elseif cmd == FAC_COMMAND.STOP then
|
elseif cmd == FAC_COMMAND.STOP then
|
||||||
|
iocontrol.get_db().facility.stop_ack(ack)
|
||||||
elseif cmd == FAC_COMMAND.START then
|
elseif cmd == FAC_COMMAND.START then
|
||||||
|
iocontrol.get_db().facility.start_ack(ack)
|
||||||
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
||||||
iocontrol.get_db().facility.ack_alarms_ack(ack)
|
iocontrol.get_db().facility.ack_alarms_ack(ack)
|
||||||
elseif cmd == FAC_COMMAND.SET_WASTE_MODE then
|
elseif cmd == FAC_COMMAND.SET_WASTE_MODE then
|
||||||
@ -711,6 +729,10 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav)
|
|||||||
if _check_length(packet, #iocontrol.get_db().units) then
|
if _check_length(packet, #iocontrol.get_db().units) then
|
||||||
iocontrol.record_control_data(packet.data)
|
iocontrol.record_control_data(packet.data)
|
||||||
end
|
end
|
||||||
|
elseif packet.type == CRDN_TYPE.API_GET_PROC then
|
||||||
|
if _check_length(packet, #iocontrol.get_db().units + 1) then
|
||||||
|
iocontrol.record_process_data(packet.data)
|
||||||
|
end
|
||||||
else _fail_type(packet) end
|
else _fail_type(packet) end
|
||||||
else
|
else
|
||||||
log.debug("discarding coordinator SCADA_CRDN packet before linked")
|
log.debug("discarding coordinator SCADA_CRDN packet before linked")
|
||||||
|
|||||||
@ -6,8 +6,8 @@ local comms = require("scada-common.comms")
|
|||||||
local log = require("scada-common.log")
|
local log = require("scada-common.log")
|
||||||
local util = require("scada-common.util")
|
local util = require("scada-common.util")
|
||||||
|
|
||||||
local FAC_COMMAND = comms.FAC_COMMAND
|
local F_CMD = comms.FAC_COMMAND
|
||||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
local U_CMD = comms.UNIT_COMMAND
|
||||||
|
|
||||||
---@class pocket_process_controller
|
---@class pocket_process_controller
|
||||||
local process = {}
|
local process = {}
|
||||||
@ -25,23 +25,32 @@ function process.init(iocontrol, pocket_comms)
|
|||||||
self.comms = pocket_comms
|
self.comms = pocket_comms
|
||||||
end
|
end
|
||||||
|
|
||||||
|
------------------------------
|
||||||
|
--#region FACILITY COMMANDS --
|
||||||
|
|
||||||
-- facility SCRAM command
|
-- facility SCRAM command
|
||||||
function process.fac_scram()
|
function process.fac_scram()
|
||||||
self.comms.send_fac_command(FAC_COMMAND.SCRAM_ALL)
|
self.comms.send_fac_command(F_CMD.SCRAM_ALL)
|
||||||
log.debug("PROCESS: FAC SCRAM ALL")
|
log.debug("PROCESS: FAC SCRAM ALL")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- facility alarm acknowledge command
|
-- facility alarm acknowledge command
|
||||||
function process.fac_ack_alarms()
|
function process.fac_ack_alarms()
|
||||||
self.comms.send_fac_command(FAC_COMMAND.ACK_ALL_ALARMS)
|
self.comms.send_fac_command(F_CMD.ACK_ALL_ALARMS)
|
||||||
log.debug("PROCESS: FAC ACK ALL ALARMS")
|
log.debug("PROCESS: FAC ACK ALL ALARMS")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--#endregion
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
--------------------------
|
||||||
|
--#region UNIT COMMANDS --
|
||||||
|
|
||||||
-- start reactor
|
-- start reactor
|
||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
function process.start(id)
|
function process.start(id)
|
||||||
self.io.units[id].control_state = true
|
self.io.units[id].control_state = true
|
||||||
self.comms.send_unit_command(UNIT_COMMAND.START, id)
|
self.comms.send_unit_command(U_CMD.START, id)
|
||||||
log.debug(util.c("PROCESS: UNIT[", id, "] START"))
|
log.debug(util.c("PROCESS: UNIT[", id, "] START"))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -49,14 +58,14 @@ end
|
|||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
function process.scram(id)
|
function process.scram(id)
|
||||||
self.io.units[id].control_state = false
|
self.io.units[id].control_state = false
|
||||||
self.comms.send_unit_command(UNIT_COMMAND.SCRAM, id)
|
self.comms.send_unit_command(U_CMD.SCRAM, id)
|
||||||
log.debug(util.c("PROCESS: UNIT[", id, "] SCRAM"))
|
log.debug(util.c("PROCESS: UNIT[", id, "] SCRAM"))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- reset reactor protection system
|
-- reset reactor protection system
|
||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
function process.reset_rps(id)
|
function process.reset_rps(id)
|
||||||
self.comms.send_unit_command(UNIT_COMMAND.RESET_RPS, id)
|
self.comms.send_unit_command(U_CMD.RESET_RPS, id)
|
||||||
log.debug(util.c("PROCESS: UNIT[", id, "] RESET RPS"))
|
log.debug(util.c("PROCESS: UNIT[", id, "] RESET RPS"))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -64,14 +73,22 @@ end
|
|||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
---@param rate number burn rate
|
---@param rate number burn rate
|
||||||
function process.set_rate(id, rate)
|
function process.set_rate(id, rate)
|
||||||
self.comms.send_unit_command(UNIT_COMMAND.SET_BURN, id, rate)
|
self.comms.send_unit_command(U_CMD.SET_BURN, id, rate)
|
||||||
log.debug(util.c("PROCESS: UNIT[", id, "] SET BURN ", rate))
|
log.debug(util.c("PROCESS: UNIT[", id, "] SET BURN ", rate))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- assign a unit to a group
|
||||||
|
---@param unit_id integer unit ID
|
||||||
|
---@param group_id integer|0 group ID or 0 for independent
|
||||||
|
function process.set_group(unit_id, group_id)
|
||||||
|
self.comms.send_unit_command(U_CMD.SET_GROUP, unit_id, group_id)
|
||||||
|
log.debug(util.c("PROCESS: UNIT[", unit_id, "] SET GROUP ", group_id))
|
||||||
|
end
|
||||||
|
|
||||||
-- acknowledge all alarms
|
-- acknowledge all alarms
|
||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
function process.ack_all_alarms(id)
|
function process.ack_all_alarms(id)
|
||||||
self.comms.send_unit_command(UNIT_COMMAND.ACK_ALL_ALARMS, id)
|
self.comms.send_unit_command(U_CMD.ACK_ALL_ALARMS, id)
|
||||||
log.debug(util.c("PROCESS: UNIT[", id, "] ACK ALL ALARMS"))
|
log.debug(util.c("PROCESS: UNIT[", id, "] ACK ALL ALARMS"))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -79,7 +96,7 @@ end
|
|||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
---@param alarm integer alarm ID
|
---@param alarm integer alarm ID
|
||||||
function process.ack_alarm(id, alarm)
|
function process.ack_alarm(id, alarm)
|
||||||
self.comms.send_unit_command(UNIT_COMMAND.ACK_ALARM, id, alarm)
|
self.comms.send_unit_command(U_CMD.ACK_ALARM, id, alarm)
|
||||||
log.debug(util.c("PROCESS: UNIT[", id, "] ACK ALARM ", alarm))
|
log.debug(util.c("PROCESS: UNIT[", id, "] ACK ALARM ", alarm))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -87,8 +104,34 @@ end
|
|||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
---@param alarm integer alarm ID
|
---@param alarm integer alarm ID
|
||||||
function process.reset_alarm(id, alarm)
|
function process.reset_alarm(id, alarm)
|
||||||
self.comms.send_unit_command(UNIT_COMMAND.RESET_ALARM, id, alarm)
|
self.comms.send_unit_command(U_CMD.RESET_ALARM, id, alarm)
|
||||||
log.debug(util.c("PROCESS: UNIT[", id, "] RESET ALARM ", alarm))
|
log.debug(util.c("PROCESS: UNIT[", id, "] RESET ALARM ", alarm))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- #endregion
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
---------------------------------
|
||||||
|
--#region AUTO PROCESS CONTROL --
|
||||||
|
|
||||||
|
-- process start command
|
||||||
|
---@param mode PROCESS process control mode
|
||||||
|
---@param burn_target number burn rate target
|
||||||
|
---@param charge_target number charge level target
|
||||||
|
---@param gen_target number generation rate target
|
||||||
|
---@param limits number[] unit burn rate limits
|
||||||
|
function process.process_start(mode, burn_target, charge_target, gen_target, limits)
|
||||||
|
self.comms.send_auto_start({ mode, burn_target, charge_target, gen_target, limits })
|
||||||
|
log.debug("PROCESS: START AUTO CTRL")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- process stop command
|
||||||
|
function process.process_stop()
|
||||||
|
self.comms.send_fac_command(F_CMD.STOP)
|
||||||
|
log.debug("PROCESS: STOP AUTO CTRL")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- #endregion
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
return process
|
return process
|
||||||
|
|||||||
@ -20,7 +20,7 @@ local pocket = require("pocket.pocket")
|
|||||||
local renderer = require("pocket.renderer")
|
local renderer = require("pocket.renderer")
|
||||||
local threads = require("pocket.threads")
|
local threads = require("pocket.threads")
|
||||||
|
|
||||||
local POCKET_VERSION = "v0.12.5-alpha"
|
local POCKET_VERSION = "v0.12.7-alpha"
|
||||||
|
|
||||||
local println = util.println
|
local println = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
|
|||||||
@ -34,16 +34,21 @@ local cpair = core.cpair
|
|||||||
|
|
||||||
local APP_ID = pocket.APP_ID
|
local APP_ID = pocket.APP_ID
|
||||||
|
|
||||||
|
local label_fg_bg = style.label
|
||||||
local lu_col = style.label_unit_pair
|
local lu_col = style.label_unit_pair
|
||||||
local text_fg = style.text_fg
|
local text_fg = style.text_fg
|
||||||
|
|
||||||
local mode_states = style.icon_states.mode_states
|
local mode_states = style.icon_states.mode_states
|
||||||
|
|
||||||
local hzd_fg_bg = cpair(colors.white, colors.gray)
|
local btn_active = cpair(colors.white, colors.black)
|
||||||
local dis_colors = cpair(colors.white, colors.lightGray)
|
local hzd_fg_bg = style.hzd_fg_bg
|
||||||
|
local hzd_dis_colors = style.hzd_dis_colors
|
||||||
|
|
||||||
-- new unit control page view
|
-- new unit control page view
|
||||||
---@param root Container parent
|
---@param root Container parent
|
||||||
local function new_view(root)
|
local function new_view(root)
|
||||||
|
local btn_fg_bg = cpair(colors.green, colors.black)
|
||||||
|
|
||||||
local db = iocontrol.get_db()
|
local db = iocontrol.get_db()
|
||||||
|
|
||||||
local frame = Div{parent=root,x=1,y=1}
|
local frame = Div{parent=root,x=1,y=1}
|
||||||
@ -58,17 +63,14 @@ local function new_view(root)
|
|||||||
|
|
||||||
local load_pane = MultiPane{parent=main,x=1,y=1,panes={load_div,main}}
|
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 = function () db.nav.open_app(APP_ID.ROOT) end } })
|
app.set_sidebar({ { label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = db.nav.go_home } })
|
||||||
|
|
||||||
local btn_fg_bg = cpair(colors.green, colors.black)
|
|
||||||
local btn_active = cpair(colors.white, colors.black)
|
|
||||||
|
|
||||||
local page_div = nil ---@type Div|nil
|
local page_div = nil ---@type Div|nil
|
||||||
|
|
||||||
-- set sidebar to display unit-specific fields based on a specified unit
|
-- set sidebar to display unit-specific fields based on a specified unit
|
||||||
local function set_sidebar()
|
local function set_sidebar()
|
||||||
local list = {
|
local list = {
|
||||||
{ label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = function () db.nav.open_app(APP_ID.ROOT) end },
|
{ label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = db.nav.go_home },
|
||||||
{ label = "FAC", color = core.cpair(colors.black, colors.orange), callback = function () app.switcher(db.facility.num_units + 1) end }
|
{ label = "FAC", color = core.cpair(colors.black, colors.orange), callback = function () app.switcher(db.facility.num_units + 1) end }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,12 +140,12 @@ local function new_view(root)
|
|||||||
|
|
||||||
u_div.line_break()
|
u_div.line_break()
|
||||||
|
|
||||||
TextBox{parent=u_div,y=8,text="CMD",width=4,fg_bg=cpair(colors.lightGray,colors.black)}
|
TextBox{parent=u_div,y=8,text="CMD",width=4,fg_bg=label_fg_bg}
|
||||||
TextBox{parent=u_div,x=14,y=8,text="mB/t",width=4,fg_bg=cpair(colors.lightGray,colors.black)}
|
TextBox{parent=u_div,x=14,y=8,text="mB/t",width=4,fg_bg=label_fg_bg}
|
||||||
local burn_cmd = NumberField{parent=u_div,x=5,y=8,width=8,default=0.01,min=0.01,max_frac_digits=2,max_chars=8,allow_decimal=true,align_right=true,fg_bg=cpair(colors.white,colors.gray),dis_fg_bg=cpair(colors.gray,colors.lightGray)}
|
local burn_cmd = NumberField{parent=u_div,x=5,y=8,width=8,default=0.01,min=0.01,max_frac_digits=2,max_chars=8,allow_decimal=true,align_right=true,fg_bg=style.field,dis_fg_bg=style.field_disable}
|
||||||
|
|
||||||
local set_burn = function () unit.set_burn(burn_cmd.get_value()) end
|
local set_burn = function () unit.set_burn(burn_cmd.get_numeric()) end
|
||||||
local set_burn_btn = PushButton{parent=u_div,x=19,y=8,text="SET",min_width=5,fg_bg=cpair(colors.green,colors.black),active_fg_bg=cpair(colors.white,colors.black),dis_fg_bg=cpair(colors.gray,colors.black),callback=set_burn}
|
local set_burn_btn = PushButton{parent=u_div,x=19,y=8,text="SET",min_width=5,fg_bg=cpair(colors.green,colors.black),active_fg_bg=cpair(colors.white,colors.black),dis_fg_bg=style.btn_disable,callback=set_burn}
|
||||||
|
|
||||||
-- enable/disable controls based on group assignment (start button is separate)
|
-- enable/disable controls based on group assignment (start button is separate)
|
||||||
burn_cmd.register(u_ps, "auto_group_id", function (gid)
|
burn_cmd.register(u_ps, "auto_group_id", function (gid)
|
||||||
@ -156,10 +158,10 @@ local function new_view(root)
|
|||||||
burn_cmd.register(u_ps, "burn_rate", burn_cmd.set_value)
|
burn_cmd.register(u_ps, "burn_rate", burn_cmd.set_value)
|
||||||
burn_cmd.register(u_ps, "max_burn", burn_cmd.set_max)
|
burn_cmd.register(u_ps, "max_burn", burn_cmd.set_max)
|
||||||
|
|
||||||
local start = HazardButton{parent=u_div,x=2,y=11,text="START",accent=colors.lightBlue,dis_colors=dis_colors,callback=unit.start,timeout=3,fg_bg=hzd_fg_bg}
|
local start = HazardButton{parent=u_div,x=2,y=11,text="START",accent=colors.lightBlue,callback=unit.start,timeout=3,fg_bg=hzd_fg_bg,dis_colors=hzd_dis_colors}
|
||||||
local ack_a = HazardButton{parent=u_div,x=12,y=11,text="ACK \x13",accent=colors.orange,dis_colors=dis_colors,callback=unit.ack_alarms,timeout=3,fg_bg=hzd_fg_bg}
|
local ack_a = HazardButton{parent=u_div,x=12,y=11,text="ACK \x13",accent=colors.orange,callback=unit.ack_alarms,timeout=3,fg_bg=hzd_fg_bg,dis_colors=hzd_dis_colors}
|
||||||
local scram = HazardButton{parent=u_div,x=2,y=15,text="SCRAM",accent=colors.yellow,dis_colors=dis_colors,callback=unit.scram,timeout=3,fg_bg=hzd_fg_bg}
|
local scram = HazardButton{parent=u_div,x=2,y=15,text="SCRAM",accent=colors.yellow,callback=unit.scram,timeout=3,fg_bg=hzd_fg_bg,dis_colors=hzd_dis_colors}
|
||||||
local reset = HazardButton{parent=u_div,x=12,y=15,text="RESET",accent=colors.red,dis_colors=dis_colors,callback=unit.reset_rps,timeout=3,fg_bg=hzd_fg_bg}
|
local reset = HazardButton{parent=u_div,x=12,y=15,text="RESET",accent=colors.red,callback=unit.reset_rps,timeout=3,fg_bg=hzd_fg_bg,dis_colors=hzd_dis_colors}
|
||||||
|
|
||||||
unit.start_ack = start.on_response
|
unit.start_ack = start.on_response
|
||||||
unit.ack_alarms_ack = ack_a.on_response
|
unit.ack_alarms_ack = ack_a.on_response
|
||||||
@ -192,8 +194,8 @@ local function new_view(root)
|
|||||||
|
|
||||||
TextBox{parent=f_div,y=1,text="Facility Commands",alignment=ALIGN.CENTER}
|
TextBox{parent=f_div,y=1,text="Facility Commands",alignment=ALIGN.CENTER}
|
||||||
|
|
||||||
local scram = HazardButton{parent=f_div,x=5,y=6,text="FAC SCRAM",accent=colors.yellow,dis_colors=dis_colors,callback=process.fac_scram,timeout=3,fg_bg=hzd_fg_bg}
|
local scram = HazardButton{parent=f_div,x=5,y=6,text="FAC SCRAM",accent=colors.yellow,dis_colors=hzd_dis_colors,callback=process.fac_scram,timeout=3,fg_bg=hzd_fg_bg}
|
||||||
local ack_a = HazardButton{parent=f_div,x=7,y=11,text="ACK \x13",accent=colors.orange,dis_colors=dis_colors,callback=process.fac_ack_alarms,timeout=3,fg_bg=hzd_fg_bg}
|
local ack_a = HazardButton{parent=f_div,x=7,y=11,text="ACK \x13",accent=colors.orange,dis_colors=hzd_dis_colors,callback=process.fac_ack_alarms,timeout=3,fg_bg=hzd_fg_bg}
|
||||||
|
|
||||||
db.facility.scram_ack = scram.on_response
|
db.facility.scram_ack = scram.on_response
|
||||||
db.facility.ack_alarms_ack = ack_a.on_response
|
db.facility.ack_alarms_ack = ack_a.on_response
|
||||||
@ -215,7 +217,7 @@ local function new_view(root)
|
|||||||
page_div = nil
|
page_div = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
app.set_sidebar({ { label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = function () db.nav.open_app(APP_ID.ROOT) end } })
|
app.set_sidebar({ { label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = db.nav.go_home } })
|
||||||
app.delete_pages()
|
app.delete_pages()
|
||||||
|
|
||||||
-- show loading screen
|
-- show loading screen
|
||||||
|
|||||||
@ -56,14 +56,14 @@ local function new_view(root)
|
|||||||
local btn_active = cpair(colors.white, colors.black)
|
local btn_active = cpair(colors.white, colors.black)
|
||||||
local btn_disable = cpair(colors.gray, colors.black)
|
local btn_disable = cpair(colors.gray, colors.black)
|
||||||
|
|
||||||
app.set_sidebar({{ label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = function () db.nav.open_app(APP_ID.ROOT) end }})
|
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
|
local page_div = nil ---@type Div|nil
|
||||||
|
|
||||||
-- load the app (create the elements)
|
-- load the app (create the elements)
|
||||||
local function load()
|
local function load()
|
||||||
local list = {
|
local list = {
|
||||||
{ label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = function () db.nav.open_app(APP_ID.ROOT) end },
|
{ label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = db.nav.go_home },
|
||||||
{ label = " \x14 ", color = core.cpair(colors.black, colors.cyan), callback = function () app.switcher(1) end },
|
{ label = " \x14 ", color = core.cpair(colors.black, colors.cyan), callback = function () app.switcher(1) end },
|
||||||
{ label = "__?", color = core.cpair(colors.black, colors.lightGray), callback = function () app.switcher(2) end }
|
{ label = "__?", color = core.cpair(colors.black, colors.lightGray), callback = function () app.switcher(2) end }
|
||||||
}
|
}
|
||||||
@ -263,7 +263,7 @@ local function new_view(root)
|
|||||||
page_div = nil
|
page_div = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
app.set_sidebar({ { label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = function () db.nav.open_app(APP_ID.ROOT) end } })
|
app.set_sidebar({ { label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = db.nav.go_home } })
|
||||||
app.delete_pages()
|
app.delete_pages()
|
||||||
|
|
||||||
-- show loading screen
|
-- show loading screen
|
||||||
|
|||||||
337
pocket/ui/apps/process.lua
Normal file
337
pocket/ui/apps/process.lua
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
--
|
||||||
|
-- Process Control Page
|
||||||
|
--
|
||||||
|
|
||||||
|
local types = require("scada-common.types")
|
||||||
|
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 Rectangle = require("graphics.elements.Rectangle")
|
||||||
|
local TextBox = require("graphics.elements.TextBox")
|
||||||
|
|
||||||
|
local WaitingAnim = require("graphics.elements.animations.Waiting")
|
||||||
|
|
||||||
|
local HazardButton = require("graphics.elements.controls.HazardButton")
|
||||||
|
local RadioButton = require("graphics.elements.controls.RadioButton")
|
||||||
|
|
||||||
|
local NumberField = require("graphics.elements.form.NumberField")
|
||||||
|
|
||||||
|
local IconIndicator = require("graphics.elements.indicators.IconIndicator")
|
||||||
|
|
||||||
|
local ALIGN = core.ALIGN
|
||||||
|
local cpair = core.cpair
|
||||||
|
local border = core.border
|
||||||
|
|
||||||
|
local APP_ID = pocket.APP_ID
|
||||||
|
|
||||||
|
local label_fg_bg = style.label
|
||||||
|
local text_fg = style.text_fg
|
||||||
|
|
||||||
|
local field_fg_bg = style.field
|
||||||
|
local field_dis_fg_bg = style.field_disable
|
||||||
|
|
||||||
|
local red_ind_s = style.icon_states.red_ind_s
|
||||||
|
local yel_ind_s = style.icon_states.yel_ind_s
|
||||||
|
local grn_ind_s = style.icon_states.grn_ind_s
|
||||||
|
local wht_ind_s = style.icon_states.wht_ind_s
|
||||||
|
|
||||||
|
local hzd_fg_bg = style.hzd_fg_bg
|
||||||
|
local dis_colors = cpair(colors.white, colors.lightGray)
|
||||||
|
|
||||||
|
-- new process 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.PROCESS, 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.purple,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[]
|
||||||
|
|
||||||
|
-- create all page divs
|
||||||
|
for _ = 1, db.facility.num_units + 3 do
|
||||||
|
local div = Div{parent=page_div}
|
||||||
|
table.insert(panes, div)
|
||||||
|
end
|
||||||
|
|
||||||
|
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_proc()
|
||||||
|
last_update = util.time_ms()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--#region unit settings/status
|
||||||
|
|
||||||
|
local rate_limits = {} ---@type NumberField[]
|
||||||
|
|
||||||
|
for i = 1, db.facility.num_units do
|
||||||
|
local u_pane = panes[i]
|
||||||
|
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
|
||||||
|
|
||||||
|
local u_page = app.new_page(nil, i)
|
||||||
|
u_page.tasks = { update }
|
||||||
|
|
||||||
|
TextBox{parent=u_div,y=1,text="Reactor Unit #"..i,alignment=ALIGN.CENTER}
|
||||||
|
|
||||||
|
TextBox{parent=u_div,y=3,text="Auto Rate Limit",fg_bg=label_fg_bg}
|
||||||
|
rate_limits[i] = NumberField{parent=u_div,x=1,y=4,width=16,default=0.01,min=0.01,max_frac_digits=2,max_chars=8,allow_decimal=true,align_right=true,fg_bg=field_fg_bg,dis_fg_bg=field_dis_fg_bg}
|
||||||
|
TextBox{parent=u_div,x=18,y=4,text="mB/t",width=4,fg_bg=label_fg_bg}
|
||||||
|
|
||||||
|
rate_limits[i].register(unit.unit_ps, "max_burn", rate_limits[i].set_max)
|
||||||
|
rate_limits[i].register(unit.unit_ps, "burn_limit", rate_limits[i].set_value)
|
||||||
|
|
||||||
|
local ready = IconIndicator{parent=u_div,y=6,label="Auto Ready",states=grn_ind_s}
|
||||||
|
local a_stb = IconIndicator{parent=u_div,label="Auto Standby",states=wht_ind_s}
|
||||||
|
local degraded = IconIndicator{parent=u_div,label="Unit Degraded",states=red_ind_s}
|
||||||
|
|
||||||
|
ready.register(u_ps, "U_AutoReady", ready.update)
|
||||||
|
degraded.register(u_ps, "U_AutoDegraded", degraded.update)
|
||||||
|
|
||||||
|
-- update standby indicator
|
||||||
|
a_stb.register(u_ps, "status", function (active)
|
||||||
|
a_stb.update(unit.annunciator.AutoControl and (not active))
|
||||||
|
end)
|
||||||
|
a_stb.register(u_ps, "AutoControl", function (auto_active)
|
||||||
|
if auto_active then
|
||||||
|
a_stb.update(unit.reactor_data.mek_status.status == false)
|
||||||
|
else a_stb.update(false) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function _set_group(value) process.set_group(i, value - 1) end
|
||||||
|
|
||||||
|
local group = RadioButton{parent=u_div,y=10,options=types.AUTO_GROUP_NAMES,callback=_set_group,radio_colors=cpair(colors.lightGray,colors.gray),select_color=colors.purple,dis_fg_bg=style.btn_disable}
|
||||||
|
|
||||||
|
-- can't change group if auto is engaged regardless of if this unit is part of auto control
|
||||||
|
group.register(f_ps, "auto_active", function (auto_active)
|
||||||
|
if auto_active then group.disable() else group.enable() end
|
||||||
|
end)
|
||||||
|
|
||||||
|
group.register(u_ps, "auto_group_id", function (gid) group.set_value(gid + 1) end)
|
||||||
|
|
||||||
|
TextBox{parent=u_div,y=16,text="Assigned Group",fg_bg=style.label}
|
||||||
|
local auto_grp = TextBox{parent=u_div,text="Manual",width=11,fg_bg=text_fg}
|
||||||
|
|
||||||
|
auto_grp.register(u_ps, "auto_group", auto_grp.set_value)
|
||||||
|
|
||||||
|
util.nop()
|
||||||
|
end
|
||||||
|
|
||||||
|
--#endregion
|
||||||
|
|
||||||
|
--#region process control options page
|
||||||
|
|
||||||
|
local o_pane = panes[db.facility.num_units + 2]
|
||||||
|
local o_div = Div{parent=o_pane,x=2,width=main.get_width()-2}
|
||||||
|
|
||||||
|
local opt_page = app.new_page(nil, db.facility.num_units + 2)
|
||||||
|
opt_page.tasks = { update }
|
||||||
|
|
||||||
|
TextBox{parent=o_div,y=1,text="Process Options",alignment=ALIGN.CENTER}
|
||||||
|
|
||||||
|
local ctl_opts = { "Monitored Max Burn", "Combined Burn Rate", "Charge Level", "Generation Rate" }
|
||||||
|
local mode = RadioButton{parent=o_div,x=1,y=3,options=ctl_opts,callback=function()end,radio_colors=cpair(colors.lightGray,colors.gray),select_color=colors.purple,dis_fg_bg=style.btn_disable}
|
||||||
|
|
||||||
|
mode.register(f_ps, "process_mode", mode.set_value)
|
||||||
|
|
||||||
|
TextBox{parent=o_div,y=9,text="Burn Rate Target",fg_bg=label_fg_bg}
|
||||||
|
local b_target = NumberField{parent=o_div,x=1,y=10,width=15,default=0.01,min=0.01,max_frac_digits=2,max_chars=8,allow_decimal=true,align_right=true,fg_bg=field_fg_bg,dis_fg_bg=field_dis_fg_bg}
|
||||||
|
TextBox{parent=o_div,x=17,y=10,text="mB/t",fg_bg=label_fg_bg}
|
||||||
|
|
||||||
|
TextBox{parent=o_div,y=12,text="Charge Level Target",fg_bg=label_fg_bg}
|
||||||
|
local c_target = NumberField{parent=o_div,x=1,y=13,width=15,default=0,min=0,max_chars=16,align_right=true,fg_bg=field_fg_bg,dis_fg_bg=field_dis_fg_bg}
|
||||||
|
TextBox{parent=o_div,x=17,y=13,text="M"..db.energy_label,fg_bg=label_fg_bg}
|
||||||
|
|
||||||
|
TextBox{parent=o_div,y=15,text="Generation Target",fg_bg=label_fg_bg}
|
||||||
|
local g_target = NumberField{parent=o_div,x=1,y=16,width=15,default=0,min=0,max_chars=16,align_right=true,fg_bg=field_fg_bg,dis_fg_bg=field_dis_fg_bg}
|
||||||
|
TextBox{parent=o_div,x=17,y=16,text="k"..db.energy_label.."/t",fg_bg=label_fg_bg}
|
||||||
|
|
||||||
|
b_target.register(f_ps, "process_burn_target", b_target.set_value)
|
||||||
|
c_target.register(f_ps, "process_charge_target", c_target.set_value)
|
||||||
|
g_target.register(f_ps, "process_gen_target", g_target.set_value)
|
||||||
|
|
||||||
|
--#endregion
|
||||||
|
|
||||||
|
--#region process control page
|
||||||
|
|
||||||
|
local c_pane = panes[db.facility.num_units + 1]
|
||||||
|
local c_div = Div{parent=c_pane,x=2,width=main.get_width()-2}
|
||||||
|
|
||||||
|
local proc_ctrl = app.new_page(nil, db.facility.num_units + 1)
|
||||||
|
proc_ctrl.tasks = { update }
|
||||||
|
|
||||||
|
TextBox{parent=c_div,y=1,text="Process Control",alignment=ALIGN.CENTER}
|
||||||
|
|
||||||
|
local u_stat = Rectangle{parent=c_div,border=border(1,colors.gray,true),thin=true,width=21,height=5,x=1,y=3,fg_bg=cpair(colors.black,colors.lightGray)}
|
||||||
|
local stat_line_1 = TextBox{parent=u_stat,x=1,y=1,text="UNKNOWN",alignment=ALIGN.CENTER}
|
||||||
|
local stat_line_2 = TextBox{parent=u_stat,x=1,y=2,text="awaiting data...",height=2,alignment=ALIGN.CENTER,trim_whitespace=true,fg_bg=cpair(colors.gray,colors.lightGray)}
|
||||||
|
|
||||||
|
stat_line_1.register(f_ps, "status_line_1", stat_line_1.set_value)
|
||||||
|
stat_line_2.register(f_ps, "status_line_2", stat_line_2.set_value)
|
||||||
|
|
||||||
|
local function _start_auto()
|
||||||
|
local limits = {}
|
||||||
|
for i = 1, #rate_limits do limits[i] = rate_limits[i].get_numeric() end
|
||||||
|
|
||||||
|
process.process_start(mode.get_value(), b_target.get_numeric(), db.energy_convert_to_fe(c_target.get_numeric()),
|
||||||
|
db.energy_convert_to_fe(g_target.get_numeric()), limits)
|
||||||
|
end
|
||||||
|
|
||||||
|
local start = HazardButton{parent=c_div,x=2,y=9,text="START",accent=colors.lightBlue,callback=_start_auto,timeout=3,fg_bg=hzd_fg_bg,dis_colors=dis_colors}
|
||||||
|
local stop = HazardButton{parent=c_div,x=13,y=9,text="STOP",accent=colors.red,callback=process.process_stop,timeout=3,fg_bg=hzd_fg_bg,dis_colors=dis_colors}
|
||||||
|
|
||||||
|
db.facility.start_ack = start.on_response
|
||||||
|
db.facility.stop_ack = stop.on_response
|
||||||
|
|
||||||
|
start.register(f_ps, "auto_ready", function (ready)
|
||||||
|
if ready and (not db.facility.auto_active) then start.enable() else start.disable() end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local auto_ready = IconIndicator{parent=c_div,y=14,label="Units Ready",states=grn_ind_s}
|
||||||
|
local auto_act = IconIndicator{parent=c_div,label="Process Active",states=grn_ind_s}
|
||||||
|
local auto_ramp = IconIndicator{parent=c_div,label="Process Ramping",states=wht_ind_s}
|
||||||
|
local auto_sat = IconIndicator{parent=c_div,label="Min/Max Burn Rate",states=yel_ind_s}
|
||||||
|
|
||||||
|
auto_ready.register(f_ps, "auto_ready", auto_ready.update)
|
||||||
|
auto_act.register(f_ps, "auto_active", auto_act.update)
|
||||||
|
auto_ramp.register(f_ps, "auto_ramping", auto_ramp.update)
|
||||||
|
auto_sat.register(f_ps, "auto_saturated", auto_sat.update)
|
||||||
|
|
||||||
|
-- REGISTER_NOTE: for optimization/brevity, due to not deleting anything but the whole element tree
|
||||||
|
-- when it comes to unloading the process app, child elements will not directly be registered here
|
||||||
|
-- (preventing garbage collection until the parent 'page_div' is deleted)
|
||||||
|
page_div.register(f_ps, "auto_active", function (active)
|
||||||
|
if active then
|
||||||
|
b_target.disable()
|
||||||
|
c_target.disable()
|
||||||
|
g_target.disable()
|
||||||
|
|
||||||
|
mode.disable()
|
||||||
|
start.disable()
|
||||||
|
|
||||||
|
for i = 1, #rate_limits do rate_limits[i].disable() end
|
||||||
|
else
|
||||||
|
b_target.enable()
|
||||||
|
c_target.enable()
|
||||||
|
g_target.enable()
|
||||||
|
|
||||||
|
mode.enable()
|
||||||
|
if db.facility.auto_ready then start.enable() end
|
||||||
|
|
||||||
|
for i = 1, #rate_limits do rate_limits[i].enable() end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
--#endregion
|
||||||
|
|
||||||
|
--#region auto-SCRAM annunciator page
|
||||||
|
|
||||||
|
local a_pane = panes[db.facility.num_units + 3]
|
||||||
|
local a_div = Div{parent=a_pane,x=2,width=main.get_width()-2}
|
||||||
|
|
||||||
|
local annunc_page = app.new_page(nil, db.facility.num_units + 3)
|
||||||
|
annunc_page.tasks = { update }
|
||||||
|
|
||||||
|
TextBox{parent=a_div,y=1,text="Automatic SCRAM",alignment=ALIGN.CENTER}
|
||||||
|
|
||||||
|
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_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}
|
||||||
|
local unit_crit = IconIndicator{parent=a_div,label="Critical Alarm",states=red_ind_s}
|
||||||
|
|
||||||
|
TextBox{parent=a_div,y=12,text="Facility",fg_bg=label_fg_bg}
|
||||||
|
local fac_rad_h = IconIndicator{parent=a_div,label="Radiation High",states=red_ind_s}
|
||||||
|
|
||||||
|
TextBox{parent=a_div,y=15,text="Generation Rate Mode",fg_bg=label_fg_bg}
|
||||||
|
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_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)
|
||||||
|
gen_fault.register(f_ps, "as_gen_fault", gen_fault.update)
|
||||||
|
|
||||||
|
--#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 = " \x17 ", color = core.cpair(colors.black, colors.purple), callback = proc_ctrl.nav_to },
|
||||||
|
{ label = " \x13 ", color = core.cpair(colors.black, colors.red), callback = annunc_page.nav_to },
|
||||||
|
{ label = "OPT", color = core.cpair(colors.black, colors.yellow), callback = opt_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 = function () app.switcher(i) end })
|
||||||
|
end
|
||||||
|
|
||||||
|
app.set_sidebar(list)
|
||||||
|
|
||||||
|
-- done, show the app
|
||||||
|
proc_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
|
||||||
@ -63,7 +63,7 @@ local function new_view(root)
|
|||||||
|
|
||||||
local load_pane = MultiPane{parent=main,x=1,y=1,panes={load_div,main}}
|
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 = function () db.nav.open_app(APP_ID.ROOT) end } })
|
app.set_sidebar({ { label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = db.nav.go_home } })
|
||||||
|
|
||||||
local btn_fg_bg = cpair(colors.yellow, colors.black)
|
local btn_fg_bg = cpair(colors.yellow, colors.black)
|
||||||
local btn_active = cpair(colors.white, colors.black)
|
local btn_active = cpair(colors.white, colors.black)
|
||||||
@ -76,7 +76,7 @@ local function new_view(root)
|
|||||||
local unit = db.units[id]
|
local unit = db.units[id]
|
||||||
|
|
||||||
local list = {
|
local list = {
|
||||||
{ label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = function () db.nav.open_app(APP_ID.ROOT) end },
|
{ label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = db.nav.go_home },
|
||||||
{ label = "U-" .. id, color = core.cpair(colors.black, colors.yellow), callback = function () app.switcher(id) end },
|
{ label = "U-" .. id, color = core.cpair(colors.black, colors.yellow), callback = function () app.switcher(id) end },
|
||||||
{ label = " \x13 ", color = core.cpair(colors.black, colors.red), callback = nav_links[id].alarm },
|
{ label = " \x13 ", color = core.cpair(colors.black, colors.red), callback = nav_links[id].alarm },
|
||||||
{ label = "RPS", tall = true, color = core.cpair(colors.black, colors.cyan), callback = nav_links[id].rps },
|
{ label = "RPS", tall = true, color = core.cpair(colors.black, colors.cyan), callback = nav_links[id].rps },
|
||||||
@ -383,7 +383,7 @@ local function new_view(root)
|
|||||||
page_div = nil
|
page_div = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
app.set_sidebar({ { label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = function () db.nav.open_app(APP_ID.ROOT) end } })
|
app.set_sidebar({ { label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = db.nav.go_home } })
|
||||||
app.delete_pages()
|
app.delete_pages()
|
||||||
|
|
||||||
-- show loading screen
|
-- show loading screen
|
||||||
|
|||||||
@ -12,6 +12,7 @@ local diag_apps = require("pocket.ui.apps.diag_apps")
|
|||||||
local dummy_app = require("pocket.ui.apps.dummy_app")
|
local dummy_app = require("pocket.ui.apps.dummy_app")
|
||||||
local guide_app = require("pocket.ui.apps.guide")
|
local guide_app = require("pocket.ui.apps.guide")
|
||||||
local loader_app = require("pocket.ui.apps.loader")
|
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 sys_apps = require("pocket.ui.apps.sys_apps")
|
||||||
local unit_app = require("pocket.ui.apps.unit")
|
local unit_app = require("pocket.ui.apps.unit")
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ local function init(main)
|
|||||||
home_page(page_div)
|
home_page(page_div)
|
||||||
unit_app(page_div)
|
unit_app(page_div)
|
||||||
control_app(page_div)
|
control_app(page_div)
|
||||||
|
process_app(page_div)
|
||||||
guide_app(page_div)
|
guide_app(page_div)
|
||||||
loader_app(page_div)
|
loader_app(page_div)
|
||||||
sys_apps(page_div)
|
sys_apps(page_div)
|
||||||
@ -78,7 +80,7 @@ local function init(main)
|
|||||||
|
|
||||||
PushButton{parent=main_pane,x=1,y=19,text="\x1b",min_width=3,fg_bg=cpair(colors.white,colors.gray),active_fg_bg=cpair(colors.gray,colors.black),callback=db.nav.nav_up}
|
PushButton{parent=main_pane,x=1,y=19,text="\x1b",min_width=3,fg_bg=cpair(colors.white,colors.gray),active_fg_bg=cpair(colors.gray,colors.black),callback=db.nav.nav_up}
|
||||||
|
|
||||||
db.nav.open_app(APP_ID.ROOT)
|
db.nav.go_home()
|
||||||
|
|
||||||
-- done with initial render, lets go!
|
-- done with initial render, lets go!
|
||||||
root_pane.set_value(2)
|
root_pane.set_value(2)
|
||||||
|
|||||||
@ -48,7 +48,7 @@ local function new_view(root)
|
|||||||
App{parent=apps_1,x=2,y=2,text="U",title="Units",callback=function()open(APP_ID.UNITS)end,app_fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=active_fg_bg}
|
App{parent=apps_1,x=2,y=2,text="U",title="Units",callback=function()open(APP_ID.UNITS)end,app_fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=active_fg_bg}
|
||||||
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=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=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.DUMMY)end,app_fg_bg=cpair(colors.black,colors.purple),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.DUMMY)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=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=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}
|
||||||
|
|||||||
@ -13,9 +13,16 @@ local cpair = core.cpair
|
|||||||
style.root = cpair(colors.white, colors.black)
|
style.root = cpair(colors.white, colors.black)
|
||||||
style.header = cpair(colors.white, colors.gray)
|
style.header = cpair(colors.white, colors.gray)
|
||||||
style.text_fg = cpair(colors.white, colors._INHERIT)
|
style.text_fg = cpair(colors.white, colors._INHERIT)
|
||||||
|
|
||||||
style.label = cpair(colors.lightGray, colors.black)
|
style.label = cpair(colors.lightGray, colors.black)
|
||||||
style.label_unit_pair = cpair(colors.lightGray, colors.lightGray)
|
style.label_unit_pair = cpair(colors.lightGray, colors.lightGray)
|
||||||
|
|
||||||
|
style.field = cpair(colors.white, colors.gray)
|
||||||
|
style.field_disable = cpair(colors.gray, colors.lightGray)
|
||||||
|
style.btn_disable = cpair(colors.gray, colors.black)
|
||||||
|
style.hzd_fg_bg = cpair(colors.white, colors.gray)
|
||||||
|
style.hzd_dis_colors = cpair(colors.white, colors.lightGray)
|
||||||
|
|
||||||
style.colors = {
|
style.colors = {
|
||||||
{ c = colors.red, hex = 0xdf4949 },
|
{ c = colors.red, hex = 0xdf4949 },
|
||||||
{ c = colors.orange, hex = 0xffb659 },
|
{ c = colors.orange, hex = 0xffb659 },
|
||||||
@ -73,6 +80,16 @@ states.yel_ind_s = {
|
|||||||
{ color = cpair(colors.black, colors.yellow), symbol = "-" }
|
{ color = cpair(colors.black, colors.yellow), symbol = "-" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
states.grn_ind_s = {
|
||||||
|
{ color = cpair(colors.black, colors.lightGray), symbol = "\x07" },
|
||||||
|
{ color = cpair(colors.black, colors.green), symbol = "+" }
|
||||||
|
}
|
||||||
|
|
||||||
|
states.wht_ind_s = {
|
||||||
|
{ color = cpair(colors.black, colors.lightGray), symbol = "\x07" },
|
||||||
|
{ color = cpair(colors.black, colors.white), symbol = "+" }
|
||||||
|
}
|
||||||
|
|
||||||
style.icon_states = states
|
style.icon_states = states
|
||||||
|
|
||||||
-- MAIN LAYOUT --
|
-- MAIN LAYOUT --
|
||||||
|
|||||||
@ -18,7 +18,7 @@ local comms = {}
|
|||||||
|
|
||||||
-- protocol/data versions (protocol/data independent changes tracked by util.lua version)
|
-- protocol/data versions (protocol/data independent changes tracked by util.lua version)
|
||||||
comms.version = "3.0.0"
|
comms.version = "3.0.0"
|
||||||
comms.api_version = "0.0.5"
|
comms.api_version = "0.0.6"
|
||||||
|
|
||||||
---@enum PROTOCOL
|
---@enum PROTOCOL
|
||||||
local PROTOCOL = {
|
local PROTOCOL = {
|
||||||
@ -68,7 +68,8 @@ local CRDN_TYPE = {
|
|||||||
UNIT_CMD = 6, -- command a reactor unit
|
UNIT_CMD = 6, -- command a reactor unit
|
||||||
API_GET_FAC = 7, -- API: get all the facility data
|
API_GET_FAC = 7, -- API: get all the facility data
|
||||||
API_GET_UNIT = 8, -- API: get reactor unit data
|
API_GET_UNIT = 8, -- API: get reactor unit data
|
||||||
API_GET_CTRL = 9 -- API: get data used for the control app
|
API_GET_CTRL = 9, -- API: get data used for the control app
|
||||||
|
API_GET_PROC = 10 -- API: get data used for the process app
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum ESTABLISH_ACK
|
---@enum ESTABLISH_ACK
|
||||||
|
|||||||
@ -425,9 +425,9 @@ function facility.new(config)
|
|||||||
|
|
||||||
ready = self.mode_set > 0
|
ready = self.mode_set > 0
|
||||||
|
|
||||||
if (self.mode_set == PROCESS.CHARGE) and (self.charge_setpoint <= 0) or
|
if ((self.mode_set == PROCESS.CHARGE) and (self.charge_setpoint <= 0)) or
|
||||||
(self.mode_set == PROCESS.GEN_RATE) and (self.gen_rate_setpoint <= 0) or
|
((self.mode_set == PROCESS.GEN_RATE) and (self.gen_rate_setpoint <= 0)) or
|
||||||
(self.mode_set == PROCESS.BURN_RATE) and (self.burn_target < 0.1) then
|
((self.mode_set == PROCESS.BURN_RATE) and (self.burn_target < 0.1)) then
|
||||||
ready = false
|
ready = false
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -436,6 +436,8 @@ function facility.new(config)
|
|||||||
if ready then self.mode = self.mode_set end
|
if ready then self.mode = self.mode_set end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
log.debug(util.c("FAC: process start ", util.trinary(ready, "accepted", "rejected")))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ready,
|
ready,
|
||||||
self.mode_set,
|
self.mode_set,
|
||||||
|
|||||||
@ -22,7 +22,7 @@ local supervisor = require("supervisor.supervisor")
|
|||||||
|
|
||||||
local svsessions = require("supervisor.session.svsessions")
|
local svsessions = require("supervisor.session.svsessions")
|
||||||
|
|
||||||
local SUPERVISOR_VERSION = "v1.5.8"
|
local SUPERVISOR_VERSION = "v1.5.9"
|
||||||
|
|
||||||
local println = util.println
|
local println = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user