Energy_Power-Flow-Card
Energiefluss-Visualisierung mit SVG + Floorplan-Card
Heute möchte ich euch meine Custom Energy-Flow-Card vorstellen. Ich habe sie jetzt eine Woche im Einsatz und läuft sehr zuverlässig. Animiert werden die Energieflüsse so wie man es aus der Power-Flow-Card von HA kennt. Zusätzlich wird der Batterieladestand optisch angezeigt und der Punkt vom Hausnetz passt sich je nach Nutzung Solar/Netz/Batterie farblich an. Außerdem sieht man immer den aktuellen Tagesverbrauch (kWh) und die aktuelle Leistung (W) der einzelnen Stränge auf einen Blick.
Für das Projekt nutze ich eine SVG-Grafik, eine css-Datei und die custom:floorplan-card
. Letztendlich müsst ihr im Beispielcode zur Card nur eure Entitäten/Sensoren austauschen und die Card sollte funktionieren.
Für ausführliche Erklärungen, wie man die SVG erstellt und verknüpft schaut euch bitte die Pool-Flow-Card an. Dort habe ich alles genau erklärt.
Voraussetzungen
- HACS installiert
floorplan-card
Custom Card installiert- Sensoren mit täglichen Energie-Werten
- CSS-Datei (energy-flow-card.css) zur dynamischen Gestaltung
Aufbau der Card im Detail
Ihr müsst einfach in der Card eure Entitäten eintragen und könnt im Anschluss die Card nutzen. Alle Animationen und Grenzwerte habe ich soweit eingestellt. Ihr könnt sie natürlich anpassen, aber die Card sollte auf Anhieb funktionieren. Im www Ordner legt ihr bitte noch einen Unterordner an z.B. Energy_Power-Flow-Card und darin speichert/kopiert ihr die css-Datei und das SVG(Bild). Die Card wird im Dashboard erstellt und der Code sieht wie folgt aus. In den ersten Zeilen des Codes müsst ihr das Bild und die CSS entsprechend eurem erstelltem Ordner verlinken.
type: custom:floorplan-card
grid_options:
columns: full
config:
console_log_level: info
defaults:
hover_action: hover-info
tap_action: more-info
image: /local/energy-flow-card/energy-flow-card-small.svg
stylesheet: /local/energy-flow-card/energy-flow-card.css
rules:
- element: soc
entity: sensor.batterie_ladezustand #Batteriestand in Prozent
state_action:
- service: floorplan.text_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
(Math.round(entity.state * 10) / 10).toString().replace(".", ",") +
" %" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
'display:block' : 'display:none'}
- service: floorplan.class_set
service_data:
class: static-value
- element: batterie100
entity: sensor.batterie_ladezustand #Batteriestand in Prozent wird berechnet
state_action:
action: call-service
service: floorplan.style_set
service_data: |
${parseFloat(entity.state) > 97 ? 'display:block' : 'display:none'}
- element: batterie80
entity: sensor.batterie_ladezustand
state_action:
action: call-service
service: floorplan.style_set
service_data: |
${parseFloat(entity.state) > 80 ? 'display:block' : 'display:none'}
- element: batterie60
entity: sensor.batterie_ladezustand
state_action:
action: call-service
service: floorplan.style_set
service_data: |
${parseFloat(entity.state) > 60 ? 'display:block' : 'display:none'}
- element: batterie40
entity: sensor.batterie_ladezustand
state_action:
action: call-service
service: floorplan.style_set
service_data: |
${parseFloat(entity.state) > 40 ? 'display:block' : 'display:none'}
- element: batterie20
entity: sensor.batterie_ladezustand
state_action:
action: call-service
service: floorplan.style_set
service_data: |
${parseFloat(entity.state) > 1 ? 'display:block' : 'display:none'}
- element: dreieckbatteriein
entity: sensor.acpowerzubatterie_energy_power #Batterie Eingangsleistung Watt
state_action:
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 30) ?
'display:block' : 'display:none'}
- element: dreieckbatterieout
entity: sensor.acpowervonbatterie_energy_power #Batterie Ausgangsleistung Watt
state_action:
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0.1) ?
'opacity:1' : 'opacity:0'}
- element: batteriein
entity: sensor.acpowerzubatterie_energy_power #Batterie Eingangsleistung Watt
state_action:
- service: floorplan.class_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 30) ?
"batteriein" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 30) ?
"display:block" : "display:none"}
- element: batterieoutani
entity: sensor.acpowervonbatterie_energy_power #Batterie Ausgangsleistung Watt
state_action:
- service: floorplan.class_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 10) ?
"hausin" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 10) ?
"display:block" : "display:none"}
- element: solaroutani
entities:
- sensor.total_solar_power_kombiniert #Solareingangsleistung Watt
- sensor.total_power_kombiniert #Hausverbauch Watt
state_action:
- service: floorplan.class_set
service_data: |-
${(
states['sensor.total_solar_power_kombiniert'].state !== undefined &&
states['sensor.total_power_kombiniert'].state !== undefined &&
parseFloat(states['sensor.total_solar_power_kombiniert'].state) >= parseFloat(states['sensor.total_power_kombiniert'].state)
) ? "hausin" : ""}
- service: floorplan.style_set
service_data: |-
${(
states['sensor.total_solar_power_kombiniert'].state !== undefined &&
states['sensor.total_power_kombiniert'].state !== undefined &&
parseFloat(states['sensor.total_solar_power_kombiniert'].state) >= parseFloat(states['sensor.total_power_kombiniert'].state)
) ? "display:block" : "display:none"}
- element: hausin
entities:
- sensor.total_solar_power_kombiniert #Solareingangsleistung Watt
- sensor.total_power_kombiniert #Hausverbauch Watt
state_action:
- service: floorplan.class_set
service_data: |-
${(
states['sensor.total_power_kombiniert'] &&
states['sensor.total_solar_power_kombiniert'] &&
parseFloat(states['sensor.total_power_kombiniert'].state) >= parseFloat(states['sensor.total_solar_power_kombiniert'].state)
) ? "hausin" : ""}
- service: floorplan.style_set
service_data: |-
${(
states['sensor.total_power_kombiniert'] &&
states['sensor.total_solar_power_kombiniert'] &&
parseFloat(states['sensor.total_power_kombiniert'].state) >= parseFloat(states['sensor.total_solar_power_kombiniert'].state)
) ? "display:block" : "display:none"}
- element: solarin
entity: sensor.total_solar_power_kombiniert #Solareingangsleistung Watt
state_action:
- service: floorplan.class_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 10) ?
"solarin" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 10) ?
"display:block" : "display:none"}
- element: netzin # Sensor sollte positive und negative Werte haben, Rest wird berechnet
entity: sensor.total_power #Netzbezug Watt von extern
state_action:
- service: floorplan.class_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 10) ?
"netzin" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 10) ?
"display:block" : "display:none"}
- element: netzout # Sensor sollte positive und negative Werte haben, Rest wird berechnet
entity: sensor.total_power #Netzeinspeisung Watt in extern
state_action:
- service: floorplan.class_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) < 0) ?
"netzout" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) < 0) ?
"display:block" : "display:none"}
- element: hausin
entity: sensor.acpowervonbatterie_energy_power #Batterie Ausgangsleistung Watt
state_action:
action: call-service
service: floorplan.class_set
service_data: >-
${(parseFloat(entity.state) > 0) ? 'hausin batteriebetrieb' :
'hausin'}
- element: solarleistung
entity: sensor.erzeugzung_taglich_kombination_solaranlagen #Solareingang Heute in kWh
state_action:
- service: floorplan.text_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
(Math.round(entity.state * 10) / 10).toString().replace(".", ",") +
" kWh" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
'display:block' : 'display:none'}
- service: floorplan.class_set
service_data:
class: static-value
- element: solarleistungwatt
entity: sensor.total_solar_power_kombiniert #Solareingangsleistung aktuell in Watt
state_action:
- service: floorplan.text_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
(Math.round(entity.state * 10) / 10).toString().replace(".", ",") +
" W" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
'display:block' : 'display:none'}
- service: floorplan.class_set
service_data:
class: static-value
- element: batterie
entity: sensor.acpowerzubatterie_energy_today #Batterieeingang Heute in kWh
state_action:
- service: floorplan.text_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0.1) ?
(Math.round(entity.state * 10) / 10).toString().replace(".", ",") +
" kWh" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
'display:block' : 'display:none'}
- service: floorplan.class_set
service_data:
class: static-value
- element: batterieinwatt
entity: sensor.acpowerzubatterie_energy_power #Batterie Eingangsleistung Watt
state_action:
- service: floorplan.text_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 30) ?
(Math.round(entity.state * 10) / 10).toString().replace(".", ",") +
" W" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 30) ?
'display:block' : 'display:none'}
- service: floorplan.class_set
service_data:
class: static-value
- element: batterieout
entity: sensor.acpowervonbatterie_energy_today #Batterieausgang Heute in kWh
state_action:
- service: floorplan.text_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0.1) ?
(Math.round(entity.state * 10) / 10).toString().replace(".", ",") +
" kWh" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
'display:block' : 'display:none'}
- service: floorplan.class_set
service_data:
class: static-value
- element: batterieoutwatt
entity: sensor.acpowervonbatterie_energy_power #Batterie Ausgangsleistung Watt
state_action:
- service: floorplan.text_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
(Math.round(entity.state * 10) / 10).toString().replace(".", ",") +
" W" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
'display:block' : 'display:none'}
- service: floorplan.class_set
service_data:
class: static-value
- element: hausverbrauchwatt
entity: sensor.total_power_kombiniert #Hausverbauch aktuell Leistung in Watt
state_action:
- service: floorplan.text_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
(Math.round(entity.state * 10) / 10).toString().replace(".", ",") +
" W" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
'display:block' : 'display:none'}
- service: floorplan.class_set
service_data:
class: static-value
- element: hausverbrauch
entity: sensor.verbrauch_taglich_nach_abzug #Hausverbauch Heute in kWh
state_action:
- service: floorplan.text_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
(Math.round(entity.state * 10) / 10).toString().replace(".", ",") +
" kWh" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
'display:block' : 'display:none'}
- service: floorplan.class_set
service_data:
class: static-value
- element: netzbezug
entity: sensor.stromverbrauch_taglich #Netzbezug Heute in kWh von extern
state_action:
- service: floorplan.text_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
(Math.round(entity.state * 10) / 10).toString().replace(".", ",") +
" kWh" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
'display:block' : 'display:none'}
- service: floorplan.class_set
service_data:
class: static-value
- element: netztbezugwatt
entity: sensor.total_power #Netzbezug Watt von extern
state_action:
- service: floorplan.text_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
(Math.round(entity.state * 10) / 10).toString().replace(".", ",") +
" W" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
'display:block' : 'display:none'}
- service: floorplan.class_set
service_data:
class: static-value
- element: netzeinspeisung
entity: sensor.solar_netzeinspeisung_kwh_taglich #Netzeinspeisung Heute in kWh in extern
state_action:
- service: floorplan.text_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0.1) ?
(Math.round(entity.state * 10) / 10).toString().replace(".", ",") +
" kWh" : ""}
- service: floorplan.style_set
service_data: >-
${(entity.state !== undefined && parseFloat(entity.state) > 0) ?
'display:block' : 'display:none'}
- service: floorplan.class_set
service_data:
class: static-value
card_mod:
style: |
ha-card {
background: none !important;
box-shadow: none !important;
border: none;
}
Ich habe ein neues github angefangen, darin sammel ich meine custom-cards, blueprints, esp-home-projekte und emoji. Wird sich in Zukunft sicherlich noch weiter füllen. GitHub - jayjojayson/HomeAssistant-Tools_Utilities_Gadgets: Home Assistant - Tools, Utilities & Gadgets (Collection about my HA Stuff). Wer Interesse hat, kann gerne vorbeischauen, ist wie gesagt noch im Aufbau.
EDIT: Für bessere Übersicht und welcher Sensor wo eingetragen werden muss, habe ich entsprechende Notizen eingefügt.