diff --git a/pocket/pocket.lua b/pocket/pocket.lua index c6f833b..c30422a 100644 --- a/pocket/pocket.lua +++ b/pocket/pocket.lua @@ -96,11 +96,12 @@ local APP_ID = { WASTE = 7, GUIDE = 8, ABOUT = 9, + RADMON = 10, -- diagnostic app pages - ALARMS = 10, + ALARMS = 11, -- other - DUMMY = 11, - NUM_APPS = 11 + DUMMY = 12, + NUM_APPS = 12 } pocket.APP_ID = APP_ID diff --git a/pocket/ui/apps/radiation.lua b/pocket/ui/apps/radiation.lua new file mode 100644 index 0000000..5c14a4a --- /dev/null +++ b/pocket/ui/apps/radiation.lua @@ -0,0 +1,219 @@ +-- +-- Radiation Monitor App +-- + +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 radiation monitor 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.RADMON, 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.yellow,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 + 2 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_rad() + last_update = util.time_ms() + end + end + + --#region unit radiation monitors + + 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="Unit #"..i.." Monitors",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 overview page + + local s_pane = panes[db.facility.num_units + 1] + local s_div = Div{parent=s_pane,x=2,width=main.get_width()-2} + + local stat_page = app.new_page(nil, db.facility.num_units + 1) + stat_page.tasks = { update } + + TextBox{parent=s_div,y=1,text="Radiation Monitors",alignment=ALIGN.CENTER} + + --#endregion + + --#region overview page + + local f_pane = panes[db.facility.num_units + 2] + local f_div = Div{parent=f_pane,x=2,width=main.get_width()-2} + + local fac_page = app.new_page(nil, db.facility.num_units + 2) + fac_page.tasks = { update } + + TextBox{parent=f_div,y=1,text="Facility Monitors",alignment=ALIGN.CENTER} + + --#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 = " \x1e ", color = core.cpair(colors.black, colors.blue), callback = stat_page.nav_to }, + { label = "FAC", color = core.cpair(colors.black, colors.yellow), callback = fac_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 + stat_page.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 diff --git a/pocket/ui/main.lua b/pocket/ui/main.lua index 588cf0b..e033777 100644 --- a/pocket/ui/main.lua +++ b/pocket/ui/main.lua @@ -14,6 +14,7 @@ local facil_app = require("pocket.ui.apps.facility") local guide_app = require("pocket.ui.apps.guide") local loader_app = require("pocket.ui.apps.loader") local process_app = require("pocket.ui.apps.process") +local rad_app = require("pocket.ui.apps.radiation") local sys_apps = require("pocket.ui.apps.sys_apps") local unit_app = require("pocket.ui.apps.unit") local waste_app = require("pocket.ui.apps.waste") @@ -71,6 +72,7 @@ local function init(main) process_app(page_div) waste_app(page_div) guide_app(page_div) + rad_app(page_div) loader_app(page_div) sys_apps(page_div) diag_apps(page_div) diff --git a/pocket/ui/pages/home_page.lua b/pocket/ui/pages/home_page.lua index ada6e92..80fdd3f 100644 --- a/pocket/ui/pages/home_page.lua +++ b/pocket/ui/pages/home_page.lua @@ -29,8 +29,9 @@ local function new_view(root) local apps_1 = Div{parent=main,x=1,y=1,height=15} local apps_2 = Div{parent=main,x=1,y=1,height=15} + local apps_3 = Div{parent=main,x=1,y=1,height=15} - local panes = { apps_1, apps_2 } + local panes = { apps_1, apps_2, apps_3 } local app_pane = AppMultiPane{parent=main,x=1,y=1,height=18,panes=panes,active_color=colors.lightGray,nav_colors=cpair(colors.lightGray,colors.gray),scroll_nav=true,drag_nav=true,callback=app.switcher} @@ -50,15 +51,17 @@ local function new_view(root) App{parent=apps_1,x=16,y=2,text="\x15",title="Control",callback=function()open(APP_ID.CONTROL)end,app_fg_bg=cpair(colors.black,colors.green),active_fg_bg=active_fg_bg} App{parent=apps_1,x=2,y=7,text="\x17",title="Process",callback=function()open(APP_ID.PROCESS)end,app_fg_bg=cpair(colors.black,colors.purple),active_fg_bg=active_fg_bg} App{parent=apps_1,x=9,y=7,text="\x7f",title="Waste",callback=function()open(APP_ID.WASTE)end,app_fg_bg=cpair(colors.black,colors.brown),active_fg_bg=active_fg_bg} - App{parent=apps_1,x=16,y=7,text="\x08",title="Devices",callback=function()open(APP_ID.DUMMY)end,app_fg_bg=cpair(colors.black,colors.lightGray),active_fg_bg=active_fg_bg} - App{parent=apps_1,x=2,y=12,text="\xb6",title="Guide",callback=function()open(APP_ID.GUIDE)end,app_fg_bg=cpair(colors.black,colors.cyan),active_fg_bg=active_fg_bg} - App{parent=apps_1,x=9,y=12,text="?",title="About",callback=function()open(APP_ID.ABOUT)end,app_fg_bg=cpair(colors.black,colors.white),active_fg_bg=active_fg_bg} + App{parent=apps_1,x=16,y=7,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="?",title="About",callback=function()open(APP_ID.ABOUT)end,app_fg_bg=cpair(colors.black,colors.white),active_fg_bg=active_fg_bg} - TextBox{parent=apps_2,text="Diagnostic Apps",x=1,y=2,alignment=ALIGN.CENTER} + App{parent=apps_2,x=2,y=2,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_2,x=9,y=2,text="\x1e",title="Rad",callback=function()open(APP_ID.RADMON)end,app_fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=active_fg_bg} - App{parent=apps_2,x=2,y=4,text="\x0f",title="Alarm",callback=function()open(APP_ID.ALARMS)end,app_fg_bg=cpair(colors.black,colors.red),active_fg_bg=active_fg_bg} - App{parent=apps_2,x=9,y=4,text="\x1e",title="LoopT",callback=function()open(APP_ID.DUMMY)end,app_fg_bg=cpair(colors.black,colors.cyan),active_fg_bg=active_fg_bg} - App{parent=apps_2,x=16,y=4,text="@",title="Comps",callback=function()open(APP_ID.DUMMY)end,app_fg_bg=cpair(colors.black,colors.orange),active_fg_bg=active_fg_bg} + TextBox{parent=apps_3,text="Diagnostic Apps",x=1,y=2,alignment=ALIGN.CENTER} + + App{parent=apps_3,x=2,y=4,text="\x0f",title="Alarm",callback=function()open(APP_ID.ALARMS)end,app_fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=active_fg_bg} + App{parent=apps_3,x=9,y=4,text="@",title="Comps",callback=function()open(APP_ID.DUMMY)end,app_fg_bg=cpair(colors.black,colors.orange),active_fg_bg=active_fg_bg} + App{parent=apps_3,x=16,y=4,text="R",title="RS Test",callback=function()open(APP_ID.DUMMY)end,app_fg_bg=cpair(colors.black,colors.red),active_fg_bg=active_fg_bg} return main end