E3DC Solar Widget 1.2 with animated arrows

Here is my first Custom Widget with animated arrows.
Thanks @JustinG for the help with the stylesheet propertys for the arrows
Maybe someone will use it…

animine4

The Icons you need:
animine5

e3dc_akku_25e3dc_akku_50e3dc_akku_75e3dc_akku_0e3dc_akku_90e3dc_akku_100
e3dc_pv_sune3dce3dc_homee3dc_externe3dc_nete3dc_wallbox

uid: E3DC_Portal
tags: []
props:
  parameters:
    - context: item
      label: Stromnetz Verbrauch
      name: netzverbrauch
      required: true
      type: TEXT
    - context: item
      label: Stromnetz Einspeisung
      name: netzeinspeisung
      required: true
      type: TEXT
    - context: item
      label: Haushalt Verbrauch
      name: gesamtverbrauch
      required: true
      type: TEXT
    - context: item
      label: PV Leistung
      name: pv_leistung
      required: true
      type: TEXT
    - context: item
      label: Batterie Laden
      name: batterieladen
      required: true
      type: TEXT
    - context: item
      label: Batterie Entladen
      name: batterieentladen
      required: true
      type: TEXT
    - context: item
      label: Batterie Ladezustand
      name: batterylevel
      required: true
      type: TEXT
    - context: item
      label: Wallbox Ladestrom
      name: wallboxladestrom
      required: false
      type: TEXT
    - context: item
      label: externer Stromproduzent
      name: externerg
      required: false
      type: TEXT        
  parameterGroups: []
timestamp: Mar 10, 2022, 10:08:22 AM
component: f7-card
config:
  style:
    padding: 1%
    justify-content: center
  class:
    - display-flex
    - align-items-center
  stylesheet: >
    .arrowleft {
       #position: absolute;
       #top: 50%;
       #left: 50%;
       #transform: translate(50%,50%);
     }
    .arrowleft div {
       display: block;
       width: 0.4em;
       height: 0.4em;
       border-bottom: 0.15em solid var(--f7-text-color);
       border-right: 0.15em solid var(--f7-text-color);
       transform: rotate(135deg);
       #margin: -25px;
       animation: animate 2s infinite;
    }  .arrowleft div:nth-child(2){
        animation-delay: -0.2s;
    }  .arrowleft div:nth-child(3){
        animation-delay: -0.4s;
    }  @keyframes animate {
        0%{
            opacity: 0;
            transform: rotate(135deg) translate(-0.7em,-0.7em);
        }
        50%{
            opacity: 1;
        }
        100%{
            opacity: 0;
            transform: rotate(135deg) translate(0.7em,0.7em);
        }
    }                 .arrowright {
       #position: absolute;
       #top: 50%;
       #left: 50%;
       #transform: translate(-50%,-50%);
     }
    .arrowright div {
       display: block;
       width: 0.4em;
       height: 0.4em;
       border-bottom: 0.15em solid var(--f7-text-color);
       border-right: 0.15em solid var(--f7-text-color);
       transform: rotate(-45deg);
       #margin: -25px;
       animation: animate2 2s infinite;
    }    .arrowright div:nth-child(2) {
        animation-delay: 0.2s;
    }      .arrowright div:nth-child(3) {
        animation-delay: 0.4s;
    }     @keyframes animate2 {
        0%{
            opacity: 0;
            transform: rotate(-45deg) translate(-0.7em,-0.7em);
        }
        50%{
            opacity: 1;
        }
        100%{
            opacity: 0;
            transform: rotate(-45deg) translate(0.7em,0.7em);
        }
    }                   
slots:
  default:
    - component: f7-col
      config:
        style:
          align-items: center
          display: flex
          flex-direction: column
          justify-content: center
          width: 20%
      slots:
        default:
          - component: oh-icon
            config:
              height: 40em
              icon: e3dc_pv_sun
          - component: oh-icon
            config:
              height: 40em
              icon: e3dc_extern
              style:
                margin-top: 1em
              visible: '=(Number.parseFloat(items[props.externerg].state.split(" ")[0]) >= 0) ? true : false'
          - component: Label
            config:
              style:
                font-size: 1em
                font-weight: bold
                text-align: center
                margin-top: 0.7em
              text: =items[props.batterylevel].state
          - component: oh-icon
            config:
              icon: e3dc_akku_0
              height: 40em
              visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) < 2) ? true : false'
          - component: oh-icon
            config:
              icon: e3dc_akku_25
              height: 40em
              visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) >= 2 && Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) < 25) ? true : false'
          - component: oh-icon
            config:
              icon: e3dc_akku_50
              height: 40em
              visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) >= 25 && Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) < 50) ? true : false'
          - component: oh-icon
            config:
              icon: e3dc_akku_75
              height: 40em
              visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) >= 50 && Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) < 75) ? true : false'
          - component: oh-icon
            config:
              icon: e3dc_akku_90
              height: 40em
              visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) >= 75 && Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) < 99) ? true : false'
          - component: oh-icon
            config:
              icon: e3dc_akku_100
              height: 40em
              visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) >= 99) ? true : false'
    - component: f7-col
      config:
        style:
          align-items: center
          display: flex
          flex-direction: column
          width: 20%
      slots:
        default:
          - component: f7-row
            config:
              class: arrowright
              visible: '=(Number.parseFloat(items[props.pv_leistung].state.split(" ")[0]) > 0) ? true : false'
            slots:
              default:
                - component: Label
                  config:
                    class: arrowright div
                - component: Label
                  config:
                    class: arrowright div
                - component: Label
                  config:
                    class: arrowright div
          - component: f7-row
            slots:
              default:
                - component: Label
                  config:
                    style:
                      font-size: 1em
                      font-weight: bold
                      text-align: center
                      padding-bottom: 2.1em                      
                    text: =Math.abs(Number.parseFloat(items[props.pv_leistung].state.split(" ")[0])) + ' ᵂ'
          - component: f7-row
            config:
              class: arrowright
              visible: '=(Number.parseFloat(items[props.externerg].state.split(" ")[0]) >= 0) ? true : false'
            slots:
              default:
                - component: Label
                  config:
                    class: arrowright div
                - component: Label
                  config:
                    class: arrowright div
                - component: Label
                  config:
                    class: arrowright div
          - component: f7-row
            slots:
              default:
                - component: Label
                  config:
                    style:
                      font-size: 1em
                      font-weight: bold
                      text-align: center
                      padding-bottom: 2.1em
                    text: =Math.abs(Number.parseFloat(items[props.externerg].state.split(" ")[0])) + ' ᵂ'
                    visible: '=(Number.parseFloat(items[props.externerg].state.split(" ")[0]) >= 0) ? true : false'
          - component: f7-row
            config:
              class: arrowright
              visible: '=(Number.parseFloat(items[props.batterieentladen].state.split(" ")[0]) > 0) ? true : false'
            slots:
              default:
                - component: Label
                  config:
                    class: arrowright div
                - component: Label
                  config:
                    class: arrowright div
                - component: Label
                  config:
                    class: arrowright div
          - component: f7-row
            config:
              class: arrowleft
              visible: '=(Number.parseFloat(items[props.batterieladen].state.split(" ")[0]) > 0) ? true : false'
            slots:
              default:
                - component: Label
                  config:
                    class: arrowleft div
                - component: Label
                  config:
                    class: arrowleft div
                - component: Label
                  config:
                    class: arrowleft div
          - component: Label
            config:
              style:
                color: green
                font-size: 1em
                font-weight: bold
                text-align: center
              text: =Math.abs(Number.parseFloat(items[props.batterieladen].state.split(" ")[0])) + ' ᵂ'
              visible: '=(Number.parseFloat(items[props.batterieladen].state.split(" ")[0]) > 0) ? true : false'
          - component: Label
            config:
              style:
                color: red
                font-size: 1em
                font-weight: bold
                text-align: center
              text: =Math.abs(Number.parseFloat(items[props.batterieentladen].state.split(" ")[0])) + ' ᵂ'
              visible: '=(Number.parseFloat(items[props.batterieentladen].state.split(" ")[0]) > 0) ? true : false'
    - component: f7-col
      config:
        style:
          align-items: center
          display: flex
          flex-direction: column
          justify-content: center
          width: 20%
      slots:
        default:
          - component: f7-block
            config:
              style:
                align-items: center
                display: flex
                flex-direction: column
                justify-content: center
            slots: {}
          - component: oh-icon
            config:
              height: 60em
              width: 60em
              icon: e3dc
    - component: f7-col
      config:
        style:
          align-items: center
          display: flex
          flex-direction: column
          justify-content: center
          width: 20%
      slots:
        default:
          - component: f7-row
            config:
              class: arrowright
              visible: '=(Number.parseFloat(items[props.netzverbrauch].state.split(" ")[0]) > 0) ? true : false'
            slots:
              default:
                - component: Label
                  config:
                    class: arrowright div
                - component: Label
                  config:
                    class: arrowright div
                - component: Label
                  config:
                    class: arrowright div
          - component: f7-row
            config:
              class: arrowleft
              visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0]) > 0) ? true : false'
            slots:
              default:
                - component: Label
                  config:
                    class: arrowleft div
                - component: Label
                  config:
                    class: arrowleft div
                - component: Label
                  config:
                    class: arrowleft div
          - component: Label
            config:
              style:
                color: red
                font-size: 1em
                font-weight: bold
                text-align: center
                padding-bottom: 2.1em
              text: =Math.abs(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0])) + ' ᵂ'
              visible: '=(Number.parseFloat(items[props.netzverbrauch].state.split(" ")[0]) == 0) ? true : false'
          - component: Label
            config:
              style:
                color: green
                font-size: 1em
                font-weight: bold
                text-align: center
                padding-bottom: 2.1em
              text: =Math.abs(Number.parseFloat(items[props.netzverbrauch].state.split(" ")[0])) + ' ᵂ'
              visible: '=(Number.parseFloat(items[props.netzverbrauch].state.split(" ")[0]) > 0) ? true : false'
          - component: f7-row
            config:
              class: arrowright
              visible: '=(Number.parseFloat(items[props.wallboxladestrom].state.split(" ")[0]) >= 0) ? true : false'
            slots:
              default:
                - component: Label
                  config:
                    class: arrowright div
                - component: Label
                  config:
                    class: arrowright div
                - component: Label
                  config:
                    class: arrowright div
          - component: Label
            config:
              style:
                font-size: 1em
                font-weight: bold
                text-align: center
                padding-bottom: 2.1em 
              visible: '=(Number.parseFloat(items[props.wallboxladestrom].state.split(" ")[0]) >= 0) ? true : false'
              text: =Math.abs(Number.parseFloat(items[props.wallboxladestrom].state.split(" ")[0])) + ' ᵂ'
          - component: f7-row
            config:
              class: arrowright
              visible: '=(Number.parseFloat(items[props.gesamtverbrauch].state.split(" ")[0]) > 0) ? true : false'
            slots:
              default:
                - component: Label
                  config:
                    class: arrowright div
                - component: Label
                  config:
                    class: arrowright div
                - component: Label
                  config:
                    class: arrowright div
          - component: Label
            config:
              style:
                font-size: 1em
                font-weight: bold
                text-align: center
              text: =Math.abs(Number.parseFloat(items[props.gesamtverbrauch].state.split(" ")[0])) + ' ᵂ'
    - component: f7-col
      config:
        style:
          align-items: center
          display: flex
          flex-direction: column
          justify-content: center
          width: 20%
      slots:
        default:
          - component: oh-icon
            config:
              height: 40em
              icon: e3dc_net
          - component: oh-icon
            config:
              height: 40em
              icon: e3dc_wallbox
              style:
                margin-top: 1em
              visible: '=(Number.parseFloat(items[props.wallboxladestrom].state.split(" ")[0]) >= 0) ? true : false'
          - component: oh-icon
            config:
              color: orange
              height: 40em
              icon: e3dc_home
              style:
                margin-top: 1em

7 Likes

I updated the first post, with new arrows and better css

1 Like

Again an Update:

  • added Wallbox
  • added external generator
  • bugfixes

If you don´t have a Wallbox or external generator don´t fill the props, then they are not shown in the widget

1 Like

hier ein paar alternative Icons als SVG
e3dc_home
e3dc_logo
e3dc_net
e3dc_akku_0
e3dc_akku_25
e3dc_akku_50
e3dc_akku_75
e3dc_akku_90
e3dc_akku_100
e3dc_pv_sun
e3dc_pv_sun_e
e3dc_pv_sun_n
e3dc_pv_sun_s
e3dc_pv_sun_w
e3dc_wallbox
e3dc_wallbox_blue
e3dc_wallbox_green
e3dc_wallbox_red

1 Like

Looks really nice, where do i have to put the icons?

Put them under conf/icons/classic

It ist now under Add-On Marketplace → UI Widgets

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.