Fronius Gen24 Energy Widget

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 :
fronius_battery_0
fronius_battery_75
fronius_battery_100_orange
fronius_battery_100
fronius_battery_charging_25
fronius_battery_charging_50
fronius_battery_charging_75
fronius_battery_charging_100_orange
fronius_battery_charging_100
fronius_battery
fronius_pv2
inverter_gen24
ohmpilot_temperature
fronius_consumption2
fronius_grid

1 Like