From c299dce8ef32c26c33fe5230fe582dd40649224e Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Tue, 27 Aug 2024 23:02:31 -0400 Subject: [PATCH] #498 work on pocket control app and support process code --- pocket/iocontrol.lua | 30 ++- pocket/pocket.lua | 36 +++- pocket/process.lua | 342 ++++++++++++++++++++++++++++++++++ pocket/ui/apps/control.lua | 199 ++++++++++++++++++++ pocket/ui/main.lua | 2 + pocket/ui/pages/home_page.lua | 2 +- 6 files changed, 604 insertions(+), 7 deletions(-) create mode 100644 pocket/process.lua create mode 100644 pocket/ui/apps/control.lua diff --git a/pocket/iocontrol.lua b/pocket/iocontrol.lua index d7964fb..0e97602 100644 --- a/pocket/iocontrol.lua +++ b/pocket/iocontrol.lua @@ -8,6 +8,8 @@ local psil = require("scada-common.psil") local types = require("scada-common.types") local util = require("scada-common.util") +local process = require("pocket.process") + local ALARM = types.ALARM local ALARM_STATE = types.ALARM_STATE @@ -38,6 +40,15 @@ local io = { ps = psil.create() } +-- luacheck: no unused args + +-- placeholder acknowledge function for type hinting +---@param success boolean +---@diagnostic disable-next-line: unused-local +local function __generic_ack(success) end + +-- luacheck: unused args + local config = nil ---@type pkt_config -- initialize facility-independent components of pocket iocontrol @@ -91,6 +102,9 @@ function iocontrol.init_core(comms, nav, cfg) io.api = { get_unit = function (unit) comms.api__get_unit(unit) end } + + -- pass IO control here since it can't be require'd due to a require loop + process.init(io, comms) end -- initialize facility-dependent components of pocket iocontrol @@ -300,6 +314,20 @@ function iocontrol.init_fac(conf) -- auto control group a_group = 0, + start = function () process.start(i) end, + scram = function () process.scram(i) end, + reset_rps = function () process.reset_rps(i) end, + ack_alarms = function () process.ack_all_alarms(i) end, + set_burn = function (rate) process.set_rate(i, rate) end, ---@param rate number burn rate + set_waste = function (mode) process.set_unit_waste(i, mode) end, ---@param mode WASTE_MODE waste processing mode + + set_group = function (grp) process.set_group(i, grp) end, ---@param grp integer|0 group ID or 0 for manual + + start_ack = __generic_ack, + scram_ack = __generic_ack, + reset_rps_ack = __generic_ack, + ack_alarms_ack = __generic_ack, + ---@type alarms alarms = { ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE, ALARM_STATE.INACTIVE }, @@ -689,7 +717,7 @@ function iocontrol.record_unit_data(data) --#region Status Information Display - local ecam = {} -- aviation reference :) back to VATSIM I go... + local ecam = {} -- aviation reference :) -- local function red(text) return { text = text, color = colors.red } end local function white(text) return { text = text, color = colors.white } end diff --git a/pocket/pocket.lua b/pocket/pocket.lua index a8867fb..060329b 100644 --- a/pocket/pocket.lua +++ b/pocket/pocket.lua @@ -9,6 +9,8 @@ local DEVICE_TYPE = comms.DEVICE_TYPE local ESTABLISH_ACK = comms.ESTABLISH_ACK local MGMT_TYPE = comms.MGMT_TYPE local CRDN_TYPE = comms.CRDN_TYPE +local UNIT_COMMAND = comms.UNIT_COMMAND +local FAC_COMMAND = comms.FAC_COMMAND local LINK_STATE = iocontrol.LINK_STATE @@ -84,13 +86,14 @@ local APP_ID = { LOADER = 2, -- main app pages UNITS = 3, - GUIDE = 4, - ABOUT = 5, + CONTROL = 4, + GUIDE = 5, + ABOUT = 6, -- diag app page - ALARMS = 6, + ALARMS = 7, -- other - DUMMY = 7, - NUM_APPS = 7 + DUMMY = 8, + NUM_APPS = 8 } pocket.APP_ID = APP_ID @@ -541,6 +544,29 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav) if self.api.linked then _send_api(CRDN_TYPE.API_GET_UNIT, { unit }) end end + -- send a facility command + ---@param cmd FAC_COMMAND command + ---@param option any? optional option options for the optional options (like waste mode) + function public.send_fac_command(cmd, option) + _send_api(CRDN_TYPE.FAC_CMD, { cmd, option }) + 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) + _send_api(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 + }) + end + + -- send a unit command + ---@param cmd UNIT_COMMAND command + ---@param unit integer unit ID + ---@param option any? optional option options for the optional options (like burn rate) + function public.send_unit_command(cmd, unit, option) + _send_api(CRDN_TYPE.UNIT_CMD, { cmd, unit, option }) + end + -- parse a packet ---@param side string ---@param sender integer diff --git a/pocket/process.lua b/pocket/process.lua new file mode 100644 index 0000000..06578d5 --- /dev/null +++ b/pocket/process.lua @@ -0,0 +1,342 @@ +-- +-- Process Control Management +-- + +local comms = require("scada-common.comms") +local log = require("scada-common.log") +local types = require("scada-common.types") +local util = require("scada-common.util") + +local FAC_COMMAND = comms.FAC_COMMAND +local UNIT_COMMAND = comms.UNIT_COMMAND + +local PROCESS = types.PROCESS +local PRODUCT = types.WASTE_PRODUCT + +---@class pocket_process_controller +local process = {} + +local self = { + io = nil, ---@type ioctl + comms = nil, ---@type pocket_comms + ---@class sys_control_states + control_states = { + ---@class sys_auto_config + process = { + mode = PROCESS.INACTIVE, + burn_target = 0.0, + charge_target = 0.0, + gen_target = 0.0, + limits = {}, + waste_product = PRODUCT.PLUTONIUM, + pu_fallback = false, + sps_low_power = false + }, + waste_modes = {}, + priority_groups = {} + } +} + +-------------------------- +-- UNIT COMMAND CONTROL -- +-------------------------- + +-- initialize the process controller +---@param iocontrol pocket_ioctl iocontrl system +---@param pocket_comms pocket_comms pocket communications +function process.init(iocontrol, pocket_comms) + self.io = iocontrol + self.comms = pocket_comms + + local ctl_proc = self.control_states.process + + for i = 1, self.io.facility.num_units do + ctl_proc.limits[i] = 0.1 + end + + local ctrl_states = settings.get("ControlStates", {}) + local config = ctrl_states.process ---@type sys_auto_config + + -- facility auto control configuration + if type(config) == "table" then + ctl_proc.mode = config.mode + ctl_proc.burn_target = config.burn_target + ctl_proc.charge_target = config.charge_target + ctl_proc.gen_target = config.gen_target + ctl_proc.limits = config.limits + ctl_proc.waste_product = config.waste_product + ctl_proc.pu_fallback = config.pu_fallback + ctl_proc.sps_low_power = config.sps_low_power + + self.io.facility.ps.publish("process_mode", ctl_proc.mode) + self.io.facility.ps.publish("process_burn_target", ctl_proc.burn_target) + self.io.facility.ps.publish("process_charge_target", self.io.energy_convert_from_fe(ctl_proc.charge_target)) + self.io.facility.ps.publish("process_gen_target", self.io.energy_convert_from_fe(ctl_proc.gen_target)) + self.io.facility.ps.publish("process_waste_product", ctl_proc.waste_product) + self.io.facility.ps.publish("process_pu_fallback", ctl_proc.pu_fallback) + self.io.facility.ps.publish("process_sps_low_power", ctl_proc.sps_low_power) + + for id = 1, math.min(#ctl_proc.limits, self.io.facility.num_units) do + local unit = self.io.units[id] ---@type ioctl_unit + unit.unit_ps.publish("burn_limit", ctl_proc.limits[id]) + end + + log.info("PROCESS: loaded auto control settings") + + -- notify supervisor of auto waste config + self.comms.send_fac_command(FAC_COMMAND.SET_WASTE_MODE, ctl_proc.waste_product) + self.comms.send_fac_command(FAC_COMMAND.SET_PU_FB, ctl_proc.pu_fallback) + self.comms.send_fac_command(FAC_COMMAND.SET_SPS_LP, ctl_proc.sps_low_power) + end + + -- unit waste states + local waste_modes = ctrl_states.waste_modes ---@type table|nil + if type(waste_modes) == "table" then + for id, mode in pairs(waste_modes) do + self.control_states.waste_modes[id] = mode + self.comms.send_unit_command(UNIT_COMMAND.SET_WASTE, id, mode) + end + + log.info("PROCESS: loaded unit waste mode settings") + end + + -- unit priority groups + local prio_groups = ctrl_states.priority_groups ---@type table|nil + if type(prio_groups) == "table" then + for id, group in pairs(prio_groups) do + self.control_states.priority_groups[id] = group + self.comms.send_unit_command(UNIT_COMMAND.SET_GROUP, id, group) + end + + log.info("PROCESS: loaded priority groups settings") + end +end + +function process.init_fac_data() +end + +-- facility SCRAM command +function process.fac_scram() + self.comms.send_fac_command(FAC_COMMAND.SCRAM_ALL) + log.debug("PROCESS: FAC SCRAM ALL") +end + +-- facility alarm acknowledge command +function process.fac_ack_alarms() + self.comms.send_fac_command(FAC_COMMAND.ACK_ALL_ALARMS) + log.debug("PROCESS: FAC ACK ALL ALARMS") +end + +-- start reactor +---@param id integer unit ID +function process.start(id) + self.io.units[id].control_state = true + self.comms.send_unit_command(UNIT_COMMAND.START, id) + log.debug(util.c("PROCESS: UNIT[", id, "] START")) +end + +-- SCRAM reactor +---@param id integer unit ID +function process.scram(id) + self.io.units[id].control_state = false + self.comms.send_unit_command(UNIT_COMMAND.SCRAM, id) + log.debug(util.c("PROCESS: UNIT[", id, "] SCRAM")) +end + +-- reset reactor protection system +---@param id integer unit ID +function process.reset_rps(id) + self.comms.send_unit_command(UNIT_COMMAND.RESET_RPS, id) + log.debug(util.c("PROCESS: UNIT[", id, "] RESET RPS")) +end + +-- set burn rate +---@param id integer unit ID +---@param rate number burn rate +function process.set_rate(id, rate) + self.comms.send_unit_command(UNIT_COMMAND.SET_BURN, id, rate) + log.debug(util.c("PROCESS: UNIT[", id, "] SET BURN ", rate)) +end + +-- set waste mode +---@param id integer unit ID +---@param mode integer waste mode +function process.set_unit_waste(id, mode) + -- publish so that if it fails then it gets reset + self.io.units[id].unit_ps.publish("U_WasteMode", mode) + + self.comms.send_unit_command(UNIT_COMMAND.SET_WASTE, id, mode) + log.debug(util.c("PROCESS: UNIT[", id, "] SET WASTE ", mode)) + + self.control_states.waste_modes[id] = mode + settings.set("ControlStates", self.control_states) + + if not settings.save("/coordinator.settings") then + log.error("process.set_unit_waste(): failed to save coordinator settings file") + end +end + +-- acknowledge all alarms +---@param id integer unit ID +function process.ack_all_alarms(id) + self.comms.send_unit_command(UNIT_COMMAND.ACK_ALL_ALARMS, id) + log.debug(util.c("PROCESS: UNIT[", id, "] ACK ALL ALARMS")) +end + +-- acknowledge an alarm +---@param id integer unit ID +---@param alarm integer alarm ID +function process.ack_alarm(id, alarm) + self.comms.send_unit_command(UNIT_COMMAND.ACK_ALARM, id, alarm) + log.debug(util.c("PROCESS: UNIT[", id, "] ACK ALARM ", alarm)) +end + +-- reset an alarm +---@param id integer unit ID +---@param alarm integer alarm ID +function process.reset_alarm(id, alarm) + self.comms.send_unit_command(UNIT_COMMAND.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) + 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)) + + self.control_states.priority_groups[unit_id] = group_id + settings.set("ControlStates", self.control_states) + + if not settings.save("/coordinator.settings") then + log.error("process.set_group(): failed to save coordinator settings file") + end +end + +-------------------------- +-- AUTO PROCESS CONTROL -- +-------------------------- + +-- write auto process control to config file +local function _write_auto_config() + -- save config + settings.set("ControlStates", self.control_states) + local saved = settings.save("/coordinator.settings") + if not saved then + log.warning("process._write_auto_config(): failed to save coordinator settings file") + end + + return saved +end + +-- stop automatic process control +function process.stop_auto() + self.comms.send_fac_command(FAC_COMMAND.STOP) + log.debug("PROCESS: STOP AUTO CTL") +end + +-- start automatic process control +function process.start_auto() + self.comms.send_auto_start(self.control_states.process) + log.debug("PROCESS: START AUTO CTL") +end + +-- set automatic process control waste mode +---@param product WASTE_PRODUCT waste product for auto control +function process.set_process_waste(product) + self.comms.send_fac_command(FAC_COMMAND.SET_WASTE_MODE, product) + + log.debug(util.c("PROCESS: SET WASTE ", product)) + + -- update config table and save + self.control_states.process.waste_product = product + _write_auto_config() +end + +-- set automatic process control plutonium fallback +---@param enabled boolean whether to enable plutonium fallback +function process.set_pu_fallback(enabled) + self.comms.send_fac_command(FAC_COMMAND.SET_PU_FB, enabled) + + log.debug(util.c("PROCESS: SET PU FALLBACK ", enabled)) + + -- update config table and save + self.control_states.process.pu_fallback = enabled + _write_auto_config() +end + +-- set automatic process control SPS usage at low power +---@param enabled boolean whether to enable SPS usage at low power +function process.set_sps_low_power(enabled) + self.comms.send_fac_command(FAC_COMMAND.SET_SPS_LP, enabled) + + log.debug(util.c("PROCESS: SET SPS LOW POWER ", enabled)) + + -- update config table and save + self.control_states.process.sps_low_power = enabled + _write_auto_config() +end + +-- save process control settings +---@param mode PROCESS control mode +---@param burn_target number burn rate target +---@param charge_target number charge target +---@param gen_target number generation rate target +---@param limits table unit burn rate limits +function process.save(mode, burn_target, charge_target, gen_target, limits) + log.debug("PROCESS: SAVE") + + -- update config table + local ctl_proc = self.control_states.process + ctl_proc.mode = mode + ctl_proc.burn_target = burn_target + ctl_proc.charge_target = charge_target + ctl_proc.gen_target = gen_target + ctl_proc.limits = limits + + -- save config + self.io.facility.save_cfg_ack(_write_auto_config()) +end + +-- handle a start command acknowledgement +---@param response table ack and configuration reply +function process.start_ack_handle(response) + local ack = response[1] + + local ctl_proc = self.control_states.process + ctl_proc.mode = response[2] + ctl_proc.burn_target = response[3] + ctl_proc.charge_target = response[4] + ctl_proc.gen_target = response[5] + + for i = 1, math.min(#response[6], self.io.facility.num_units) do + ctl_proc.limits[i] = response[6][i] + + local unit = self.io.units[i] ---@type ioctl_unit + unit.unit_ps.publish("burn_limit", ctl_proc.limits[i]) + end + + self.io.facility.ps.publish("process_mode", ctl_proc.mode) + self.io.facility.ps.publish("process_burn_target", ctl_proc.burn_target) + self.io.facility.ps.publish("process_charge_target", self.io.energy_convert_from_fe(ctl_proc.charge_target)) + self.io.facility.ps.publish("process_gen_target", self.io.energy_convert_from_fe(ctl_proc.gen_target)) + + self.io.facility.start_ack(ack) +end + +-- record waste product state after attempting to change it +---@param response WASTE_PRODUCT supervisor waste product state +function process.waste_ack_handle(response) + self.control_states.process.waste_product = response + self.io.facility.ps.publish("process_waste_product", response) +end + +-- record plutonium fallback state after attempting to change it +---@param response boolean supervisor plutonium fallback state +function process.pu_fb_ack_handle(response) + self.control_states.process.pu_fallback = response + self.io.facility.ps.publish("process_pu_fallback", response) +end + +return process diff --git a/pocket/ui/apps/control.lua b/pocket/ui/apps/control.lua new file mode 100644 index 0000000..cc533d2 --- /dev/null +++ b/pocket/ui/apps/control.lua @@ -0,0 +1,199 @@ +-- +-- Unit Control Page +-- + +local util = require("scada-common.util") + +local iocontrol = require("pocket.iocontrol") +local pocket = require("pocket.pocket") + +local style = require("pocket.ui.style") + +local core = require("graphics.core") + +local Div = require("graphics.elements.div") +local ListBox = require("graphics.elements.listbox") +local MultiPane = require("graphics.elements.multipane") +local TextBox = require("graphics.elements.textbox") + +local WaitingAnim = require("graphics.elements.animations.waiting") + +local HazardButton = require("graphics.elements.controls.hazard_button") +local PushButton = require("graphics.elements.controls.push_button") + +local NumberField = require("graphics.elements.form.number_field") + +local DataIndicator = require("graphics.elements.indicators.data") +local IconIndicator = require("graphics.elements.indicators.icon") + +local ALIGN = core.ALIGN +local cpair = core.cpair + +local APP_ID = pocket.APP_ID + +-- local label = style.label +local lu_col = style.label_unit_pair +local text_fg = style.text_fg +local basic_states = style.icon_states.basic_states +local mode_states = style.icon_states.mode_states +local red_ind_s = style.icon_states.red_ind_s +local yel_ind_s = style.icon_states.yel_ind_s + + +local hzd_fg_bg = cpair(colors.white, colors.gray) +local dis_colors = cpair(colors.white, colors.lightGray) + +local emc_ind_s = { + { color = cpair(colors.black, colors.gray), symbol = "-" }, + { color = cpair(colors.black, colors.white), symbol = "\x07" }, + { color = cpair(colors.black, colors.green), symbol = "+" } +} + +-- new unit control page view +---@param root graphics_element 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.CONTROL, 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.green,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 = function () db.nav.open_app(APP_ID.ROOT) end } }) + + local btn_fg_bg = cpair(colors.green, colors.black) + local btn_active = cpair(colors.white, colors.black) + + local page_div = nil ---@type nil|graphics_element + + -- set sidebar to display unit-specific fields based on a specified unit + local function set_sidebar() + local list = { + { label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = function () db.nav.open_app(APP_ID.ROOT) end }, + } + + 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) + end + + -- load the app (create the elements) + local function load() + page_div = Div{parent=main,y=2,width=main.get_width()} + + local panes = {} + + local active_unit = 1 + + -- create all page divs + for _ = 1, db.facility.num_units do + local div = Div{parent=page_div} + table.insert(panes, div) + end + + -- previous unit + local function prev(x) + active_unit = util.trinary(x == 1, db.facility.num_units, x - 1) + app.switcher(active_unit) + end + + -- next unit + local function next(x) + active_unit = util.trinary(x == db.facility.num_units, 1, x + 1) + app.switcher(active_unit) + end + + 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] ---@type pioctl_unit + local u_ps = unit.unit_ps + + -- refresh data callback, every 500ms it will re-send the query + local last_update = 0 + local function update() + if util.time_ms() - last_update >= 500 then + db.api.get_unit(i) + last_update = util.time_ms() + end + end + + --#region Main Unit Overview + + 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} + PushButton{parent=u_div,x=1,y=1,text="<",fg_bg=btn_fg_bg,active_fg_bg=btn_active,callback=function()prev(i)end} + PushButton{parent=u_div,x=21,y=1,text=">",fg_bg=btn_fg_bg,active_fg_bg=btn_active,callback=function()next(i)end} + + local rate = DataIndicator{parent=u_div,y=3,lu_colors=lu_col,label="Burn",unit="mB/t",format="%10.2f",value=0,commas=true,width=26,fg_bg=text_fg} + local temp = DataIndicator{parent=u_div,lu_colors=lu_col,label="Temp",unit=db.temp_label,format="%10.2f",value=0,commas=true,width=26,fg_bg=text_fg} + + local ctrl = IconIndicator{parent=u_div,x=1,y=6,label="Control State",states=mode_states} + + rate.register(u_ps, "act_burn_rate", rate.update) + temp.register(u_ps, "temp", function (t) temp.update(db.temp_convert(t)) end) + ctrl.register(u_ps, "U_ControlStatus", ctrl.update) + + 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,x=14,y=8,text="mB/t",width=4,fg_bg=cpair(colors.lightGray,colors.black)} + 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)} + + local set_burn = function () unit.set_burn(burn_cmd.get_value()) 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} + + 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,fg_bg=hzd_fg_bg} + 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,fg_bg=hzd_fg_bg} + local scram = HazardButton{parent=u_div,x=2,y=15,text="SCRAM",accent=colors.yellow,dis_colors=dis_colors,callback=unit.scram,fg_bg=hzd_fg_bg} + local reset = HazardButton{parent=u_div,x=12,y=15,text="RESET",accent=colors.red,dis_colors=dis_colors,callback=unit.reset_rps,fg_bg=hzd_fg_bg} + + --#endregion + + util.nop() + end + + -- setup multipane + local u_pane = MultiPane{parent=page_div,x=1,y=1,panes=panes} + app.set_root_pane(u_pane) + + set_sidebar() + + -- done, show the app + 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 = function () db.nav.open_app(APP_ID.ROOT) end } }) + 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 diff --git a/pocket/ui/main.lua b/pocket/ui/main.lua index 080371c..bf66f9b 100644 --- a/pocket/ui/main.lua +++ b/pocket/ui/main.lua @@ -7,6 +7,7 @@ local util = require("scada-common.util") local iocontrol = require("pocket.iocontrol") local pocket = require("pocket.pocket") +local control_app = require("pocket.ui.apps.control") local diag_apps = require("pocket.ui.apps.diag_apps") local dummy_app = require("pocket.ui.apps.dummy_app") local guide_app = require("pocket.ui.apps.guide") @@ -62,6 +63,7 @@ local function init(main) -- create all the apps & pages home_page(page_div) unit_app(page_div) + control_app(page_div) guide_app(page_div) loader_app(page_div) sys_apps(page_div) diff --git a/pocket/ui/pages/home_page.lua b/pocket/ui/pages/home_page.lua index b143728..38385be 100644 --- a/pocket/ui/pages/home_page.lua +++ b/pocket/ui/pages/home_page.lua @@ -47,7 +47,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=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.DUMMY)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=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}