I’m bringing up the thread again since I’ve been asked to share the widget code. First thanks again @crnjan for providing the solution swiftly, and @tonicoveiro for spurring me to properly fix the code and make it somewhat presentable. I tried to introduce as many customisable props as possible, but also to avoid annoyances while setting it up.
Energy balance widget code
uid: energy_balance_widget
tags:
- cards
- energy
props:
parameters:
- name: itemProd # Required items
context: item
label: Power generation
required: true
type: TEXT
groupName: itemsGroup
- name: itemLoad
context: item
label: Power load
required: true
type: TEXT
groupName: itemsGroup
- name: itemToGrid # Optional items for graph
context: item
label: Yielded power
type: TEXT
groupName: itemsOptGroup
- name: itemFromGrid
context: item
label: Withdrawn power
type: TEXT
groupName: itemsOptGroup
- name: iconProd # Icons override
label: Sun icon override of the power production. Use only f7 styled icons from https://framework7.io/icons/
type: TEXT
groupName: labelGroup
- name: textCardTitle # Labels to use in the list items
label: Card title. Leave empty to conceal it
type: TEXT
groupName: labelGroup
- name: textProd
label: Power generation (std "Photovoltaic")
type: TEXT
groupName: labelGroup
- name: textToGrid
label: Power yielded (std "Yielded")
type: TEXT
groupName: labelGroup
- name: textFromGrid
label: Power withdrawn (std "Withdrawn")
type: TEXT
groupName: labelGroup
- name: textLoad
label: Power load (std "House load")
type: TEXT
groupName: labelGroup
- name: textGraph
label: Accordion of the graph (std "Go to graph")
type: TEXT
groupName: labelGroup
description: Leave empty for standard English labels. These will also be displayed in the graph
- name: colorProd # Colours override
label: Power generated (std yellow)
type: TEXT
groupName: colorGroup
- name: colorYield
label: Power yielded (std green)
type: TEXT
groupName: colorGroup
- name: colorWithdraw
label: Power withdrawn (std blue)
type: TEXT
groupName: colorGroup
description: Insert here the colour of the list items (eg. "rgba(43,128,240,.9)", "yellow", "purple"). The colouring will affect also graph lines. Leave empty for preset colours.
parameterGroups:
- name: itemsGroup
label: Items (Required)
- name: itemsOptGroup
label: Items (Required only for the graph)
- name: labelGroup
label: Labels displayed
- name: colorGroup
label: Colour
timestamp: Sep 21, 2022, 9:52:48 AM
component: f7-card
config:
style: # This widget is thought for a smartphone, I haven't checked if it looks crap on different screen sizes. If it does, tweak these options
border-radius: var(--f7-card-expandable-border-radius)
box-shadow: var(--f7-card-expandable-box-shadow)
margin-left: 5px
margin-right: 5px
padding: 0px
--f7-card-header-font-weight: 800
--f7-card-header-padding-vertical: 0px
title: '=(props.textCardTitle) ? props.textCardTitle : "Energy"'
slots:
content:
- component: f7-list # Item list
slots:
default:
- component: f7-list-item # Power production item
slots:
default:
- component: f7-icon
config:
f7: '=(props.iconProd) ? props.iconProd : "sun_max_fill"'
size: 25px
style:
left: 0px
color: '=(props.colorProd) ? props.colorProd : "rgba(248,195,10,1)"'
- component: Label
config:
style:
left: 40px
position: absolute
text: '=(props.textProd) ? props.textProd : "Photovoltaic"'
- component: Label
config:
style:
position: absolute
right: 15px
text: '=(props.itemProd) ? (Math.round(Number.parseFloat(items[props.itemProd].state)) + " W") : "N/d"'
- component: f7-list-item # Power available item (grid)
slots:
default:
- component: f7-icon
config:
f7: bolt_fill
size: 25px
style:
left: 0px
color: '=(props.colorYield) ? props.colorYield : "rgba(66,184,81,1)"'
- component: Label
config:
style:
left: 40px
position: absolute
text: '=(props.textToGrid) ? props.textToGrid : "Yielded"'
- component: Label
config:
style:
position: absolute
right: 15px
text: '=(props.itemProd && props.itemLoad ? ((items[props.itemProd].state > items[props.itemLoad].state) ? Math.round(Number.parseFloat(items[props.itemProd].state)-Number.parseFloat(items[props.itemLoad].state)) : 0) + " W" : "N/d")'
- component: f7-list-item # Power withdrawn item (grid)
slots:
default:
- component: f7-icon
config:
f7: bolt_fill
size: 25px
style:
left: 0px
color: '=(props.colorWithdraw) ? props.colorWithdraw : "rgba(43,128,240,.9)"'
- component: Label
config:
style:
left: 40px
position: absolute
text: '=(props.textFromGrid) ? props.textFromGrid : "Withdrawn"'
- component: Label
config:
style:
position: absolute
right: 15px
text: '=(props.itemProd && props.itemLoad ? ((items[props.itemProd].state < items[props.itemLoad].state) ? Math.abs(Math.round(Number.parseFloat(items[props.itemLoad].state)-Number.parseFloat(items[props.itemProd].state))) : 0) + " W" : "N/d")'
- component: f7-list-item # Power load item
slots:
default:
- component: f7-icon
config:
f7: house_fill
size: 25px
style:
left: 0px
- component: Label
config:
style:
left: 40px
position: absolute
text: '=(props.textLoad) ? props.textLoad : "House load"'
- component: Label
config:
style:
position: absolute
right: 15px
text: '=(props.itemLoad) ? (Math.round(Number.parseFloat(items[props.itemLoad].state)) + " W") : "N/d"'
- component: f7-list-item # Summary graph item
config:
accordionItem: true
slots:
content:
- component: f7-icon
config:
color: gray
f7: graph_circle_fill
size: 25px
style:
left: 0px
- component: Label
config:
style:
left: 40px
position: absolute
text: '=(props.textGraph) ? props.textGraph : "Go to graph"'
default:
- component: f7-accordion-content
slots:
default:
- component: oh-chart
config:
period: 4h # Change here to display a longer/shorter time series
periodVisible: false # Change here if you want to browse time periods
slots:
grid:
- component: oh-chart-grid
config:
bottom: 5
left: 5
right: 5
top: 5
legend:
- component: oh-chart-legend
config:
bottom: 0
type: scroll
series:
- component: oh-time-series
config:
areaStyle:
opacity: 0.25
color: '=(props.colorProd) ? props.colorProd : "rgba(248,195,10,1)"'
item: '=props.itemProd'
name: '=(props.textProd) ? props.textProd : "Photovoltaic"'
type: line
- component: oh-time-series
config:
areaStyle: {}
color: '=(props.colorYield) ? props.colorYield : "rgba(66,184,81,1)"'
item: '=props.itemToGrid'
name: '=(props.textToGrid) ? props.textToGrid : "Yielded"'
type: line
- component: oh-time-series
config:
areaStyle: {}
color: '=(props.colorWithdraw) ? props.colorWithdraw : "rgba(43,128,240,.9)"'
item: '=props.itemFromGrid'
name: '=(props.textFromGrid) ? props.textFromGrid : "Withdrawn"'
type: line
tooltip:
- component: oh-chart-tooltip
config:
confine: true
show: true
smartFormatter: true
xAxis:
- component: oh-time-axis
config:
show: false
yAxis:
- component: oh-value-axis
config:
show: false
Let me do a bit of explaining. The widget is fully functional with two items which measure,
- the power produced by your power source,
- the house load.
To access the graph functionality you will need persistence, and unfortunately that means two additional items; one that tracks the power yielded to the grid, and one the power withdrawn. The good news is that you can make a rule that calculates them using the first two items I mentioned before quite simply and then store them in your persistence. This is the main limit.
P.S. For clarity I’ve added few comments in the code, don’t let them vanish as soon as you refresh the openHAB widget editor!
Eventually I ended up creating the animated widget below which is a more minimal in-between with the one in this post that gave me inspiration, but this one is far from complete yet!