diff --git a/coordinator/coordinator.lua b/coordinator/coordinator.lua index 78748c8..71da387 100644 --- a/coordinator/coordinator.lua +++ b/coordinator/coordinator.lua @@ -387,10 +387,14 @@ function coordinator.comms(version, nic, sv_watchdog) end -- send the auto process control configuration with a start command - ---@param auto_cfg sys_auto_config configuration - function public.send_auto_start(auto_cfg) + ---@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 public.send_auto_start(mode, burn_target, charge_target, gen_target, limits) _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 @@ -578,7 +582,7 @@ function coordinator.comms(version, nic, sv_watchdog) if cmd == FAC_COMMAND.SCRAM_ALL then process.fac_ack(cmd, ack) elseif cmd == FAC_COMMAND.STOP then - iocontrol.get_db().facility.stop_ack(ack) + process.fac_ack(cmd, ack) elseif cmd == FAC_COMMAND.START then if packet.length == 7 then process.start_ack_handle({ table.unpack(packet.data, 2) }) diff --git a/coordinator/iocontrol.lua b/coordinator/iocontrol.lua index aa436a6..d28c5c9 100644 --- a/coordinator/iocontrol.lua +++ b/coordinator/iocontrol.lua @@ -107,8 +107,6 @@ function iocontrol.init(conf, comms, temp_scale, energy_scale) radiation = types.new_zero_radiation_reading(), 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 } alarm_tones = { false, false, false, false, false, false, false, false }, diff --git a/coordinator/process.lua b/coordinator/process.lua index f96b3e7..183a815 100644 --- a/coordinator/process.lua +++ b/coordinator/process.lua @@ -25,12 +25,12 @@ local pctl = { control_states = { ---@class sys_auto_config process = { - mode = PROCESS.INACTIVE, + mode = PROCESS.INACTIVE, ---@type PROCESS burn_target = 0.0, charge_target = 0.0, gen_target = 0.0, - limits = {}, ---@type number[] - waste_product = PRODUCT.PLUTONIUM, + limits = {}, ---@type number[] + waste_product = PRODUCT.PLUTONIUM, ---@type WASTE_PRODUCT pu_fallback = false, sps_low_power = false }, @@ -49,6 +49,7 @@ local pctl = { ---@field requestors function[] list of callbacks from the requestors -- write auto process control to config file +---@return boolean saved local function _write_auto_config() -- save config settings.set("ControlStates", pctl.control_states) @@ -180,6 +181,36 @@ function process.create_handle() 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 = {} -- luacheck: no unused args @@ -194,6 +225,16 @@ function process.create_handle() ---@diagnostic disable-next-line: unused-local 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 --#endregion @@ -335,6 +376,21 @@ function process.set_rate(id, rate) log.debug(util.c("PROCESS: UNIT[", id, "] SET BURN ", rate)) 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 ---@param id integer unit ID ---@param mode integer waste mode @@ -369,39 +425,12 @@ function process.reset_alarm(id, alarm) log.debug(util.c("PROCESS: UNIT[", id, "] RESET ALARM ", alarm)) 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 -------------------------- -- 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 ---@param product WASTE_PRODUCT waste product for auto control function process.set_process_waste(product) @@ -439,9 +468,9 @@ function process.set_sps_low_power(enabled) end -- save process control settings ----@param mode PROCESS control mode +---@param mode PROCESS process control mode ---@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 limits number[] unit burn rate limits function process.save(mode, burn_target, charge_target, gen_target, limits) @@ -472,9 +501,7 @@ function process.start_ack_handle(response) for i = 1, math.min(#response[6], pctl.io.facility.num_units) do ctl_proc.limits[i] = response[6][i] - - local unit = pctl.io.units[i] - unit.unit_ps.publish("burn_limit", ctl_proc.limits[i]) + pctl.io.units[i].unit_ps.publish("burn_limit", ctl_proc.limits[i]) end pctl.io.facility.ps.publish("process_mode", ctl_proc.mode) @@ -482,7 +509,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_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 -- record waste product settting after attempting to change it diff --git a/coordinator/session/pocket.lua b/coordinator/session/pocket.lua index 25dd2da..3572d97 100644 --- a/coordinator/session/pocket.lua +++ b/coordinator/session/pocket.lua @@ -108,14 +108,20 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout) -- link callback transmissions - self.proc_handle.fac_ack.on_scram = function (success) _send(CRDN_TYPE.FAC_CMD, { FAC_COMMAND.SCRAM_ALL, success }) end - self.proc_handle.fac_ack.on_ack_alarms = function (success) _send(CRDN_TYPE.FAC_CMD, { FAC_COMMAND.ACK_ALL_ALARMS, success }) end + local f_ack = self.proc_handle.fac_ack + + 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 - self.proc_handle.unit_ack[u].on_start = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.START, u, success }) end - self.proc_handle.unit_ack[u].on_scram = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.SCRAM, 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 - self.proc_handle.unit_ack[u].on_ack_alarms = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.ACK_ALL_ALARMS, u, success }) end + local u_ack = self.proc_handle.unit_ack[u] + u_ack.on_start = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.START, u, success }) end + u_ack.on_scram = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.SCRAM, 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 -- 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") self.proc_handle.fac_scram() elseif cmd == FAC_COMMAND.STOP then + log.info(log_tag .. "STOP PROCESS CTRL") + self.proc_handle.process_stop() 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 log.info(log_tag .. "FAC ACK ALL 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.RESET_ALARM 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 log.debug(log_tag .. "CRDN unit command unknown") end diff --git a/coordinator/startup.lua b/coordinator/startup.lua index d712fa9..9cd8e61 100644 --- a/coordinator/startup.lua +++ b/coordinator/startup.lua @@ -19,7 +19,7 @@ local renderer = require("coordinator.renderer") local sounder = require("coordinator.sounder") local threads = require("coordinator.threads") -local COORDINATOR_VERSION = "v1.5.11" +local COORDINATOR_VERSION = "v1.5.12" local CHUNK_LOAD_DELAY_S = 30.0 diff --git a/coordinator/ui/components/process_ctl.lua b/coordinator/ui/components/process_ctl.lua index 44c9ceb..f49964b 100644 --- a/coordinator/ui/components/process_ctl.lua +++ b/coordinator/ui/components/process_ctl.lua @@ -273,15 +273,15 @@ local function new_view(root, x, y) -- start automatic control after saving process control settings local function _start_auto() _save_cfg() - process.start_auto() + db.process.process_start() 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 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 - facility.stop_ack = stop.on_response + db.process.fac_ack.on_start = start.on_response + db.process.fac_ack.on_stop = stop.on_response function facility.save_cfg_ack(ack) tcd.dispatch(0.2, function () save.on_response(ack) end) diff --git a/pocket/pocket.lua b/pocket/pocket.lua index 74a85c5..4b0de9d 100644 --- a/pocket/pocket.lua +++ b/pocket/pocket.lua @@ -562,6 +562,12 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav) _send_api(CRDN_TYPE.FAC_CMD, { cmd, option }) 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 ---@param cmd UNIT_COMMAND command ---@param unit integer unit ID @@ -664,7 +670,9 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav) if cmd == FAC_COMMAND.SCRAM_ALL then iocontrol.get_db().facility.scram_ack(ack) elseif cmd == FAC_COMMAND.STOP then + iocontrol.get_db().facility.stop_ack(ack) elseif cmd == FAC_COMMAND.START then + iocontrol.get_db().facility.start_ack(ack) elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then iocontrol.get_db().facility.ack_alarms_ack(ack) elseif cmd == FAC_COMMAND.SET_WASTE_MODE then diff --git a/pocket/process.lua b/pocket/process.lua index 454caff..2d317c6 100644 --- a/pocket/process.lua +++ b/pocket/process.lua @@ -25,6 +25,10 @@ function process.init(iocontrol, pocket_comms) self.comms = pocket_comms end + +------------------------------ +--#region FACILITY COMMANDS -- + -- facility SCRAM command function process.fac_scram() self.comms.send_fac_command(FAC_COMMAND.SCRAM_ALL) @@ -37,6 +41,12 @@ function process.fac_ack_alarms() log.debug("PROCESS: FAC ACK ALL ALARMS") end +--#endregion +------------------------------ + +-------------------------- +--#region UNIT COMMANDS -- + -- start reactor ---@param id integer unit ID function process.start(id) @@ -68,6 +78,14 @@ function process.set_rate(id, rate) log.debug(util.c("PROCESS: UNIT[", id, "] SET BURN ", rate)) 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(UNIT_COMMAND.SET_GROUP, unit_id, group_id) + log.debug(util.c("PROCESS: UNIT[", unit_id, "] SET GROUP ", group_id)) +end + -- acknowledge all alarms ---@param id integer unit ID function process.ack_all_alarms(id) @@ -91,4 +109,30 @@ function process.reset_alarm(id, alarm) log.debug(util.c("PROCESS: UNIT[", id, "] RESET ALARM ", alarm)) 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(FAC_COMMAND.STOP) + log.debug("PROCESS: STOP AUTO CTRL") +end + +-- #endregion +--------------------------------- + return process diff --git a/pocket/startup.lua b/pocket/startup.lua index 304b1cc..0f6fe40 100644 --- a/pocket/startup.lua +++ b/pocket/startup.lua @@ -20,7 +20,7 @@ local pocket = require("pocket.pocket") local renderer = require("pocket.renderer") local threads = require("pocket.threads") -local POCKET_VERSION = "v0.12.6-alpha" +local POCKET_VERSION = "v0.12.7-alpha" local println = util.println local println_ts = util.println_ts