Widget for Energy Monitoring

I have created a new widget for energy monitoring for my house. Huge thanks to others who gave me inspiration for how to get it done. It features areas for solar, grid, house, car, battery and hot water diverter (eddi). It also uses svg graphics to show energy flows and some simple gradient fills to indicate levels for each of the different areas. Hope it might be of use to someone. Next steps will be to make the individual areas clikable so it can go through to a graph and i also hope to add a section for boiler operation once i have a monitoring system for boiler running.

uid: test_svg
tags: []
props:
  parameters:
    - context: item
      description: Daily Solar
      label: dailySolar
      name: dailySolar
      required: false
      type: TEXT
    - context: item
      description: Power Solar
      label: powerSolar
      name: powerSolar
      required: false
      type: TEXT
    - context: item
      description: Daily Grid In
      label: dailyGridIn
      name: dailyGridIn
      required: false
      type: TEXT
    - context: item
      description: Daily Grid Out
      label: dailyGridOut
      name: dailyGridOut
      required: false
      type: TEXT
    - context: item
      description: Power Grid
      label: powerGrid
      name: powerGrid
      required: false
      type: TEXT
    - context: item
      description: Battery Power
      label: batteryPower
      name: batteryPower
      required: false
      type: TEXT
    - context: item
      description: Battery Pct
      label: batteryPct
      name: batteryPct
      required: false
      type: TEXT
    - context: item
      description: Power Eddi
      label: powerEddi
      name: powerEddi
      required: false
      type: TEXT
    - context: item
      description: Daily Eddi
      label: dailyEddi
      name: dailyEddi
      required: false
      type: TEXT
    - context: item
      description: Temp Eddi
      label: tempEddi
      name: tempEddi
      required: false
      type: TEXT
    - context: item
      description: Temp Status
      label: statusEddi
      name: statusEddi
      required: false
      type: TEXT
    - context: item
      description: EV Power
      label: evPower
      name: evPower
      required: false
      type: TEXT
    - context: item
      description: EV Pct
      label: evPct
      name: evPct
      required: false
      type: TEXT
    - context: item
      description: EV Range
      label: evRange
      name: evRange
      required: false
      type: TEXT
    - context: item
      description: EV Charge Status
      label: evChargeStatus
      name: evChargeStatus
      required: false
      type: TEXT
    - context: item
      description: EV Connect Status
      label: evConnectStatus
      name: evConnectStatus
      required: false
      type: TEXT
    - context: item
      description: House power
      label: powerHouse
      name: powerHouse
      required: false
      type: TEXT
    - context: item
      description: House Today
      label: todayHouse
      name: todayHouse
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Mar 30, 2025, 1:49:37 PM
component: f7-block
config:
  style:
    width: 700px
slots:
  default:
    - component: f7-row
      config:
        style:
          height: 90px
          display: flex
      slots:
        default:
          - component: f7-col
            config:
              style:
                width: 5%
                height: 70px
          - component: f7-col
            config:
              align: center
              style:
                width: 15%
                height: 100%
                display: flex
                align-items: center
                justify-content: space-around
                flex-direction: column
                border: 1px solid rgba(255, 255, 0, 0.5)
                border-radius: 10px
                background: ='linear-gradient(to top, rgba(255, 255, 0, 0.5) ' +
                  (items[props.powerSolar].state / 4000 * 100) + '%, black 0% )'
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: f7:sun_maxx
                - component: Label
                  config:
                    text: ='Today ' + items[props.dailySolar].state / 10 + ' kWh'
                    style:
                      font-size: 12px
                - component: Label
                  config:
                    text: =items[props.powerSolar].state + ' W'
                    style:
                      font-size: 12px
          - component: f7-col
            config:
              style:
                width: 25%
                height: 100%
            slots:
              default:
                - component: svg
                  config:
                    viewBox: 0 0 170 50
                    xlmns: http://www.w3.org/2000/svg
                    style:
                      height: 100%
                      width: 100%
                  slots:
                    default:
                      - component: path
                        config:
                          id: path7
                          d: M 0 35 L 121 35 A 35 35 0 0 1 156 70
                          stroke: yellow
                          stroke-width: 1
                          vector-effect: non-scaling-stroke
                          fill: none
                      - component: circle
                        config:
                          cx: 0
                          cy: 0
                          r: 4
                          fill: yellow
                          visible: =(items[props.powerSolar].state) == 0 ? false:true
                        slots:
                          default:
                            - component: animateMotion
                              config:
                                begin: 0s;
                                calcMode: linear
                                dur: 2s
                                repeatCount: indefinite
                              slots:
                                default:
                                  - component: mpath
                                    config:
                                      href: "#path7"
          - component: f7-col
            config:
              align: center
              style:
                width: 10%
                height: 100%
          - component: f7-col
            config:
              style:
                width: 25%
                height: 100%
            slots:
              default:
                - component: svg
                  config:
                    viewBox: 0 0 170 50
                    xlmns: http://www.w3.org/2000/svg
                    style:
                      height: 100%
                      width: 100%
                  slots:
                    default:
                      - component: path
                        config:
                          id: path8
                          d: M 0 70 A 35 35 0 0 1 35 35 L 170 35
                          stroke: orange
                          stroke-width: 1
                          vector-effect: non-scaling-stroke
                          visible: =(items[props.evConnectStatus].state) == 'disconnected' ? false:true
                          fill: none
                      - component: circle
                        config:
                          cx: 0
                          cy: 0
                          r: 4
                          fill: orange
                          visible: =(items[props.evPower].state) == 0 ? false:true
                        slots:
                          default:
                            - component: animateMotion
                              config:
                                begin: 0s;
                                calcMode: linear
                                dur: 3s
                                repeatCount: indefinite
                              slots:
                                default:
                                  - component: mpath
                                    config:
                                      href: "#path8"
          - component: f7-col
            config:
              align: center
              style:
                width: 15%
                height: 100%
                display: flex
                align-items: center
                justify-content: space-around
                flex-direction: column
                border: 1px solid rgba(255, 165, 0, 0.5)
                border-radius: 10px
                background: ='linear-gradient(to top, rgba(255, 165, 0, 0.5) ' +
                  (items[props.evPct].state) + '%, black 0% )'
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: f7:car_fill
                - component: Label
                  config:
                    text: =items[props.evPower].state + ' kW'
                    style:
                      font-size: 12px
                - component: Label
                  config:
                    text: =items[props.evPct].state + " % | " + items[props.evRange].state + "km"
                    style:
                      font-size: 12px
                - component: Label
                  config:
                    text: =items[props.evChargeStatus].state
                    style:
                      font-size: 10px
          - component: f7-col
            config:
              style:
                width: 5%
                height: 70px
    - component: f7-row
      config:
        style:
          width: 100%
          height: 90px
      slots:
        default:
          - component: f7-col
            config:
              align: center
              style:
                width: 20%
                height: 100%
                display: flex
                align-items: center
                justify-content: space-around
                flex-direction: column
          - component: f7-col
            config:
              align: center
              style:
                width: 20%
                height: 100%
          - component: f7-col
            config:
              align: center
              style:
                width: 20%
                height: 100%
                display: flex
                align-items: center
                justify-content: space-around
                flex-direction: column
                border: 1px solid purple
                border-radius: 20px
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: f7:house
                - component: Label
                  config:
                    text: ='Today ' + items[props.todayHouse].state / 10 + ' kWh'
                    style:
                      font-size: 12px
                - component: Label
                  config:
                    text: =items[props.powerHouse].state + ' kW'
                    style:
                      font-size: 12px
          - component: f7-col
            config:
              style:
                width: 20%
                height: 100%
            slots:
              default:
                - component: svg
                  config:
                    viewBox: 0 0 156 70
                    xlmns: http://www.w3.org/2000/svg
                    style:
                      height: 100%
                      width: 100%
                  slots:
                    default:
                      - component: path
                        config:
                          id: path11
                          d: '=(items[props.batteryPower].numericState) < 0 ? "M 156 35 L 0 35" : "M 0 35
                            L 156 35"'
                          stroke: green
                          stroke-width: 1
                          vector-effect: non-scaling-stroke
                          fill: none
                      - component: circle
                        config:
                          cx: 0
                          cy: 0
                          r: 4
                          fill: green
                        slots:
                          default:
                            - component: animateMotion
                              config:
                                begin: 0s;
                                calcMode: linear
                                dur: 3.5s
                                repeatCount: indefinite
                              slots:
                                default:
                                  - component: mpath
                                    config:
                                      href: "#path11"
          - component: f7-col
            config:
              align: center
              style:
                width: 15%
                height: 100%
                border: 1px solid  rgba(0, 128, 0, 0.5)
                border-radius: 10px
                background: ='linear-gradient(to top, rgba(0, 128, 0, 0.5) ' +
                  (items[props.batteryPct].state) + '%, black 0% )'
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: f7:battery_25
                - component: Label
                  config:
                    text: =items[props.batteryPower].state
                    style:
                      font-size: 12px
                - component: Label
                  config:
                    text: =items[props.batteryPct].state + ' %'
                    style:
                      font-size: 12px
          - component: f7-col
            config:
              style:
                width: 5%
                height: 70px
    - component: f7-row
      config:
        style:
          width: 100%
          height: 90px
      slots:
        default:
          - component: f7-col
            config:
              align: center
              style:
                width: 5%
                height: 100%
                display: flex
                align-items: center
                justify-content: space-around
                flex-direction: column
          - component: f7-col
            config:
              align: center
              style:
                width: 15%
                height: 100%
                display: flex
                align-items: center
                justify-content: space-around
                flex-direction: column
                background: ='linear-gradient(' + ((items[props.powerGrid].state) > 0 ? "to
                  top":"to bottom") + ', rgba(255, 0, 0, 0.5) '
                  +  Math.abs(items[props.powerGrid].state)/10000 * 100 + '%,
                  black 0% )'
                border: 1px solid  rgba(255, 0, 0, 0.5)
                border-radius: 10px
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: if:mdi:transmission-tower
                - component: Label
                  config:
                    text: ='In ' + items[props.dailyGridIn].state / 10 + ' kWh'
                    style:
                      font-size: 12px
                - component: Label
                  config:
                    text: ='Out ' + items[props.dailyGridOut].state / 10 + ' kWh'
                    style:
                      font-size: 12px
                - component: Label
                  config:
                    text: =items[props.powerGrid].state + ' W'
                    style:
                      font-size: 12px
          - component: f7-col
            config:
              style:
                width: 25%
                height: 100%
            slots:
              default:
                - component: svg
                  config:
                    viewBox: 0 0 170 90
                    xlmns: http://www.w3.org/2000/svg
                    style:
                      height: 100%
                      width: 100%
                  slots:
                    default:
                      - component: path
                        config:
                          id: path9
                          d: '=(items[props.powerGrid].state) < 0 ? "M 156 0 A 35 35 0 0 1 121 35 L 0 35 "
                            : "M 0 35 L 121 35 A 35 35 0 0 0 156 0"'
                          stroke: red
                          stroke-width: 1
                          vector-effect: non-scaling-stroke
                          fill: none
                      - component: circle
                        config:
                          cx: 0
                          cy: 0
                          r: 4
                          fill: red
                          visible: true
                        slots:
                          default:
                            - component: animateMotion
                              config:
                                begin: 0s;
                                calcMode: linear
                                dur: 3s
                                repeatCount: indefinite
                              slots:
                                default:
                                  - component: mpath
                                    config:
                                      href: "#path9"
          - component: f7-col
            config:
              align: center
              style:
                width: 10%
                height: 100%
            slots:
              default:
                - component: Label
                  config:
                    style:
                      font-size: 12px
          - component: f7-col
            config:
              style:
                width: 25%
                height: 100%
            slots:
              default:
                - component: svg
                  config:
                    viewBox: 0 0 170 90
                    xlmns: http://www.w3.org/2000/svg
                    style:
                      height: 100%
                      width: 100%
                  slots:
                    default:
                      - component: path
                        config:
                          id: path10
                          d: M 0 0 A 35 35 0 0 0 35 35 L 170 35
                          stroke: blue
                          stroke-width: 1
                          vector-effect: non-scaling-stroke
                          fill: none
                      - component: circle
                        config:
                          cx: 0
                          cy: 0
                          r: 4
                          fill: blue
                          visible: =(items[props.powerEddi].state) == 0 ? false:true
                        slots:
                          default:
                            - component: animateMotion
                              config:
                                begin: 0s;
                                calcMode: linear
                                dur: 2s
                                repeatCount: indefinite
                              slots:
                                default:
                                  - component: mpath
                                    config:
                                      href: "#path10"
          - component: f7-col
            config:
              align: center
              style:
                width: 15%
                height: 100%
                display: flex
                align-items: center
                justify-content: space-around
                flex-direction: column
                background: ='linear-gradient(to top, rgba(0, 0, 255, 0.5) ' +
                  (items[props.tempEddi].state/60 * 100) + '%, black 0% )'
                border: 1px solid  rgba(0, 0, 255, 0.5)
                border-radius: 10px
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: f7:thermometer
                - component: Label
                  config:
                    text: ='Today ' + Math.round(items[props.dailyEddi].state * 100)/100 + ' kWh'
                    style:
                      font-size: 12px
                - component: Label
                  config:
                    text: =items[props.powerEddi].state + ' kW | '  + items[props.tempEddi].state +
                      ' C'
                    style:
                      font-size: 12px
                - component: Label
                  config:
                    text: =items[props.statusEddi].displayState
                    style:
                      font-size: 10px
          - component: f7-col
            config:
              style:
                width: 5%
                height: 70px

4 Likes

The easiest way for users to adopt and use a widget like this is to post it to the Marketplace. Then they can find it in MainUI → Add-on Store → UI Widgets and install it instead of copy and paste.

3 Likes

Would it be possible to add/remove devices, easily? (Without having to manually go through the code).
Like if a user dont have a boiler, solar etc, then there is no need for it to be there?