Energy Widget like in Home Assistant Demo

Thanks for the great Work !!!

Wow, very cool! Thanks for the work!

Are the animations possible or does the technology not allow it?

Probably yes with offset-path and offset-distance it seems… but as usual you can forget Safari. You can define animation keyframes with the stylesheet config property.

For instance, this demo:

Can be reproduced like so:

component: f7-card
slots:
  content:
    - component: f7-block
      config:
        style:
          height: 150px
        stylesheet: >
          @keyframes path-move {
            0% { offset-distance: 0%; }
            100% { offset-distance: 100%; }
          }
      slots:
        default:
          - component: f7-block
            config:
              style:
                width: 40px
                height: 40px
                background: cyan
                animation: path-move 3000ms infinite alternate ease-in-out
                offset-path: path('M20,20 C20,100 200,0 200,100')

going further note that you can override the animation speed with:

animation-duration: =Math.round(3000 - Number.parseFloat(items.SomeValue.state.split(' ')[0]) * 300) + 'ms'`

(or something better) to e.g. make it faster when the item quantity state increases.

More info here:

I’ll leave that as an exercise for the reader :wink:

1 Like

Wow, this is really awesome. Many thanks for your efforts. I also noticed this widget on HA pages.

I’m very new to OH and haven’t started to make my own pages yet because I’m still setting up my controllers with Modbus interface (e.g. Steca inverter). So, I’m wondering how to use this widget.

This is really great. Did also anybody try to make the energy dashboard:

Is this somehow feasible in OH3 MainUI?

So it may be right - I couldn’t resist a challenge.
So going back to this - and yet it’s a hack and could be improved but here it is (I think some have found out this trick before me):

if you want to build your own HTML hierarchy…: well it turns out you can use the f7-row component because it offers the ability to choose your own HTML tag along with their children.

So if you inspect (“steal the code of…?”) Home Assistant’s page you’ll note that the widget’s animated “pipes” is a rather simple SVG:

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice">
              <path id="return" class="return" vector-effect="non-scaling-stroke" d="M47,0 v15 c0,40 -10,35 -30,35 h-20"></path> 
              <path id="solar" class="solar" vector-effect="non-scaling-stroke" d="M53,0 v15 c0,40 10,35 30,35 h20"></path>
              <path class="grid" id="grid" vector-effect="non-scaling-stroke" d="M0,56 H100"></path>
              <circle r="1" class="return" vector-effect="non-scaling-stroke">
                    <animateMotion repeatCount="indefinite" calcMode="linear" dur="5.26366433175909s">
                      <mpath xlink:href="#return"></mpath>
                    </animateMotion>
                  </circle>
              <circle r="1" class="solar" vector-effect="non-scaling-stroke">
                    <animateMotion repeatCount="indefinite" calcMode="linear" dur="3.511455128333689s">
                      <mpath xlink:href="#solar"></mpath>
                    </animateMotion>
                  </circle>
              <circle r="1" class="grid" vector-effect="non-scaling-stroke">
                    <animateMotion repeatCount="indefinite" calcMode="linear" dur="4.102157928533736s">
                      <mpath xlink:href="#grid"></mpath>
                    </animateMotion>
              </circle>
</svg>

So how would you translate this into openHAB’s widget definition YAML? - well, like this:

- component: f7-row
  config:
    tag: svg
    xmlns: http://www.w3.org/2000/svg
    viewBox: 0 0 100 100
    preserveAspectRatio: xMidYMid slice
    style:
      height: auto
  slots:
    default:
      - component: f7-row
        config:
          tag: path
          id: path1
          d: M53,0 v15 c0,40 10,35 30,35 h20
          stroke: orange
          stroke-width: 1
          vector-effect: non-scaling-stroke
          fill: none
      - component: f7-row
        config:
          tag: circle
          r: 1
          vector-effect: non-scaling-stroke
          fill: orange
          style:
            stroke-width: 4
        slots:
          default:
            - component: f7-row
              config:
                tag: animateMotion
                repeatCount: indefinite
                calcMode: linear
                dur: 5s
              slots:
                default:
                  - component: f7-row
                    config:
                      tag: mpath
                      xlink:href: "#path1"
      - component: f7-row
        config:
          tag: path
          id: path2
          d: M47,0 v15 c0,40 -10,35 -30,35 h-20
          stroke: purple
          stroke-width: 1
          vector-effect: non-scaling-stroke
          fill: none
      - component: f7-row
        config:
          tag: circle
          r: 1
          vectorEffect: non-scaling-stroke
          strokeWidth: 10
          fill: purple
        slots:
          default:
            - component: f7-row
              config:
                tag: animateMotion
                repeatCount: indefinite
                calcMode: linear
                dur: 3s
              slots:
                default:
                  - component: f7-row
                    config:
                      tag: mpath
                      xlink:href: "#path2"
      - component: f7-row
        config:
          tag: path
          id: path3
          d: M0,56 H100
          stroke: teal
          stroke-width: 1
          vector-effect: non-scaling-stroke
          fill: none
      - component: f7-row
        config:
          tag: circle
          r: 1
          vectorEffect: non-scaling-stroke
          strokeWidth: 10
          fill: teal
        slots:
          default:
            - component: f7-row
              config:
                tag: animateMotion
                repeatCount: indefinite
                calcMode: linear
                dur: 3s
              slots:
                default:
                  - component: f7-row
                    config:
                      tag: mpath
                      xlink:href: "#path3"

You can change the speed of the animations (dur properties) with expressions as appropriate.
There could be built-in improvements in this area in the future since it definititely has potential!

2022-01-17_22-35-15

Final widget:

uid: energy_summary
tags: []
props:
  parameters: []
  parameterGroups: []
timestamp: Jan 7, 2022, 12:59:10 PM
component: f7-card
config:
  title: Energy Summary (test)
slots:
  content:
    - component: f7-block
      config:
        style:
          margin: 0
          padding: 0
      slots:
        default:
          - component: f7-block
            config:
              style:
                margin: 0
                padding: 0
                display: flex
                justify-content: space-between
                --f7-theme-color: var(--f7-text-color)
                --f7-block-font-size: 12px
            slots:
              default:
                - component: f7-col
                  config:
                    style:
                      display: flex
                      flex-direction: column
                      align-items: center
                  slots:
                    default:
                      - component: Label
                        config:
                          text: Non-fossil
                      - component: f7-block
                        config:
                          style:
                            height: 80px
                            width: 80px
                            border: 2px solid darkgreen
                            border-radius: 40px
                            display: flex
                            justify-content: center
                            align-items: center
                            flex-direction: column
                        slots:
                          default:
                            - component: oh-icon
                              config:
                                icon: if:mdi:leaf
                                height: 20px
                                color: darkgreen
                            - component: Label
                              config:
                                text: 0.7 kWh
                                style:
                                  font-size: 12px
                      - component: f7-block
                        config:
                          style:
                            height: 30px
                            width: 2px
                            padding: 0
                            margin: 0
                            border: 1px solid darkgreen
                            display: flex
                            justify-content: center
                            align-items: center
                            flex-direction: column
                      - component: f7-block
                        config:
                          style:
                            margin-top: 0
                            height: 80px
                            width: 80px
                            border: 2px solid teal
                            border-radius: 40px
                            display: flex
                            justify-content: center
                            align-items: center
                            flex-direction: column
                        slots:
                          default:
                            - component: oh-icon
                              config:
                                icon: if:mdi:transmission-tower
                                height: 20px
                                color: teal
                            - component: oh-link
                              config:
                                text: 2.3 kWh
                                iconF7: arrow_left
                                iconSize: 12px
                                iconColor: purple
                                style:
                                  font-size: 12px
                                  white-space: nowrap
                            - component: oh-link
                              config:
                                text: 5.7 kWh
                                iconF7: arrow_right
                                iconSize: 12px
                                iconColor: blue
                                style:
                                  font-size: 12px
                                  white-space: nowrap
                      - component: Label
                        config:
                          text: Grid
                - component: f7-col
                  config:
                    style:
                      flex-grow: 1
                      display: flex
                      flex-direction: column
                      align-items: center
                  slots:
                    default:
                      - component: Label
                        config:
                          text: Solar
                      - component: f7-block
                        config:
                          style:
                            height: 80px
                            width: 80px
                            border: 2px solid orange
                            border-radius: 40px
                            display: flex
                            justify-content: center
                            align-items: center
                            flex-direction: column
                        slots:
                          default:
                            - component: oh-icon
                              config:
                                icon: if:mdi:solar-power
                                height: 20px
                                color: orange
                            - component: Label
                              config:
                                text: 9.5 kWh
                                style:
                                  font-size: 12px
                      - component: f7-block
                        config:
                          style:
                            margin: 0
                            padding: 0
                            width: 100%
                            display: flex
                            height: 125px
                            justify-content: center
                        slots:
                          default:
                            - component: f7-row
                              config:
                                tag: svg
                                xmlns: http://www.w3.org/2000/svg
                                viewBox: 0 0 100 100
                                preserveAspectRatio: xMidYMid slice
                                style:
                                  height: auto
                              slots:
                                default:
                                  - component: f7-row
                                    config:
                                      tag: path
                                      id: path1
                                      d: M53,0 v15 c0,40 10,35 30,35 h20
                                      stroke: orange
                                      stroke-width: 1
                                      vector-effect: non-scaling-stroke
                                      fill: none
                                  - component: f7-row
                                    config:
                                      tag: circle
                                      r: 1
                                      vector-effect: non-scaling-stroke
                                      fill: orange
                                      style:
                                        stroke-width: 4
                                    slots:
                                      default:
                                        - component: f7-row
                                          config:
                                            tag: animateMotion
                                            repeatCount: indefinite
                                            calcMode: linear
                                            dur: 5s
                                          slots:
                                            default:
                                              - component: f7-row
                                                config:
                                                  tag: mpath
                                                  xlink:href: "#path1"
                                  - component: f7-row
                                    config:
                                      tag: path
                                      id: path2
                                      d: M47,0 v15 c0,40 -10,35 -30,35 h-20
                                      stroke: purple
                                      stroke-width: 1
                                      vector-effect: non-scaling-stroke
                                      fill: none
                                  - component: f7-row
                                    config:
                                      tag: circle
                                      r: 1
                                      vectorEffect: non-scaling-stroke
                                      strokeWidth: 10
                                      fill: purple
                                    slots:
                                      default:
                                        - component: f7-row
                                          config:
                                            tag: animateMotion
                                            repeatCount: indefinite
                                            calcMode: linear
                                            dur: 3s
                                          slots:
                                            default:
                                              - component: f7-row
                                                config:
                                                  tag: mpath
                                                  xlink:href: "#path2"
                                  - component: f7-row
                                    config:
                                      tag: path
                                      id: path3
                                      d: M0,56 H100
                                      stroke: teal
                                      stroke-width: 1
                                      vector-effect: non-scaling-stroke
                                      fill: none
                                  - component: f7-row
                                    config:
                                      tag: circle
                                      r: 1
                                      vectorEffect: non-scaling-stroke
                                      strokeWidth: 10
                                      fill: teal
                                    slots:
                                      default:
                                        - component: f7-row
                                          config:
                                            tag: animateMotion
                                            repeatCount: indefinite
                                            calcMode: linear
                                            dur: 3s
                                          slots:
                                            default:
                                              - component: f7-row
                                                config:
                                                  tag: mpath
                                                  xlink:href: "#path3"
                - component: f7-col
                  config:
                    style:
                      display: flex
                      flex-direction: column
                      align-items: center
                  slots:
                    default:
                      - component: Label
                        config:
                          text: Gas
                      - component: f7-block
                        config:
                          style:
                            height: 80px
                            width: 80px
                            border: 2px solid darkred
                            border-radius: 40px
                            display: flex
                            justify-content: center
                            align-items: center
                            flex-direction: column
                        slots:
                          default:
                            - component: oh-icon
                              config:
                                icon: if:mdi:gas
                                height: 20px
                                color: darkred
                            - component: Label
                              config:
                                text: 1.7 m³
                                style:
                                  font-size: 12px
                      - component: f7-block
                        config:
                          style:
                            height: 30px
                            width: 2px
                            padding: 0
                            margin: 0
                            border: 1px solid darkred
                            display: flex
                            justify-content: center
                            align-items: center
                            flex-direction: column
                      - component: f7-block
                        config:
                          style:
                            margin-top: 0
                            height: 80px
                            width: 80px
                            border: 2px solid gray
                            border-radius: 40px
                            display: flex
                            justify-content: center
                            align-items: center
                            flex-direction: column
                        slots:
                          default:
                            - component: oh-icon
                              config:
                                icon: if:mdi:home
                                height: 20px
                                color: gray
                            - component: Label
                              config:
                                text: 12.9 kWh
                                style:
                                  font-size: 12px
                                  white-space: nowrap
                      - component: Label
                        config:
                          text: Home

17 Likes

Very nice! This should be in the marketplace for sure.

This is perhaps the coolest thing in OH.

I put this widget on my Overview page (copied the code above). I haven’t included my own data yet but will do once I can read my energy meters. There is one glitch, though. For some reason the lines are too short. I tried to look at the code but didn’t find the parameters that I would need to change. I also tried to change the column widths but this didn’t help.

For sure, but I meant this to be a example/showcase and I’m afraid I’m too busy (read: lazy) to make it into a proper turn-key widget. What I’m willing to try however is to make a Wiki entry in the marketplace so the widget would be initially be the one above with the hardcoded values and eventually (but I’m not holding my breath :sweat_smile:) it would be improved by others who can edit wiki entries?

Many thanks to @ysc. Created my first animated widget!

dear
Grat job, I want to start from your code to add the possibility to select items from standard UI

just for information, NON FOSSIL value is related to???
how it’s calculated (or should be calculated?)

How do you read GAS value? there is a special hardware (like shelly em or other for energy ) or do you read the value from your supllier site/api?

This is completely up to you. If you have smart meters at home, you can read them, or try DIY projects for meter readings. There are many to find in google.

I for myself read my gas meter with a proximity sensor and a tasmota baseded nodeMCU and my smart electricity meter with a SML reader connected to the same nodeMCU.

dear All

here you can find the first version of configurable widget.

Let me know if you find some bugs or if you have suggestion for improve it

This is a very nice work, thank you.

I do have a humble question, would it be possible (for someone) to add battery charging and usage to the widget…basically it needs to be connected to Solar and Home for charging from solar and supplying home…

I really tried myself but am really not sufficient enough in YAML design…

Thanks.

Did anybody already managed to rebuild the complete Home Assistant Energy Dashboard with all the charts and graphs.

I think there should be a standard template/page in openHAB to easily create this kind of page, as actually everybody could use it.

2 Likes

Who says that ? I e.g could not use it like I assume many others

There is no need to make it a standard page/widget, but feel free to create the complete setup and publish it to the marketplace, so anybody who wants it, can use it. It might become a nice project like the main_widget project.
But like always, somebody has to make a start.

Hi Livio,

thanks for the nice widget. I like it and use it. I would love to have just one more parameter to add, or basically it could be calculated also with the values we can provide now →

on the left side we see how much we import and export from/to the grid. I would also like to see similarly on the right side (home) how much energy that I used is from the solarplant and how much is imported. its basically a simple substraction from values we have.

could you add it? if not i may fuzzle around a bit with the widget as i think it should be not so difficult. but maybe its quick for you and you like the idea. if not i may share my experiment here.

however. thanks for making this work already!
mathias

Here is my implementation without “Non-fossil” and “Gas”, but with property item-support and slight style changes.

uid: energy-summary
tags: []
props:
  parameters:
    - context: item
      description: The item for grid consumption
      label: Grid Consumption
      name: grid_consumption
      required: false
    - context: item
      description: The item for grid surplus
      label: Grid Surplus
      name: grid_surplus
      required: false
      type: TEXT
    - context: item
      description: The item for pv production
      label: PV Production
      name: pv_production
      required: false
      type: TEXT
    - context: item
      label: PV Own Consumption
      name: pv_own_consumption
      required: false
      type: TEXT
    - context: item
      description: The item for home consumption
      label: Home Consumption
      name: home_consumption
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Aug 17, 2023, 7:14:09 PM
component: f7-card
config:
  title: Energy Summary
slots:
  content:
    - component: f7-block
      config:
        style:
          margin: 0
          padding: 0
      slots:
        default:
          - component: f7-block
            config:
              style:
                margin: 0
                padding: 0
                display: flex
                justify-content: space-between
                --f7-theme-color: var(--f7-text-color)
                --f7-block-font-size: 12px
            slots:
              default:
                - component: f7-col
                  config:
                    style:
                      display: flex
                      flex-direction: column
                      align-items: center
                  slots:
                    default:
                      - component: f7-block
                        config:
                          style:
                            margin-top: 140px
                            padding-top: 10px
                            height: 100px
                            width: 100px
                            border: 2px solid teal
                            border-radius: 50px
                            display: flex
                            justify-content: top
                            align-items: center
                            flex-direction: column
                        slots:
                          default:
                            - component: oh-icon
                              config:
                                icon: if:mdi:transmission-tower
                                height: 25px
                                color: teal
                            - component: oh-link
                              config:
                                text: =@props.grid_surplus
                                iconF7: arrow_left
                                iconSize: 12px
                                iconColor: purple
                                style:
                                  font-size: 12px
                                  white-space: nowrap
                                action: analyzer
                                actionAnalyzerItems:
                                  - =props.grid_surplus
                            - component: oh-link
                              config:
                                text: =@props.grid_consumption
                                iconF7: arrow_right
                                iconSize: 12px
                                iconColor: grey
                                style:
                                  font-size: 12px
                                  white-space: nowrap
                                action: analyzer
                                actionAnalyzerItems:
                                  - =props.grid_consumption
                      - component: Label
                        config:
                          text: Grid
                - component: f7-col
                  config:
                    style:
                      flex-grow: 1
                      display: flex
                      flex-direction: column
                      align-items: center
                  slots:
                    default:
                      - component: Label
                        config:
                          text: PV
                      - component: f7-block
                        config:
                          style:
                            padding-top: 20px
                            height: 100px
                            width: 100px
                            border: 2px solid orange
                            border-radius: 50px
                            display: flex
                            justify-content: top
                            align-items: center
                            flex-direction: column
                        slots:
                          default:
                            - component: oh-icon
                              config:
                                icon: if:mdi:solar-power
                                height: 25px
                                color: orange
                            - component: oh-link
                              config:
                                text: =@props.pv_production
                                style:
                                  font-size: 12px
                                action: analyzer
                                actionAnalyzerItems:
                                  - =props.pv_production
                      - component: f7-block
                        config:
                          style:
                            margin: 0
                            padding: 0
                            width: 100%
                            display: flex
                            height: 125px
                            justify-content: center
                        slots:
                          default:
                            - component: f7-row
                              config:
                                tag: svg
                                xmlns: http://www.w3.org/2000/svg
                                viewBox: 0 0 100 100
                                preserveAspectRatio: xMidYMid slice
                                style:
                                  height: auto
                              slots:
                                default:
                                  - component: f7-row
                                    config:
                                      tag: path
                                      id: path1
                                      d: M53,0 v15 c0,40 10,35 30,35 h20
                                      stroke: orange
                                      stroke-width: 1
                                      vector-effect: non-scaling-stroke
                                      fill: none
                                  - component: f7-row
                                    config:
                                      tag: circle
                                      r: 1
                                      vector-effect: non-scaling-stroke
                                      fill: orange
                                      style:
                                        stroke-width: 4
                                    slots:
                                      default:
                                        - component: f7-row
                                          config:
                                            tag: animateMotion
                                            repeatCount: indefinite
                                            calcMode: linear
                                            dur: 5s
                                          slots:
                                            default:
                                              - component: f7-row
                                                config:
                                                  tag: mpath
                                                  xlink:href: "#path1"
                                  - component: f7-row
                                    config:
                                      tag: path
                                      id: path2
                                      d: M47,0 v15 c0,40 -10,35 -30,35 h-20
                                      stroke: purple
                                      stroke-width: 1
                                      vector-effect: non-scaling-stroke
                                      fill: none
                                  - component: f7-row
                                    config:
                                      tag: circle
                                      r: 1
                                      vectorEffect: non-scaling-stroke
                                      strokeWidth: 10
                                      fill: purple
                                    slots:
                                      default:
                                        - component: f7-row
                                          config:
                                            tag: animateMotion
                                            repeatCount: indefinite
                                            calcMode: linear
                                            dur: 3s
                                          slots:
                                            default:
                                              - component: f7-row
                                                config:
                                                  tag: mpath
                                                  xlink:href: "#path2"
                                  - component: f7-row
                                    config:
                                      tag: path
                                      id: path3
                                      d: M0,56 H100
                                      stroke: teal
                                      stroke-width: 1
                                      vector-effect: non-scaling-stroke
                                      fill: none
                                  - component: f7-row
                                    config:
                                      tag: circle
                                      r: 1
                                      vectorEffect: non-scaling-stroke
                                      strokeWidth: 10
                                      fill: teal
                                    slots:
                                      default:
                                        - component: f7-row
                                          config:
                                            tag: animateMotion
                                            repeatCount: indefinite
                                            calcMode: linear
                                            dur: 3s
                                          slots:
                                            default:
                                              - component: f7-row
                                                config:
                                                  tag: mpath
                                                  xlink:href: "#path3"
                - component: f7-col
                  config:
                    style:
                      display: flex
                      flex-direction: column
                      align-items: center
                  slots:
                    default:
                      - component: f7-block
                        config:
                          style:
                            margin-top: 140px
                            padding-top: 10px
                            height: 100px
                            width: 100px
                            border: 2px solid gray
                            border-radius: 50px
                            display: flex
                            justify-content: top
                            align-items: center
                            flex-direction: column
                        slots:
                          default:
                            - component: oh-icon
                              config:
                                icon: if:mdi:home
                                height: 25px
                                color: grey
                            - component: oh-link
                              config:
                                text: =@props.pv_own_consumption
                                iconF7: arrow_right
                                iconSize: 12px
                                iconColor: yellow
                                style:
                                  font-size: 12px
                                  white-space: nowrap
                                action: analyzer
                                actionAnalyzerItems:
                                  - =props.pv_own_consumption
                            - component: oh-link
                              config:
                                text: =@props.home_consumption
                                iconF7: arrow_right
                                iconSize: 12px
                                iconColor: grey
                                style:
                                  font-size: 12px
                                  white-space: nowrap
                                action: analyzer
                                actionAnalyzerItems:
                                  - =props.home_consumption
                      - component: Label
                        config:
                          text: Home

image

Having strange problems when it comes to small screens. Any idea how to solve this?

image

After a few hours of work and a lot of fiddling, I finally finished my HA-like energy dashboard.
Now all that’s missing is my balcony power plant.
Thank you everyone for the templates and ideas.

I couldn’t solve a problem with the energy widget. As soon as no solar item is selected, the widget becomes much wider than with the solar item selected. That’s a shame, especially if you want to create a universal dashboard and the width of a widget plays an important role.

2 Likes