Out of the box
Thanks a lot
You mentioned above also the issue that the PV power label is shifted down towards the center when the battery is neither charging nor discharging. I think that’s a rare situation that doesn’t happen in most systems, which is probably why it has not been widely noticed. But it is possible. So I added some transparent dummy text that is placed instead of the battery arrows and power value in that case. It should keep the PV power roughly where it should be. I have tested with light and dark modes and it seems to work as far as I can tell, although the widget in general does not look so great in dark mode.
So here is version 1.4:
uid: E3DC_Widget
tags:
- e3dc
- pv
- version 1.4
props:
parameters:
- context: item
label: Stromnetz Bezug / Grid-to-Home
name: gridtohome
required: true
type: TEXT
- context: item
label: Stromnetz Einspeisung / Home-to-Grid
name: hometogrid
required: true
type: TEXT
- context: item
label: Haushalt Verbrauch / Household Consumption
name: household_consumption
required: true
type: TEXT
- context: item
label: PV Leistung / PV Power
name: pv_power
required: true
type: TEXT
- context: item
label: Batterie Laden / Battery Charge
name: battery_charge
required: true
type: TEXT
- context: item
label: Batterie Entladen / Battery Discharge
name: battery_discharge
required: true
type: TEXT
- context: item
label: Batterie Ladezustand / Battery SoC
name: batterylevel
required: true
type: TEXT
- context: item
label: Wallbox Ladestrom / Wallbox Charging
name: wallbox_charge
required: false
type: TEXT
- context: item
label: externer Stromproduzent / External Inverter
name: external_energy
required: false
type: TEXT
parameterGroups: []
timestamp: Feb 28, 2024, 3:49:14 PM
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: '=props.external_energy ? (Number.parseFloat(items[props.external_energy].state.split(" ")[0]) > 0) ? true : false : false'
- component: Label
config:
style:
font-size: 1em
font-weight: bold
margin-top: 0.7em
text-align: center
text: =items[props.batterylevel].state
- component: oh-icon
config:
height: 40em
icon: e3dc_akku_0
visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) < 2) ? true : false'
- component: oh-icon
config:
height: 40em
icon: e3dc_akku_25
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:
height: 40em
icon: e3dc_akku_50
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:
height: 40em
icon: e3dc_akku_75
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:
height: 40em
icon: e3dc_akku_90
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:
height: 40em
icon: e3dc_akku_100
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_power].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
padding-bottom: 2.1em
text-align: center
text: =Math.abs(Number.parseFloat(items[props.pv_power].state.split(" ")[0])) + ' ᵂ'
- component: f7-row
config:
class: arrowright
visible: '=props.external_energy ? (Number.parseFloat(items[props.external_energy].state.split(" ")[0]) > 0) ? true : false : 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
padding-bottom: 2.1em
text-align: center
text: '=props.external_energy ? Math.abs(Number.parseFloat(items[props.external_energy].state.split(" ")[0])) + " ᵂ" : ""'
visible: '=props.external_energy ? (Number.parseFloat(items[props.external_energy].state.split(" ")[0]) > 0) ? true : false : false'
- component: f7-row
config:
class: arrowright
visible: '=(Number.parseFloat(items[props.battery_discharge].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.battery_charge].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: f7-row
config:
visible: '=(Number.parseFloat(items[props.battery_charge].state.split(" ")[0]) == 0) && (Number.parseFloat(items[props.battery_discharge].state.split(" ")[0]) == 0) ? true : false'
slots:
default:
- component: Label
config:
style:
font-size: 0.6em
color: transparent
text-align: center
text: ='0'
- component: Label
config:
style:
color: green
font-size: 1em
font-weight: bold
text-align: center
text: =Math.abs(Number.parseFloat(items[props.battery_charge].state.split(" ")[0])) + ' ᵂ'
visible: '=(Number.parseFloat(items[props.battery_charge].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.battery_discharge].state.split(" ")[0])) + ' ᵂ'
visible: '=(Number.parseFloat(items[props.battery_discharge].state.split(" ")[0]) > 0) ? true : false'
- component: Label
config:
style:
font-size: 1em
color: transparent
text-align: center
text: ='0'
visible: '=(Number.parseFloat(items[props.battery_charge].state.split(" ")[0]) == 0) && (Number.parseFloat(items[props.battery_discharge].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
icon: e3dc
width: 60em
- 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.hometogrid].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.gridtohome].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
padding-bottom: 2.1em
text-align: center
text: =Math.abs(Number.parseFloat(items[props.gridtohome].state.split(" ")[0])) + ' ᵂ'
visible: '=(Number.parseFloat(items[props.hometogrid].state.split(" ")[0]) == 0) ? true : false'
- component: Label
config:
style:
color: green
font-size: 1em
font-weight: bold
padding-bottom: 2.1em
text-align: center
text: =Math.abs(Number.parseFloat(items[props.hometogrid].state.split(" ")[0])) + ' ᵂ'
visible: '=(Number.parseFloat(items[props.hometogrid].state.split(" ")[0]) > 0) ? true : false'
- component: f7-row
config:
class: arrowright
visible: '=props.wallbox_charge ? (Number.parseFloat(items[props.wallbox_charge].state.split(" ")[0]) > 0) ? true : false : 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
padding-bottom: 2.1em
text-align: center
text: '=props.wallbox_charge ? Math.abs(Number.parseFloat(items[props.wallbox_charge].state.split(" ")[0])) + " ᵂ" : ""'
visible: '=props.wallbox_charge ? (Number.parseFloat(items[props.wallbox_charge].state.split(" ")[0]) > 0) ? true : false : false'
- component: f7-row
config:
class: arrowright
visible: '=(Number.parseFloat(items[props.household_consumption].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.household_consumption].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: '=props.wallbox_charge ? (Number.parseFloat(items[props.wallbox_charge].state.split(" ")[0]) > 0) ? true : false : false'
- component: oh-icon
config:
color: orange
height: 40em
icon: e3dc_home
style:
margin-top: 1em
Please let me know if you find any further issues.
@vbbaby3 : As you are the creator/maintainer of the widget, please take a look and see if you like it.
No problem, you can do what you want
I switched to home assistant