I have taken the SMA Widget " Animated Energy Widget" from Sebastian as basis for this Fronius (Gen24) widget that (tries to) replicate solarweb. It is not animated (yet) and the code quality/efficiency is basic, but after some weeks of testing, it seems to be doing what it should.
Main features:
- Shows PV production and splits consumption into “consumed by house” & “consumed by Ohmpilot”
- Shows water temperature
- Shows power from/to grid
- Shows battery state of charge and whether battery is charging or discarging
uid: energy_overview_widget_Fronius_2
tags: []
props:
parameters:
- context: item
label: Netzeinspeisung
name: netzeinspeisung
required: true
type: TEXT
- context: item
label: Netzbezug
name: netzbezug
required: true
type: TEXT
- context: item
label: Gesamtverbrauch
name: gesamtverbrauch
required: true
type: TEXT
- context: item
label: PV Leistung
name: pv_leistung
required: true
type: TEXT
- context: item
label: Batterieleistung
name: batterieleistung
required: true
type: TEXT
- context: item
label: Batterie Ladezustand
name: batterylevel
required: true
type: TEXT
- context: item
label: Verbrauch Ohmpilot
name: consumptionOhmpilot
required: true
type: TEXT
- context: item
label: Temperatur Ohmpilot
name: temperatureOhmpilot
required: true
type: TEXT
- context: item
label: Self Consumption
name: selfConsumption
required: true
type: TEXT
- context: item
label: Current Relative Autonomy
name: relativeAutonomy
required: true
type: TEXT
- context: item
label: AC Voltage
name: acVoltage
required: true
type: TEXT
parameterGroups: []
timestamp: Apr 24, 2024, 7:11:48 AM
component: f7-card
config:
class:
- display-flex
- flex-direction-column
- align-items-center
style:
height: 383px
title: Energy Overview .......................................................................
slots:
content:
- component: f7-block
config:
style:
--f7-theme-color: var(--f7-text-color)
display: flex
justify-content: space-between
padding: 0
slots:
default:
- component: f7-col
config:
style:
align-items: center
display: flex
flex-direction: row
slots:
default:
- component: f7-block
config:
style:
align-items: center
display: flex
flex-direction: column
height: 110px
justify-content: center
margin-top: 20px
width: 110px
slots:
default:
- component: f7-block
config:
style:
align-items: center
border: 2px solid gray
border-radius: 50px
display: flex
flex-direction: column
height: 100px
justify-content: top
margin-right: 70px
margin-top: 160px
padding-top: 100px
width: 102px
- component: oh-icon
config:
height: 70px
icon: fronius_grid
style:
margin-right: 70px
margin-top: -80px
text-align: center
width: 45px
- component: Label
config:
style:
color: gray
font-size: 15px
margin-left: -60px
margin-top: 0px
text-align: center
width: 100px
text: = Number.parseInt(items[props.netzeinspeisung].state.toString().replace('-',' ')) + ' W'
textNew: = Number.parseInt(items[props.netzeinspeisung].state) + ' W'
textOld: =items[props.netzeinspeisung].state
visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0]) < 0) ? true : false'
- component: Label
config:
style:
color: orange
font-size: 15px
margin-left: -60px
margin-top: 0px
text-align: center
width: 100px
text: = Number.parseInt(items[props.netzeinspeisung].state.toString().replace('-',' ')) + ' W'
textNew: = Number.parseInt(items[props.netzeinspeisung].state) + ' W'
textddd: =items[props.netzeinspeisung].state
visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0]) > 0) ? true : false'
- component: Label
config:
style:
color: "#6cbe58"
font-size: 15px
margin-left: -60px
margin-top: 0px
text-align: center
width: 100px
text: =items[props.netzeinspeisung].state
textNew: = Number.parseInt(items[props.netzeinspeisung].state) + ' W'
visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0]) == 0) ? true : false'
- component: Label
config:
style:
color: gray
font-size: 9px
font-weight: bold
margin-right: 70px
margin-top: -5px
text-align: center
width: 100px
text: = 'to grid'
visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0]) < 0) ? true : false'
- component: Label
config:
style:
color: orange
font-size: 9px
font-weight: bold
margin-right: 70px
margin-top: -5px
text-align: center
width: 100px
text: = 'from grid'
visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0]) > 0) ? true : false'
- component: Label
config:
style:
color: "#6cbe58"
font-size: 9px
font-weight: bold
margin-right: 70px
margin-top: -5px
text-align: center
width: 100px
text: = '----'
visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0]) == 0) ? true : false'
- component: f7-row
config:
preserveAspectRatio: xMidYMid slice
style:
height: auto
tag: svg
viewBox: 0 0 100 100
xmlns: http://www.w3.org/2000/svg
slots:
default:
- component: f7-row
config:
d: M53,0 v15 c0,40 10,35 30,35 h20
fill: none
id: path1
stroke: orange
stroke-width: 1
tag: path
vector-effect: non-scaling-stroke
- component: f7-row
config:
fill: orange
r: 1
style:
stroke-width: 4
tag: circle
vector-effect: non-scaling-stroke
slots:
default:
- component: f7-row
config:
calcMode: linear
dur: 5s
repeatCount: indefinite
tag: animateMotion
slots:
default:
- component: f7-row
config:
tag: mpath
xlink:href: "#path1"
- component: f7-col
config:
style:
align-items: center
display: flex
flex-direction: column
flex-grow: 1
slots:
default:
- component: f7-block
config:
style:
align-items: center
display: flex
flex-direction: column
height: 110px
justify-content: center
margin-top: 0
width: 110px
slots:
default:
- component: f7-block
config:
style:
align-items: center
border: 2px solid orange
border-radius: 50px
borderOld: 2px solid teal
display: flex
flex-direction: column
height: 100px
justify-content: top
margin-right: 320px
margin-top: -50px
padding-top: 100px
width: 102px
- component: oh-icon
config:
height: 50px
heightNew: '=(Number.parseInt(items[props.pv_leistung].state.split(" ")[0]) > 100 && Number.parseFloat(items[props.pv_leistung].state.split(" ")[0]) < 1000) ? "50px" : "100px"'
icon: fronius_pv2
style:
margin-right: 320px
margin-top: -80px
text-align: center
width: 100px
- component: Label
config:
style:
font-size: 15px
margin-right: 320px
margin-top: -10px
text-align: center
width: 100px
text: = Number.parseInt(items[props.pv_leistung].state) + ' W'
textOld: =items[props.pv_leistung].displayState
- component: Label
config:
style:
color: gray
font-size: 9px
font-weight: bold
margin-right: 320px
margin-top: -5px
text-align: center
width: 100px
text: = 'Power'
visible: '=(Number.parseFloat(items[props.pv_leistung].state.split(" ")[0]) > 0) ? true : false'
- component: Label
config:
style:
color: orange
font-size: 9px
font-weight: bold
margin-right: 320px
margin-top: -5px
text-align: center
width: 100px
text: = 'No power'
visible: '=(Number.parseFloat(items[props.pv_leistung].state.split(" ")[0]) <= 0) ? true : false'
- component: f7-block
config:
style:
align-items: center
border: 2px solid teal
border-radius: 50px
display: flex
flex-direction: column
height: 100px
justify-content: top
margin-right: 40px
margin-top: -20px
padding-top: 0px
width: 102px
slots:
default:
- component: oh-icon
config:
height: 50px
icon: fronius_inverter
style:
margin-right: 0px
margin-top: 15px
text-align: center
width: 100px
- component: Label
config:
style:
font-size: 11px
margin-top: -3px
text-align: center
width: 100px
text: =items[props.relativeAutonomy].displayState
- component: Label
config:
style:
font-size: 9px
margin-top: -3px
text-align: center
width: 100px
text: =items[props.acVoltage].displayState
- component: f7-row
config:
preserveAspectRatio: xMidYMid slice
style:
height: auto
width: auto
tag: svg
viewBox: 0 0 100 100
xmlns: http://www.w3.org/2000/svg
slots:
default:
- component: f7-row
config:
d: M60 -5 v10 c0 30 10 35 30 35 h20
fill: none
id: path1
stroke: rgba(100, 150, 200, 0.8)
stroke-width: 2
tag: path
vector-effect: non-scaling-stroke
visible: '=(Number.parseFloat(items[props.batterieleistung].state.split(" ")[0]) < 0) ? true : false'
- component: f7-row
config:
fill: rgba(100, 150, 200, 0.8)
r: 6
style:
stroke-width: 4
tag: circle
vector-effect: non-scaling-stroke
visible: '=(Number.parseFloat(items[props.batterieleistung].state.split(" ")[0]) < 0) ? true : false'
slots:
default:
- component: f7-row
config:
calcMode: linear
dur: 4s
repeatCount: indefinite
tag: animateMotion
slots:
default:
- component: f7-row
config:
tag: mpath
xlink:href: "#path1"
- component: f7-row
config:
d: M40 -5 v10 c0 40 -10 35 -30 35 h-20
fill: none
id: path2
stroke: rgba(100, 150, 200, 0.8)
stroke-width: 2
tag: path
vector-effect: non-scaling-stroke
visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0]) > 0 && Number.parseFloat(items[props.netzbezug].state.split(" ")[0]) == 0) ? true : false'
- component: f7-row
config:
fill: rgba(100, 150, 200, 0.8)
r: 6
strokeWidth: 10
tag: circle
vectorEffect: non-scaling-stroke
visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0]) > 0 && Number.parseFloat(items[props.netzbezug].state.split(" ")[0]) == 0) ? true : false'
slots:
default:
- component: f7-row
config:
calcMode: linear
dur: 4s
repeatCount: indefinite
tag: animateMotion
slots:
default:
- component: f7-row
config:
tag: mpath
xlink:href: "#path2"
- component: f7-row
config:
d: M50, 0 v100
fill: none
id: path3
stroke: rgba(100, 150, 200, 0.8)
stroke-width: 1
tag: path
vector-effect: non-scaling-stroke
visible: =items[props.pv_leistung].displayState
- component: f7-row
config:
fill: rgba(100, 150, 200, 0.8)
r: 6
strokeWidth: 10
tag: circle
vectorEffect: non-scaling-stroke
visible: '=(Number.parseFloat(items[props.pv_leistung].state.split(" ")[0]) - (Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0]) + Math.abs(Number.parseFloat(items[props.batterieleistung].state.split(" ")[0]))) > 0) ? true : false'
slots:
default:
- component: f7-row
config:
calcMode: linear
dur: 4s
repeatCount: indefinite
tag: animateMotion
slots:
default:
- component: f7-row
config:
tag: mpath
xlink:href: "#path3"
- component: f7-row
config:
d: M 105 50 l -10 0 c -40 0 -35 10 -35 50 l 0 20
fill: none
id: path5
stroke: rgba(100, 150, 200, 0.8)
stroke-width: 2
tag: path
vector-effect: non-scaling-stroke
visible: '=(Number.parseFloat(items[props.batterieleistung].state.split(" ")[0]) > 0) ? true : false'
- component: f7-row
config:
fill: rgba(100, 150, 200, 0.8)
r: 6
strokeWidth: 10
tag: circle
vectorEffect: non-scaling-stroke
visible: '=(Number.parseFloat(items[props.batterieleistung].state.split(" ")[0]) > 0) ? true : false'
slots:
default:
- component: f7-row
config:
calcMode: linear
dur: 4s
repeatCount: indefinite
tag: animateMotion
slots:
default:
- component: f7-row
config:
tag: mpath
xlink:href: "#path5"
- component: f7-block
config:
style:
align-items: center
border: 2px solid teal
border-radius: 50px
display: flex
flex-direction: column
height: 100px
justify-content: top
margin-right: -240px
margin-top: -205px
padding-top: 0px
width: 102px
slots:
default:
- component: oh-icon
config:
height: 50px
icon: fronius_consumption2
iconOLD: fronius_consumption
style:
margin-right: 0px
margin-top: 20px
text-align: center
width: 100px
- component: Label
config:
style:
font-size: 15px
margin-top: -10px
text-align: center
width: 100px
text: = Number.parseInt(items[props.gesamtverbrauch].state.toString().replace('-',' ')) - Number.parseInt(items[props.consumptionOhmpilot].state) + ' W'
textOld: =items[props.gesamtverbrauch].displayState
textOld2: = Number.parseInt(items[props.gesamtverbrauch].state) + ' W'
textOld3: = Number.parseInt(items[props.gesamtverbrauch].state.toString().replace('-',' ')) + ' W'
- component: oh-icon
config:
height: 30px
icon: ohmpilot_temperature
style:
margin-right: -150px
margin-top: -100px
text-align: center
width: 100px
- component: Label
config:
icon: ohmpilot_temperature
style:
font-size: 14px
margin-right: -225px
margin-top: -22px
text-align: center
width: 100px
text: =Number.parseInt(items[props.temperatureOhmpilot].state) + ' °C'
textOld: =Number.parseInt(items[props.temperatureOhmpilot].state) + (Number.parseInt('273')) + ' °C'
- component: Label
config:
style:
font-size: 14px
margin-right: -210px
margin-top: 0px
text-align: center
width: 100px
text: = Number.parseInt(items[props.consumptionOhmpilot].state) + ' W'
textOld: =items[props.consumptionOhmpilot].displayState
- component: f7-col
config:
style:
align-items: center
display: flex
flex-direction: row
slots:
default:
- component: f7-block
config:
style:
align-items: center
border: 2px solid green
border-radius: 50px
display: flex
flex-direction: column
height: 100px
justify-content: top
margin-right: 50px
margin-top: 190px
padding-top: 0px
width: 102px
slots:
default:
- component: oh-icon
config:
height: 50px
icon: fronius_battery_0
style:
margin-right: 0px
margin-top: 15px
text-align: center
width: 50px
text: =items[props.batterylevel].displayState
visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) >= 0.01 && Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) < 0.25) ? true : false'
- component: oh-icon
config:
height: 50px
icon: fronius_battery_charging_25
style:
margin-right: 0px
margin-top: 15px
text-align: center
width: 50px
text: =items[props.batterylevel].displayState
visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) >= 0.25 && Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) < 0.50) ? true : false'
- component: oh-icon
config:
height: 50px
icon: fronius_battery_charging_50
style:
margin-right: 0px
margin-top: 15px
text-align: center
width: 50px
text: =items[props.batterylevel].displayState
visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) >= 0.50 && Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) < 0.75) ? true : false'
- component: oh-icon
config:
height: 50px
icon: fronius_battery_charging_75
style:
margin-right: 0px
margin-top: 15px
text-align: center
width: 50px
text: =items[props.batterylevel].displayState
visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) >= 0.75 && Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) < 0.90) ? true : false'
- component: oh-icon
config:
height: 50px
icon: fronius_battery_charging_100
style:
margin-right: 0px
margin-top: 15px
text-align: center
width: 50px
text: =items[props.batterylevel].displayState
visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) >= 0.90) ? true : false'
- component: Label
config:
style:
color: '=(Number.parseFloat(items[props.batterieleistung].state.split(" ")[0]) > 0) ? "orange" : "#6cbe58"'
font-size: 15px
margin-top: -5px
text-align: center
white-space: nowrap
width: 100px
text: = Number.parseInt(items[props.batterieleistung].state.toString().replace('-',' ')) + ' W'
textNew: = Number.parseInt(items[props.batterieleistung].state) + ' W'
textOld: =items[props.batterieleistung].displayState
- component: Label
config:
style:
color: "#6cbe58"
font-size: 9px
font-weight: bold
margin-right: 0px
margin-top: -5px
text-align: center
width: 100px
text: = 'charging'
visible: '=(Number.parseFloat(items[props.batterieleistung].state.split(" ")[0]) < 0) ? true : false'
- component: Label
config:
style:
color: orange
font-size: 9px
font-weight: bold
margin-right: 0px
margin-top: -5px
text-align: center
width: 100px
text: = 'depleting'
visible: '=(Number.parseFloat(items[props.batterieleistung].state.split(" ")[0]) > 0) ? true : false'
- component: Label
config:
style:
color: gray
font-size: 11px
font-weight: bold
margin-right: 0px
margin-top: -5px
text-align: center
width: 100px
text: = '----'
visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0]) == 0) ? true : false'
- component: oh-icon
config:
height: 30px
icon: fronius_battery
style:
margin-right: -150px
margin-top: -100px
text-align: center
width: 0px
- component: Label
config:
style:
color: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) < 0.30) ? "orange" : "#6cbe58"'
font-size: 12px
margin-right: -65px
margin-top: 15px
text-align: center
width: 100px
text: =Number.parseInt(items[props.batterylevel].displayState) + '%'
textNew: =items[props.batterylevel].displayState
visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) > 0.10) ? true : false'
- component: Label
config:
component: Label
style:
color: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) <= 0.10) ? "red" : "orange"'
font-size: 12px
margin-right: -68px
margin-top: 15px
text-align: center
width: 100px
text: =Number.parseInt(items[props.batterylevel].displayState) + '%'
textNew: =items[props.batterylevel].displayState
visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) <= 0.10) ? true : false'
Here are the icons, add them to your openhab folder under conf/icons/classic :