mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
#232 WIP coordinator flow view
This commit is contained in:
parent
7bd8f34773
commit
e0809f52a6
@ -55,6 +55,8 @@ function coordinator.configure_monitors(num_units)
|
|||||||
local monitors = {
|
local monitors = {
|
||||||
primary = nil,
|
primary = nil,
|
||||||
primary_name = "",
|
primary_name = "",
|
||||||
|
flow = nil,
|
||||||
|
flow_name = "",
|
||||||
unit_displays = {},
|
unit_displays = {},
|
||||||
unit_name_map = {}
|
unit_name_map = {}
|
||||||
}
|
}
|
||||||
@ -69,8 +71,8 @@ function coordinator.configure_monitors(num_units)
|
|||||||
table.insert(available, iface)
|
table.insert(available, iface)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- we need a certain number of monitors (1 per unit + 1 primary display)
|
-- we need a certain number of monitors (1 per unit + 1 primary display + 1 flow display)
|
||||||
local num_displays_needed = num_units + 1
|
local num_displays_needed = num_units + 2
|
||||||
if #names < num_displays_needed then
|
if #names < num_displays_needed then
|
||||||
local message = "not enough monitors connected (need " .. num_displays_needed .. ")"
|
local message = "not enough monitors connected (need " .. num_displays_needed .. ")"
|
||||||
println(message)
|
println(message)
|
||||||
@ -83,10 +85,12 @@ function coordinator.configure_monitors(num_units)
|
|||||||
log.warning("configure_monitors(): failed to load coordinator settings file (may not exist yet)")
|
log.warning("configure_monitors(): failed to load coordinator settings file (may not exist yet)")
|
||||||
else
|
else
|
||||||
local _primary = settings.get("PRIMARY_DISPLAY")
|
local _primary = settings.get("PRIMARY_DISPLAY")
|
||||||
|
local _flow = settings.get("FLOW_DISPLAY")
|
||||||
local _unitd = settings.get("UNIT_DISPLAYS")
|
local _unitd = settings.get("UNIT_DISPLAYS")
|
||||||
|
|
||||||
-- filter out already assigned monitors
|
-- filter out already assigned monitors
|
||||||
util.filter_table(available, function (x) return x ~= _primary end)
|
util.filter_table(available, function (x) return x ~= _primary end)
|
||||||
|
util.filter_table(available, function (x) return x ~= _flow end)
|
||||||
if type(_unitd) == "table" then
|
if type(_unitd) == "table" then
|
||||||
util.filter_table(available, function (x) return not util.table_contains(_unitd, x) end)
|
util.filter_table(available, function (x) return not util.table_contains(_unitd, x) end)
|
||||||
end
|
end
|
||||||
@ -106,7 +110,6 @@ function coordinator.configure_monitors(num_units)
|
|||||||
end
|
end
|
||||||
|
|
||||||
while iface_primary_display == nil and #available > 0 do
|
while iface_primary_display == nil and #available > 0 do
|
||||||
-- lets get a monitor
|
|
||||||
iface_primary_display = ask_monitor(available)
|
iface_primary_display = ask_monitor(available)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -118,6 +121,31 @@ function coordinator.configure_monitors(num_units)
|
|||||||
monitors.primary = ppm.get_periph(iface_primary_display)
|
monitors.primary = ppm.get_periph(iface_primary_display)
|
||||||
monitors.primary_name = iface_primary_display
|
monitors.primary_name = iface_primary_display
|
||||||
|
|
||||||
|
--------------------------
|
||||||
|
-- FLOW MONITOR DISPLAY --
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
local iface_flow_display = settings.get("FLOW_DISPLAY") ---@type boolean|string|nil
|
||||||
|
|
||||||
|
if not util.table_contains(names, iface_flow_display) then
|
||||||
|
println("flow monitor display is not connected")
|
||||||
|
local response = dialog.ask_y_n("would you like to change it", true)
|
||||||
|
if response == false then return false end
|
||||||
|
iface_flow_display = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
while iface_flow_display == nil and #available > 0 do
|
||||||
|
iface_flow_display = ask_monitor(available)
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(iface_flow_display) ~= "string" then return false end
|
||||||
|
|
||||||
|
settings.set("FLOW_DISPLAY", iface_flow_display)
|
||||||
|
util.filter_table(available, function (x) return x ~= iface_flow_display end)
|
||||||
|
|
||||||
|
monitors.flow = ppm.get_periph(iface_flow_display)
|
||||||
|
monitors.flow_name = iface_flow_display
|
||||||
|
|
||||||
-------------------
|
-------------------
|
||||||
-- UNIT DISPLAYS --
|
-- UNIT DISPLAYS --
|
||||||
-------------------
|
-------------------
|
||||||
@ -130,7 +158,6 @@ function coordinator.configure_monitors(num_units)
|
|||||||
local display = nil
|
local display = nil
|
||||||
|
|
||||||
while display == nil and #available > 0 do
|
while display == nil and #available > 0 do
|
||||||
-- lets get a monitor
|
|
||||||
println("please select monitor for unit #" .. i)
|
println("please select monitor for unit #" .. i)
|
||||||
display = ask_monitor(available)
|
display = ask_monitor(available)
|
||||||
end
|
end
|
||||||
@ -152,7 +179,6 @@ function coordinator.configure_monitors(num_units)
|
|||||||
end
|
end
|
||||||
|
|
||||||
while display == nil and #available > 0 do
|
while display == nil and #available > 0 do
|
||||||
-- lets get a monitor
|
|
||||||
display = ask_monitor(available)
|
display = ask_monitor(available)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ local iocontrol = require("coordinator.iocontrol")
|
|||||||
local style = require("coordinator.ui.style")
|
local style = require("coordinator.ui.style")
|
||||||
local pgi = require("coordinator.ui.pgi")
|
local pgi = require("coordinator.ui.pgi")
|
||||||
|
|
||||||
|
local flow_view = require("coordinator.ui.layout.flow_view")
|
||||||
local panel_view = require("coordinator.ui.layout.front_panel")
|
local panel_view = require("coordinator.ui.layout.front_panel")
|
||||||
local main_view = require("coordinator.ui.layout.main_view")
|
local main_view = require("coordinator.ui.layout.main_view")
|
||||||
local unit_view = require("coordinator.ui.layout.unit_view")
|
local unit_view = require("coordinator.ui.layout.unit_view")
|
||||||
@ -29,6 +30,7 @@ local engine = {
|
|||||||
ui = {
|
ui = {
|
||||||
front_panel = nil, ---@type graphics_element|nil
|
front_panel = nil, ---@type graphics_element|nil
|
||||||
main_display = nil, ---@type graphics_element|nil
|
main_display = nil, ---@type graphics_element|nil
|
||||||
|
flow_display = nil, ---@type graphics_element|nil
|
||||||
unit_displays = {}
|
unit_displays = {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,8 +62,9 @@ end
|
|||||||
|
|
||||||
-- init all displays in use by the renderer
|
-- init all displays in use by the renderer
|
||||||
function renderer.init_displays()
|
function renderer.init_displays()
|
||||||
-- init primary monitor
|
-- init primary and flow monitors
|
||||||
_init_display(engine.monitors.primary)
|
_init_display(engine.monitors.primary)
|
||||||
|
_init_display(engine.monitors.flow)
|
||||||
|
|
||||||
-- init unit displays
|
-- init unit displays
|
||||||
for _, monitor in ipairs(engine.monitors.unit_displays) do
|
for _, monitor in ipairs(engine.monitors.unit_displays) do
|
||||||
@ -169,6 +172,12 @@ function renderer.start_ui()
|
|||||||
main_view(engine.ui.main_display)
|
main_view(engine.ui.main_display)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- show flow view on flow monitor
|
||||||
|
if engine.monitors.flow ~= nil then
|
||||||
|
engine.ui.flow_display = DisplayBox{window=engine.monitors.flow,fg_bg=style.root}
|
||||||
|
flow_view(engine.ui.flow_display)
|
||||||
|
end
|
||||||
|
|
||||||
-- show unit views on unit displays
|
-- show unit views on unit displays
|
||||||
for idx, display in pairs(engine.monitors.unit_displays) do
|
for idx, display in pairs(engine.monitors.unit_displays) do
|
||||||
engine.ui.unit_displays[idx] = DisplayBox{window=display,fg_bg=style.root}
|
engine.ui.unit_displays[idx] = DisplayBox{window=display,fg_bg=style.root}
|
||||||
@ -192,6 +201,7 @@ function renderer.close_ui()
|
|||||||
|
|
||||||
-- delete element trees
|
-- delete element trees
|
||||||
if engine.ui.main_display ~= nil then engine.ui.main_display.delete() end
|
if engine.ui.main_display ~= nil then engine.ui.main_display.delete() end
|
||||||
|
if engine.ui.flow_display ~= nil then engine.ui.flow_display.delete() end
|
||||||
for _, display in pairs(engine.ui.unit_displays) do display.delete() end
|
for _, display in pairs(engine.ui.unit_displays) do display.delete() end
|
||||||
|
|
||||||
-- report ui as not ready
|
-- report ui as not ready
|
||||||
@ -199,6 +209,7 @@ function renderer.close_ui()
|
|||||||
|
|
||||||
-- clear root UI elements
|
-- clear root UI elements
|
||||||
engine.ui.main_display = nil
|
engine.ui.main_display = nil
|
||||||
|
engine.ui.flow_display = nil
|
||||||
engine.ui.unit_displays = {}
|
engine.ui.unit_displays = {}
|
||||||
|
|
||||||
-- clear unit monitors
|
-- clear unit monitors
|
||||||
@ -317,6 +328,8 @@ function renderer.handle_mouse(event)
|
|||||||
elseif engine.ui_ready then
|
elseif engine.ui_ready then
|
||||||
if event.monitor == engine.monitors.primary_name then
|
if event.monitor == engine.monitors.primary_name then
|
||||||
engine.ui.main_display.handle_mouse(event)
|
engine.ui.main_display.handle_mouse(event)
|
||||||
|
elseif event.monitor == engine.monitors.flow_name then
|
||||||
|
engine.ui.flow_display.handle_mouse(event)
|
||||||
else
|
else
|
||||||
for id, monitor in ipairs(engine.monitors.unit_name_map) do
|
for id, monitor in ipairs(engine.monitors.unit_name_map) do
|
||||||
if event.monitor == monitor then
|
if event.monitor == monitor then
|
||||||
|
@ -22,7 +22,7 @@ local sounder = require("coordinator.sounder")
|
|||||||
|
|
||||||
local apisessions = require("coordinator.session.apisessions")
|
local apisessions = require("coordinator.session.apisessions")
|
||||||
|
|
||||||
local COORDINATOR_VERSION = "v0.21.2"
|
local COORDINATOR_VERSION = "v1.0.0"
|
||||||
|
|
||||||
local println = util.println
|
local println = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
|
159
coordinator/ui/components/flow_overview.lua
Normal file
159
coordinator/ui/components/flow_overview.lua
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
--
|
||||||
|
-- Basic Unit Flow Overview
|
||||||
|
--
|
||||||
|
|
||||||
|
local util = require("scada-common.util")
|
||||||
|
|
||||||
|
local core = require("graphics.core")
|
||||||
|
|
||||||
|
local style = require("coordinator.ui.style")
|
||||||
|
|
||||||
|
local reactor_view = require("coordinator.ui.components.reactor")
|
||||||
|
local boiler_view = require("coordinator.ui.components.boiler")
|
||||||
|
local turbine_view = require("coordinator.ui.components.turbine")
|
||||||
|
|
||||||
|
local Div = require("graphics.elements.div")
|
||||||
|
local PipeNetwork = require("graphics.elements.pipenet")
|
||||||
|
local TextBox = require("graphics.elements.textbox")
|
||||||
|
|
||||||
|
local Rectangle = require("graphics.elements.rectangle")
|
||||||
|
|
||||||
|
local DataIndicator = require("graphics.elements.indicators.data")
|
||||||
|
local HorizontalBar = require("graphics.elements.indicators.hbar")
|
||||||
|
local StateIndicator = require("graphics.elements.indicators.state")
|
||||||
|
|
||||||
|
local IndicatorLight = require("graphics.elements.indicators.light")
|
||||||
|
local TriIndicatorLight = require("graphics.elements.indicators.trilight")
|
||||||
|
local VerticalBar = require("graphics.elements.indicators.vbar")
|
||||||
|
|
||||||
|
local cpair = core.cpair
|
||||||
|
local border = core.border
|
||||||
|
|
||||||
|
local TEXT_ALIGN = core.TEXT_ALIGN
|
||||||
|
|
||||||
|
local pipe = core.pipe
|
||||||
|
|
||||||
|
-- make a new unit overview window
|
||||||
|
---@param parent graphics_element parent
|
||||||
|
---@param x integer top left x
|
||||||
|
---@param y integer top left y
|
||||||
|
---@param unit ioctl_unit unit database entry
|
||||||
|
local function make(parent, x, y, unit)
|
||||||
|
local height = 16
|
||||||
|
|
||||||
|
local v_start = 1 + ((unit.unit_id - 1) * 4)
|
||||||
|
local v_names = {
|
||||||
|
util.sprintf("PV%02d-PU", v_start),
|
||||||
|
util.sprintf("PV%02d-PO", v_start + 1),
|
||||||
|
util.sprintf("PV%02d-PL", v_start + 2),
|
||||||
|
util.sprintf("PV%02d-AM", v_start + 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(parent.get_height() >= (y + height), "flow display not of sufficient vertical resolution (add an additional row of monitors) " .. y .. "," .. parent.get_height())
|
||||||
|
|
||||||
|
-- bounding box div
|
||||||
|
local root = Div{parent=parent,x=x,y=y,width=114,height=height}
|
||||||
|
|
||||||
|
local text_fg_bg = cpair(colors.black, colors.white)
|
||||||
|
local lu_col = cpair(colors.gray, colors.gray)
|
||||||
|
|
||||||
|
-------------
|
||||||
|
-- REACTOR --
|
||||||
|
-------------
|
||||||
|
|
||||||
|
local reactor = Rectangle{parent=root,x=1,y=1,border=border(1, colors.gray, true),width=19,height=5,fg_bg=cpair(colors.white,colors.gray)}
|
||||||
|
TextBox{parent=reactor,y=1,text="FISSION REACTOR",alignment=TEXT_ALIGN.CENTER,height=1}
|
||||||
|
TextBox{parent=reactor,y=3,text="UNIT #"..unit.unit_id,alignment=TEXT_ALIGN.CENTER,height=1}
|
||||||
|
TextBox{parent=root,x=19,y=2,text="\x1b \x80 \x1a",width=1,height=3,fg_bg=cpair(colors.lightGray,colors.gray)}
|
||||||
|
TextBox{parent=root,x=4,y=5,text="\x19",width=1,height=1,fg_bg=cpair(colors.lightGray,colors.gray)}
|
||||||
|
|
||||||
|
local rc_pipes = {}
|
||||||
|
|
||||||
|
table.insert(rc_pipes, pipe(0, 1, 19, 1, colors.lightBlue, true))
|
||||||
|
table.insert(rc_pipes, pipe(0, 3, 19, 3, colors.orange, true))
|
||||||
|
table.insert(rc_pipes, pipe(39, 1, 58, 1, colors.blue, true))
|
||||||
|
table.insert(rc_pipes, pipe(39, 3, 58, 3, colors.white, true))
|
||||||
|
|
||||||
|
table.insert(rc_pipes, pipe(78, 0, 83, 0, colors.white, true))
|
||||||
|
table.insert(rc_pipes, pipe(78, 2, 83, 2, colors.white, true))
|
||||||
|
table.insert(rc_pipes, pipe(78, 4, 83, 4, colors.white, true))
|
||||||
|
|
||||||
|
PipeNetwork{parent=root,x=20,y=1,pipes=rc_pipes,bg=colors.lightGray}
|
||||||
|
|
||||||
|
local hc_rate = DataIndicator{parent=root,x=22,y=3,lu_colors=lu_col,label="",unit="mB/t",format="%11.0f",value=287000000,commas=true,width=16,fg_bg=text_fg_bg}
|
||||||
|
local cc_rate = DataIndicator{parent=root,x=22,y=5,lu_colors=lu_col,label="",unit="mB/t",format="%11.0f",value=287000000,commas=true,width=16,fg_bg=text_fg_bg}
|
||||||
|
|
||||||
|
local boiler = Rectangle{parent=root,x=40,y=1,border=border(1, colors.gray, true),width=19,height=5,fg_bg=cpair(colors.white,colors.gray)}
|
||||||
|
TextBox{parent=boiler,y=1,text="THERMO-ELECTRIC",alignment=TEXT_ALIGN.CENTER,height=1}
|
||||||
|
TextBox{parent=boiler,y=3,text="BOILERS",alignment=TEXT_ALIGN.CENTER,height=1}
|
||||||
|
TextBox{parent=root,x=40,y=2,text="\x1b \x80 \x1a",width=1,height=3,fg_bg=cpair(colors.lightGray,colors.gray)}
|
||||||
|
TextBox{parent=root,x=58,y=2,text="\x1b \x80 \x1a",width=1,height=3,fg_bg=cpair(colors.lightGray,colors.gray)}
|
||||||
|
|
||||||
|
local wt_rate = DataIndicator{parent=root,x=61,y=3,lu_colors=lu_col,label="",unit="mB/t",format="%11.0f",value=287000000,commas=true,width=16,fg_bg=text_fg_bg}
|
||||||
|
local st_rate = DataIndicator{parent=root,x=61,y=5,lu_colors=lu_col,label="",unit="mB/t",format="%11.0f",value=287000000,commas=true,width=16,fg_bg=text_fg_bg}
|
||||||
|
|
||||||
|
local turbine = Rectangle{parent=root,x=79,y=1,border=border(1, colors.gray, true),width=19,height=5,fg_bg=cpair(colors.white,colors.gray)}
|
||||||
|
TextBox{parent=turbine,y=1,text="STEAM TURBINE",alignment=TEXT_ALIGN.CENTER,height=1}
|
||||||
|
TextBox{parent=turbine,y=3,text="GENERATORS",alignment=TEXT_ALIGN.CENTER,height=1}
|
||||||
|
TextBox{parent=root,x=79,y=2,text="\x1a \x80 \x1b",width=1,height=3,fg_bg=cpair(colors.lightGray,colors.gray)}
|
||||||
|
|
||||||
|
TextBox{parent=root,x=101,y=3,text="\x10\x11",fg_bg=cpair(colors.black,colors.lightGray),width=2,height=1}
|
||||||
|
TextBox{parent=root,x=103,y=3,text="\x7f",fg_bg=cpair(colors.white,colors.lightGray),width=1,height=1}
|
||||||
|
local conn = TriIndicatorLight{parent=root,x=106,y=1,label="PRV01",c1=colors.gray,c2=colors.yellow,c3=colors.red}
|
||||||
|
local conn = TriIndicatorLight{parent=root,x=106,y=3,label="PRV02",c1=colors.gray,c2=colors.yellow,c3=colors.red}
|
||||||
|
local conn = TriIndicatorLight{parent=root,x=106,y=5,label="PRV03",c1=colors.gray,c2=colors.yellow,c3=colors.red}
|
||||||
|
|
||||||
|
local waste = Div{parent=root,x=3,y=6}
|
||||||
|
|
||||||
|
local waste_pipes = {
|
||||||
|
pipe(0, 0, 16, 1, colors.brown, true),
|
||||||
|
pipe(12, 1, 16, 5, colors.brown, true),
|
||||||
|
pipe(18, 1, 44, 1, colors.brown, true),
|
||||||
|
pipe(18, 5, 23, 5, colors.brown, true),
|
||||||
|
pipe(52, 1, 80, 1, colors.green, true),
|
||||||
|
pipe(42, 4, 60, 4, colors.cyan, true),
|
||||||
|
pipe(56, 4, 60, 8, colors.cyan, true),
|
||||||
|
pipe(62, 4, 80, 4, colors.cyan, true),
|
||||||
|
pipe(62, 8, 110, 8, colors.cyan, true),
|
||||||
|
pipe(93, 1, 94, 3, colors.black, true, true),
|
||||||
|
pipe(93, 4, 109, 6, colors.black, true, true),
|
||||||
|
pipe(109, 6, 107, 6, colors.black, true, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
PipeNetwork{parent=waste,x=2,y=1,pipes=waste_pipes,bg=colors.lightGray}
|
||||||
|
|
||||||
|
local function _valve(vx, vy, n)
|
||||||
|
TextBox{parent=waste,x=vx,y=vy,text="\x10\x11",fg_bg=cpair(colors.black,colors.lightGray),width=2,height=1}
|
||||||
|
local conn = IndicatorLight{parent=waste,x=vx-3,y=vy+1,label=v_names[n],colors=cpair(colors.green,colors.gray)}
|
||||||
|
local state = IndicatorLight{parent=waste,x=vx-3,y=vy+2,label="STATE",colors=cpair(colors.white,colors.white)}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _machine(mx, my, name)
|
||||||
|
local l = string.len(name) + 2
|
||||||
|
TextBox{parent=waste,x=mx,y=my,text=util.strrep("\x8f",l),alignment=TEXT_ALIGN.CENTER,fg_bg=cpair(colors.lightGray,colors.gray),width=l,height=1}
|
||||||
|
TextBox{parent=waste,x=mx,y=my+1,text=name,alignment=TEXT_ALIGN.CENTER,fg_bg=cpair(colors.white,colors.gray),width=l,height=1}
|
||||||
|
end
|
||||||
|
|
||||||
|
local waste_rate = DataIndicator{parent=waste,x=1,y=3,lu_colors=lu_col,label="",unit="mB/t",format="%7.2f",value=1234.56,width=12,fg_bg=text_fg_bg}
|
||||||
|
local pu_rate = DataIndicator{parent=waste,x=70,y=3,lu_colors=lu_col,label="",unit="mB/t",format="%7.3f",value=123.456,width=12,fg_bg=text_fg_bg}
|
||||||
|
local po_rate = DataIndicator{parent=waste,x=45,y=6,lu_colors=lu_col,label="",unit="mB/t",format="%7.3f",value=123.456,width=12,fg_bg=text_fg_bg}
|
||||||
|
local popl_rate = DataIndicator{parent=waste,x=70,y=6,lu_colors=lu_col,label="",unit="mB/t",format="%7.3f",value=123.456,width=12,fg_bg=text_fg_bg}
|
||||||
|
local poam_rate = DataIndicator{parent=waste,x=70,y=10,lu_colors=lu_col,label="",unit="mB/t",format="%7.3f",value=123.456,width=12,fg_bg=text_fg_bg}
|
||||||
|
local spent_rate = DataIndicator{parent=waste,x=99,y=4,lu_colors=lu_col,label="",unit="mB/t",format="%7.3f",value=123.456,width=12,fg_bg=text_fg_bg}
|
||||||
|
|
||||||
|
_valve(18, 2, 1); _valve(18, 6, 2); _valve(62, 5, 3); _valve(62, 9, 4)
|
||||||
|
_machine(45, 1, "CENTRIFUGE \x1a"); _machine(83, 1, "PRC [Pu] \x1a"); _machine(83, 4, "PRC [Po] \x1a"); _machine(94, 6, "SPENT WASTE \x1b")
|
||||||
|
|
||||||
|
|
||||||
|
TextBox{parent=waste,x=25,y=3,text="SNAs [Po]",alignment=TEXT_ALIGN.CENTER,width=19,height=1,fg_bg=cpair(colors.white,colors.gray)}
|
||||||
|
local sna_po = Rectangle{parent=waste,x=25,y=4,border=border(1, colors.gray, true),width=19,height=7,thin=true,fg_bg=cpair(colors.black,colors.white)}
|
||||||
|
local sna_act = IndicatorLight{parent=sna_po,label="ACTIVE",colors=cpair(colors.green,colors.red)}
|
||||||
|
local sna_cnt = DataIndicator{parent=sna_po,x=12,y=1,lu_colors=lu_col,label="CNT",unit="",format="%2d",value=99,width=7,fg_bg=text_fg_bg}
|
||||||
|
local sna_pk = DataIndicator{parent=sna_po,y=3,lu_colors=lu_col,label="PEAK",unit="mB/t",format="%7.2f",value=1000,width=17,fg_bg=text_fg_bg}
|
||||||
|
local sna_max = DataIndicator{parent=sna_po,lu_colors=lu_col,label="MAX ",unit="mB/t",format="%7.2f",value=1000,width=17,fg_bg=text_fg_bg}
|
||||||
|
local sna_in = DataIndicator{parent=sna_po,lu_colors=lu_col,label="IN ",unit="mB/t",format="%7.2f",value=1000,width=17,fg_bg=text_fg_bg}
|
||||||
|
|
||||||
|
return root
|
||||||
|
end
|
||||||
|
|
||||||
|
return make
|
41
coordinator/ui/layout/flow_view.lua
Normal file
41
coordinator/ui/layout/flow_view.lua
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
--
|
||||||
|
-- Flow Monitor GUI
|
||||||
|
--
|
||||||
|
|
||||||
|
local util = require("scada-common.util")
|
||||||
|
|
||||||
|
local iocontrol = require("coordinator.iocontrol")
|
||||||
|
|
||||||
|
local style = require("coordinator.ui.style")
|
||||||
|
|
||||||
|
local flow_overview = require("coordinator.ui.components.flow_overview")
|
||||||
|
|
||||||
|
local core = require("graphics.core")
|
||||||
|
|
||||||
|
local TextBox = require("graphics.elements.textbox")
|
||||||
|
|
||||||
|
local DataIndicator = require("graphics.elements.indicators.data")
|
||||||
|
|
||||||
|
local TEXT_ALIGN = core.TEXT_ALIGN
|
||||||
|
|
||||||
|
local cpair = core.cpair
|
||||||
|
|
||||||
|
-- create new flow view
|
||||||
|
---@param main graphics_element main displaybox
|
||||||
|
local function init(main)
|
||||||
|
local facility = iocontrol.get_db().facility
|
||||||
|
local units = iocontrol.get_db().units
|
||||||
|
|
||||||
|
-- window header message
|
||||||
|
local header = TextBox{parent=main,y=1,text="Facility Coolant and Waste Flow Monitor",alignment=TEXT_ALIGN.CENTER,height=1,fg_bg=style.header}
|
||||||
|
-- max length example: "01:23:45 AM - Wednesday, September 28 2022"
|
||||||
|
local datetime = TextBox{parent=main,x=(header.get_width()-42),y=1,text="",alignment=TEXT_ALIGN.RIGHT,width=42,height=1,fg_bg=style.header}
|
||||||
|
|
||||||
|
datetime.register(facility.ps, "date_time", datetime.set_value)
|
||||||
|
|
||||||
|
for i = 1, 4 do
|
||||||
|
flow_overview(main, 25, 5 + ((i - 1) * 20), units[i])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return init
|
@ -7,7 +7,7 @@ local flasher = require("graphics.flasher")
|
|||||||
|
|
||||||
local core = {}
|
local core = {}
|
||||||
|
|
||||||
core.version = "1.0.2"
|
core.version = "1.0.3"
|
||||||
|
|
||||||
core.flasher = flasher
|
core.flasher = flasher
|
||||||
core.events = events
|
core.events = events
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
-- Pipe Graphics Element
|
-- Pipe Graphics Element
|
||||||
|
|
||||||
local util = require("scada-common.util")
|
local util = require("scada-common.util")
|
||||||
|
local log = require("scada-common.log")
|
||||||
|
|
||||||
local core = require("graphics.core")
|
local core = require("graphics.core")
|
||||||
local element = require("graphics.element")
|
local element = require("graphics.element")
|
||||||
@ -14,6 +15,12 @@ local element = require("graphics.element")
|
|||||||
---@field y? integer auto incremented if omitted
|
---@field y? integer auto incremented if omitted
|
||||||
---@field hidden? boolean true to hide on initial draw
|
---@field hidden? boolean true to hide on initial draw
|
||||||
|
|
||||||
|
---@class _pipe_map_entry
|
||||||
|
---@field atr boolean align top right (or bottom left for false)
|
||||||
|
---@field thin boolean thin pipe or not
|
||||||
|
---@field fg string foreground blit
|
||||||
|
---@field bg string background blit
|
||||||
|
|
||||||
-- new pipe network
|
-- new pipe network
|
||||||
---@param args pipenet_args
|
---@param args pipenet_args
|
||||||
---@return graphics_element element, element_id id
|
---@return graphics_element element, element_id id
|
||||||
@ -44,102 +51,266 @@ local function pipenet(args)
|
|||||||
-- create new graphics element base object
|
-- create new graphics element base object
|
||||||
local e = element.new(args)
|
local e = element.new(args)
|
||||||
|
|
||||||
-- draw all pipes
|
-- determine if there are any thin pipes involved
|
||||||
|
local any_thin = false
|
||||||
for p = 1, #args.pipes do
|
for p = 1, #args.pipes do
|
||||||
local pipe = args.pipes[p] ---@type pipe
|
any_thin = args.pipes[p].thin
|
||||||
|
if any_thin then break end
|
||||||
|
end
|
||||||
|
|
||||||
local x = 1 + pipe.x1
|
if not any_thin then
|
||||||
local y = 1 + pipe.y1
|
-- draw all pipes
|
||||||
|
for p = 1, #args.pipes do
|
||||||
|
local pipe = args.pipes[p] ---@type pipe
|
||||||
|
|
||||||
local x_step = util.trinary(pipe.x1 >= pipe.x2, -1, 1)
|
local x = 1 + pipe.x1
|
||||||
local y_step = util.trinary(pipe.y1 >= pipe.y2, -1, 1)
|
local y = 1 + pipe.y1
|
||||||
|
|
||||||
e.window.setCursorPos(x, y)
|
local x_step = util.trinary(pipe.x1 >= pipe.x2, -1, 1)
|
||||||
|
local y_step = util.trinary(pipe.y1 >= pipe.y2, -1, 1)
|
||||||
|
|
||||||
local c = core.cpair(pipe.color, e.fg_bg.bkg)
|
if pipe.thin then
|
||||||
|
x_step = util.trinary(pipe.x1 == pipe.x2, 0, x_step)
|
||||||
|
y_step = util.trinary(pipe.y1 == pipe.y2, 0, y_step)
|
||||||
|
end
|
||||||
|
|
||||||
if pipe.align_tr then
|
e.window.setCursorPos(x, y)
|
||||||
-- cross width then height
|
|
||||||
for i = 1, pipe.w do
|
local c = core.cpair(pipe.color, e.fg_bg.bkg)
|
||||||
if pipe.thin then
|
|
||||||
if i == pipe.w then
|
if pipe.align_tr then
|
||||||
-- corner
|
-- cross width then height
|
||||||
if y_step > 0 then
|
for i = 1, pipe.w do
|
||||||
e.window.blit("\x93", c.blit_bkg, c.blit_fgd)
|
if pipe.thin then
|
||||||
|
if i == pipe.w then
|
||||||
|
-- corner
|
||||||
|
if y_step > 0 then
|
||||||
|
e.window.blit("\x93", c.blit_bkg, c.blit_fgd)
|
||||||
|
else
|
||||||
|
e.window.blit("\x8e", c.blit_fgd, c.blit_bkg)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
e.window.blit("\x8e", c.blit_fgd, c.blit_bkg)
|
e.window.blit("\x8c", c.blit_fgd, c.blit_bkg)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
if i == pipe.w and y_step > 0 then
|
||||||
|
-- corner
|
||||||
|
e.window.blit(" ", c.blit_bkg, c.blit_fgd)
|
||||||
|
else
|
||||||
|
e.window.blit("\x8f", c.blit_fgd, c.blit_bkg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
x = x + x_step
|
||||||
|
e.window.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- back up one
|
||||||
|
x = x - x_step
|
||||||
|
|
||||||
|
for _ = 1, pipe.h - 1 do
|
||||||
|
y = y + y_step
|
||||||
|
e.window.setCursorPos(x, y)
|
||||||
|
|
||||||
|
if pipe.thin then
|
||||||
|
e.window.blit("\x95", c.blit_bkg, c.blit_fgd)
|
||||||
|
else
|
||||||
|
e.window.blit(" ", c.blit_bkg, c.blit_fgd)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- cross height then width
|
||||||
|
for i = 1, pipe.h do
|
||||||
|
if pipe.thin then
|
||||||
|
if i == pipe.h then
|
||||||
|
-- corner
|
||||||
|
if y_step < 0 then
|
||||||
|
e.window.blit("\x97", c.blit_bkg, c.blit_fgd)
|
||||||
|
elseif y_step > 0 then
|
||||||
|
e.window.blit("\x8d", c.blit_fgd, c.blit_bkg)
|
||||||
|
else
|
||||||
|
e.window.blit("\x8c", c.blit_fgd, c.blit_bkg)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
e.window.blit("\x95", c.blit_fgd, c.blit_bkg)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if i == pipe.h and y_step < 0 then
|
||||||
|
-- corner
|
||||||
|
e.window.blit("\x83", c.blit_bkg, c.blit_fgd)
|
||||||
|
else
|
||||||
|
e.window.blit(" ", c.blit_bkg, c.blit_fgd)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
y = y + y_step
|
||||||
|
e.window.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- back up one
|
||||||
|
y = y - y_step
|
||||||
|
|
||||||
|
for _ = 1, pipe.w - 1 do
|
||||||
|
x = x + x_step
|
||||||
|
e.window.setCursorPos(x, y)
|
||||||
|
|
||||||
|
if pipe.thin then
|
||||||
e.window.blit("\x8c", c.blit_fgd, c.blit_bkg)
|
e.window.blit("\x8c", c.blit_fgd, c.blit_bkg)
|
||||||
end
|
|
||||||
else
|
|
||||||
if i == pipe.w and y_step > 0 then
|
|
||||||
-- corner
|
|
||||||
e.window.blit(" ", c.blit_bkg, c.blit_fgd)
|
|
||||||
else
|
else
|
||||||
e.window.blit("\x8f", c.blit_fgd, c.blit_bkg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
x = x + x_step
|
|
||||||
e.window.setCursorPos(x, y)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- back up one
|
|
||||||
x = x - x_step
|
|
||||||
|
|
||||||
for _ = 1, pipe.h - 1 do
|
|
||||||
y = y + y_step
|
|
||||||
e.window.setCursorPos(x, y)
|
|
||||||
|
|
||||||
if pipe.thin then
|
|
||||||
e.window.blit("\x95", c.blit_bkg, c.blit_fgd)
|
|
||||||
else
|
|
||||||
e.window.blit(" ", c.blit_bkg, c.blit_fgd)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- cross height then width
|
|
||||||
for i = 1, pipe.h do
|
|
||||||
if pipe.thin then
|
|
||||||
if i == pipe.h then
|
|
||||||
-- corner
|
|
||||||
if y_step < 0 then
|
|
||||||
e.window.blit("\x97", c.blit_bkg, c.blit_fgd)
|
|
||||||
else
|
|
||||||
e.window.blit("\x8d", c.blit_fgd, c.blit_bkg)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
e.window.blit("\x95", c.blit_fgd, c.blit_bkg)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if i == pipe.h and y_step < 0 then
|
|
||||||
-- corner
|
|
||||||
e.window.blit("\x83", c.blit_bkg, c.blit_fgd)
|
e.window.blit("\x83", c.blit_bkg, c.blit_fgd)
|
||||||
else
|
|
||||||
e.window.blit(" ", c.blit_bkg, c.blit_fgd)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
y = y + y_step
|
|
||||||
e.window.setCursorPos(x, y)
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- build map if using thin pipes, easist way to check adjacent blocks (cannot 'cheat' like with standard width)
|
||||||
|
local map = {}
|
||||||
|
|
||||||
-- back up one
|
-- allocate map
|
||||||
y = y - y_step
|
for x = 1, args.width do
|
||||||
|
table.insert(map, {})
|
||||||
|
for _ = 1, args.height do table.insert(map[x], false) end
|
||||||
|
end
|
||||||
|
|
||||||
for _ = 1, pipe.w - 1 do
|
-- build map
|
||||||
x = x + x_step
|
for p = 1, #args.pipes do
|
||||||
e.window.setCursorPos(x, y)
|
local pipe = args.pipes[p] ---@type pipe
|
||||||
|
|
||||||
if pipe.thin then
|
local x = 1 + pipe.x1
|
||||||
e.window.blit("\x8c", c.blit_fgd, c.blit_bkg)
|
local y = 1 + pipe.y1
|
||||||
else
|
|
||||||
e.window.blit("\x83", c.blit_bkg, c.blit_fgd)
|
local x_step = util.trinary(pipe.x1 >= pipe.x2, -1, 1)
|
||||||
|
local y_step = util.trinary(pipe.y1 >= pipe.y2, -1, 1)
|
||||||
|
|
||||||
|
local entry = { atr = pipe.align_tr, thin = pipe.thin, fg = colors.toBlit(pipe.color), bg = e.fg_bg.blit_bkg }
|
||||||
|
|
||||||
|
if pipe.align_tr then
|
||||||
|
-- cross width then height
|
||||||
|
for _ = 1, pipe.w do
|
||||||
|
map[x][y] = entry
|
||||||
|
x = x + x_step
|
||||||
|
end
|
||||||
|
|
||||||
|
x = x - x_step -- back up one
|
||||||
|
|
||||||
|
for _ = 1, pipe.h do
|
||||||
|
map[x][y] = entry
|
||||||
|
y = y + y_step
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- cross height then width
|
||||||
|
for _ = 1, pipe.h do
|
||||||
|
map[x][y] = entry
|
||||||
|
y = y + y_step
|
||||||
|
end
|
||||||
|
|
||||||
|
y = y - y_step -- back up one
|
||||||
|
|
||||||
|
for _ = 1, pipe.w do
|
||||||
|
map[x][y] = entry
|
||||||
|
x = x + x_step
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- for x = 1, args.width do
|
||||||
|
-- for y = 1, args.height do
|
||||||
|
-- local entry = map[x][y] ---@type _pipe_map_entry|false
|
||||||
|
-- if entry == false then
|
||||||
|
-- e.window.setCursorPos(x, y)
|
||||||
|
-- e.window.blit("x", "f", "e")
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- render
|
||||||
|
for x = 1, args.width do
|
||||||
|
for y = 1, args.height do
|
||||||
|
local entry = map[x][y] ---@type _pipe_map_entry|false
|
||||||
|
local char = ""
|
||||||
|
local invert = false
|
||||||
|
|
||||||
|
if entry ~= false then
|
||||||
|
local function check(cx, cy)
|
||||||
|
return (map[cx] ~= nil) and (map[cx][cy] ~= nil) and (map[cx][cy] ~= false) and (map[cx][cy].fg == entry.fg)
|
||||||
|
end
|
||||||
|
|
||||||
|
if entry.thin then
|
||||||
|
if check(x - 1, y) then -- if left
|
||||||
|
if check(x, y - 1) then -- if above
|
||||||
|
if check(x + 1, y) then -- if right
|
||||||
|
if check(x, y + 1) then -- if below
|
||||||
|
char = util.trinary(entry.atr, "\x91", "\x9d")
|
||||||
|
invert = entry.atr
|
||||||
|
else -- not below
|
||||||
|
char = util.trinary(entry.atr, "\x8e", "\x8d")
|
||||||
|
end
|
||||||
|
else -- not right
|
||||||
|
if check(x, y + 1) then -- if below
|
||||||
|
char = util.trinary(entry.atr, "\x91", "\x95")
|
||||||
|
invert = entry.atr
|
||||||
|
else -- not below
|
||||||
|
char = util.trinary(entry.atr, "\x8e", "\x85")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif check(x, y + 1) then-- not above, if below
|
||||||
|
if check(x + 1, y) then -- if right
|
||||||
|
char = util.trinary(entry.atr, "\x93", "\x9c")
|
||||||
|
invert = entry.atr
|
||||||
|
else -- not right
|
||||||
|
char = util.trinary(entry.atr, "\x93", "\x94")
|
||||||
|
invert = entry.atr
|
||||||
|
end
|
||||||
|
else -- not above, not below
|
||||||
|
char = "\x8c"
|
||||||
|
end
|
||||||
|
elseif check(x + 1, y) then -- not left, if right
|
||||||
|
if check(x, y - 1) then -- if above
|
||||||
|
if check(x, y + 1) then -- if below
|
||||||
|
char = util.trinary(entry.atr, "\x95", "\x9d")
|
||||||
|
invert = entry.atr
|
||||||
|
else -- not below
|
||||||
|
char = util.trinary(entry.atr, "\x8a", "\x8d")
|
||||||
|
end
|
||||||
|
else -- not above
|
||||||
|
if check(x, y + 1) then -- if below
|
||||||
|
char = util.trinary(entry.atr, "\x97", "\x9c")
|
||||||
|
invert = entry.atr
|
||||||
|
else -- not below
|
||||||
|
char = "\x8c"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else -- not left, not right
|
||||||
|
char = "\x95"
|
||||||
|
invert = entry.atr
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if check(x, y - 1) then -- above
|
||||||
|
-- not below and (if left or right)
|
||||||
|
if (not check(x, y + 1)) and (check(x - 1, y) or check(x + 1, y)) then
|
||||||
|
char = util.trinary(entry.atr, "\x8f", "\x83")
|
||||||
|
invert = not entry.atr
|
||||||
|
else -- not above w/ sides only
|
||||||
|
char = " "
|
||||||
|
invert = true
|
||||||
|
end
|
||||||
|
elseif check(x, y + 1) then -- not above, if below
|
||||||
|
char = util.trinary(entry.atr, "\x8f", "\x83")
|
||||||
|
invert = not entry.atr
|
||||||
|
else -- not above, not below
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
e.window.setCursorPos(x, y)
|
||||||
|
|
||||||
|
if invert then
|
||||||
|
e.window.blit(char, entry.bg, entry.fg)
|
||||||
|
else
|
||||||
|
e.window.blit(char, entry.fg, entry.bg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return e.complete()
|
return e.complete()
|
||||||
|
Loading…
Reference in New Issue
Block a user