Solarprognose in Apex-Chart mit automatischem Graph-Span und Offset

Hallo,
ich suche jetzt schon seit Tagen an einer Lösung um ein Datums/Zeitformat in eine Dezimal-Zahl umzuwandeln.

    ##Integration SUN
    {{ states ('sensor.sun_next_rising') }}
    ##Integration SUN2
    {{ state_attr ('sensor.home_sun_rising','today') }}

Die Ergebnisse sehen dann so aus:

##Integration SUN
2024-12-20T07:32:02+00:00
##Integration SUN2
2024-12-19 08:32:36.584927+01:00

Einmal in Sommer/Winterzeit einmal in UTC.
Mein Ziel wäre es, dieses Datum/Zeitformat in dezimale Stunden (localtime) umzuwandeln. In diesem Beispiel ca. 8,5 Stunden. Also die Stunden und Minuten von 0:00 Uhr bis Sonnenaufgang in einer dezimalen Zahl. Da kann ich dann z.B. plus 0,5 für eine halbe Stunde hinzufügen.
In etlichen Beispielen habe ich gesehen, daß es umgekehrt (Dezimal zu Datum/Zeit) recht einfach ist. Vielleicht bin ja auch im Moment einfach nur Blind. Eine einfache Lösung für die Stundenzahl von Tageslicht habe ich mit der SUN2-Integration verwirklicht (Daylight). Erst wollte ich ja nur die Differenz zwischen Sonnenaufgang und -Untergang. Das funktionierte aber nur am Abend, wenn sich beide Zeiten innerhalb des Tages befanden.
Above-horizon scheint wohl nur in der Automatisierung zu funktionieren. Ich habe da keine Stunden herausbekommen.
An dieser Stelle möchte ich auch noch herzlichen Dank für die Arbeit von rany2 an der ha-open-meteo-solar-forecast - Integration sagen.
Für mich hier in Norddeutschland funktioniert es wirklich klasse (5-15%).

Im Apex-Chart sieht es dann folgendermaßen aus:
Der Card-Templater ist da wirklich Klasse. Funktioniert auch in der Swipe-Card.

type: custom:card-templater
card:
  type: custom:apexcharts-card
  experimental:
    color_threshold: true
  cache: true
  update_interval: 115sec
  apex_config:
    chart:
      tickAmount: 10
      height: 240px
    tooltip:
      enabled: false
    legend:
      show: false
  header:
    title: Meteo Solarprognose heute
    show: true
    standard_format: false
    show_states: true
    colorize_states: true
  graph_span_template: |
    "{{state_attr('sensor.home_sun_daylight','today')|round(1)}}h"
  span:
    start: day
    offset_template: >-
      +{{ ((as_timestamp(state_attr('sun.sun','next_rising')) -
      as_timestamp(now().replace(hour=23,minute=59))) / 3600) | round(1) }}h
  now:
    show: true
    color: khaki
    label: ""
  yaxis:
    - id: kwh
      decimals: 0
      apex_config:
        tickAmount: 5
    - id: header_only
      decimals: 1
  series:
    - entity: sensor.meteo_production_today_sum
      yaxis_id: kwh
      type: area
      curve: smooth
      name: Forecast Power
      color: yellow
      color_threshold:
        - value: 100
          color: darkred
        - value: 800
          color: red
        - value: 1800
          color: orange
        - value: 3600
          color: green
        - value: 6400
          color: yellow
      opacity: 0.6
      data_generator: |
        return Object.entries(entity.attributes.watts).map(
          ([key, value]) => [new Date(key).getTime(), value]
        );
      show:
        legend_value: false
        in_header: false
      stroke_width: 0.35
      float_precision: 2
      extend_to: false
      statistics:
        type: mean
        period: 5minute
        align: start
    - entity: sensor.meteo_production_today_sum
      yaxis_id: header_only
      name: Prognose heute
      color: orange
      show:
        legend_value: false
        in_header: raw
        in_chart: false
      unit: "\_\_kWh"

Da ich zwei Dachhälften mit Solarmodulen bestückt habe, habe ich beide Meteo-Solar Einträge zusammengezählt:

##Open-Meteo-Solar Prognose
      - name: "meteo production today sum"
        unique_id: "meteo_production_today_sum"
        unit_of_measurement: "kWh"
        device_class: energy
        state: >
          {% set sensor1 = states('sensor.energy_production_today') |float %}
          {% set sensor2 = states('sensor.energy_production_today_2') |float %}
          {{  ((sensor1 + sensor2)*0.985)|float(0)|round(1) }}
        attributes:
          temp: >-
          watts: >-
            {% set sensor1 = state_attr('sensor.energy_production_today', 'watts') %}
            {% set sensor2 = state_attr('sensor.energy_production_today_2', 'watts') %}
            {% set ns = namespace(output={}) %}
            {% for time, value in sensor1.items() %}
              {% set sum_value = value + sensor2[time] %}
              {% set ns.output = dict({time: sum_value}, **ns.output) %}
            {% endfor %}
            {{ ns.output }}

Das ganze sieht dann so aus:

Sowohl die x-Achse als auch der Offset sollen sich dann dynamisch anpassen, damit ich nicht immer von Hand die Tageslänge anpassen muss.

Vielleicht hat ja jemand eine Idee, wie ich die vorhandenen Templates vereinfachen oder verbessern kann. Und wie ich generell Datum/Zeitformate in Dezimalzahlen umwandeln kann.

mfg
Rainer

Hallo, ich beantworte meine Frage mal selbst. Zumindest funktioniert es so.
Ich habe dazu die Integration “SUN2” geladen.
Damit kann man recht einfach mit Zeitformaten rechnen.

##Stunden von Mitternacht bis Sonnenaufgang - Offset
      - name: "prog mitternacht sonnenaufgang"
        unique_id: "prog_mitternacht_sonnenaufgang"
        state: >
          {% set ns   = as_timestamp(state_attr('sensor.home_sun_rising','today')) -%}
          {% set nr   = as_timestamp(state_attr('sensor.home_sun_solar_midnight','today')) -%}
          {{ (((ns - nr) / (60*60)))|round(2) }}
          
##Stunden zwischen Sonnenaufgang und Sonnenuntergang  - Spanne
      - name: "prog tageslicht"
        unique_id: "prog_tageslicht"
        state: >
          {% set ns   = state_attr('sensor.home_sun_daylight','today') -%}
          {{ (((ns)))|round(2) }}

Die Einträge im APEX-Chart sind bei mir wie folgt:

type: custom:card-templater
card:
  type: custom:apexcharts-card
  experimental:
    color_threshold: true
  cache: true
  update_interval: 115sec
  apex_config:
    chart:
      tickAmount: 10
      height: 240px
    tooltip:
      enabled: false
    legend:
      show: false
  header:
    title: Meteo Solarprognose heute
    show: true
    standard_format: false
    show_states: true
    colorize_states: true
  graph_span_template: |
    "{{(states('sensor.prog_tageslicht')|round(2))}}h"
  span:
    start: day
    offset_template: +{{ (states('sensor.prog_mitternacht_sonnenaufgang')|round(2))}}h

Nach diesen dezimalen Zahlen habe ich gesucht.

mfg
Rainer

Moin,
ich versuche gerade Deine Apex-Charts in meinem HA einzurichten. Habe zusätzlich noch card-templater und sun2 installiert. Verstehe ich das richtig, dass der Code mit sun2 den Code mit sun.sun im ersten Beitrag ersetzt?
Ich bekomme aktuell nur diesen Chart angezeigt:

2024-12-25 12_08_28-Solar – Home Assistant

Der Yaml-Code sieht bei mir so aus (nur 1 Feld):

type: custom:card-templater
card:
  type: custom:apexcharts-card
  experimental:
    color_threshold: true
  cache: true
  update_interval: 115sec
  apex_config:
    chart:
      tickAmount: 10
      height: 240px
    tooltip:
      enabled: false
    legend:
      show: false
  header:
    title: Meteo Solarprognose heute
    show: true
    standard_format: false
    show_states: true
    colorize_states: true
  graph_span_template: |
    "{{(states('sensor.prog_tageslicht')|round(2))}}h"
  span:
    start: day
    offset_template: +{{ (states('sensor.prog_mitternacht_sonnenaufgang')|round(2))}}h
  now:
    show: true
    color: khaki
    label: ""
  yaxis:
    - id: kwh
      decimals: 0
      apex_config:
        tickAmount: 5
    - id: header_only
      decimals: 1
  series:
    - entity: sensor.energy_production_today
      yaxis_id: kwh
      type: area
      curve: smooth
      name: Forecast Power
      color: yellow
      color_threshold:
        - value: 100
          color: darkred
        - value: 800
          color: red
        - value: 1800
          color: orange
        - value: 3600
          color: green
        - value: 6400
          color: yellow
      opacity: 0.6
      data_generator: |
        return Object.entries(entity.attributes.watts).map(
          ([key, value]) => [new Date(key).getTime(), value]
        );
      show:
        legend_value: false
        in_header: false
      stroke_width: 0.35
      float_precision: 2
      extend_to: false
      statistics:
        type: mean
        period: 5minute
        align: start
    - entity: sensor.energy_production_today
      yaxis_id: header_only
      name: Prognose heute
      color: orange
      show:
        legend_value: false
        in_header: raw
        in_chart: false
      unit: "\_\_kWh"

Habe ich da noch was übersehen? Hätte gerne auch die drei Charts bei mir eingebunden; die finde ich sehr gut.

Hallo Ottokar,
ja ich habe sun in SUN2 geändert. Dein Chart-Code funktioniert bei mir einwandfrei. Die von Dir gezeigte Grafik habe ich auch auf einem anderen Rechner, allerdings nur 15-20 Sekunden, dann ist die Grafik richtig. Der Unterschied zu den beiden Rechnern ist:
Die Templater-Card ist wohl etwas Leistungshungriger.
Mein Rechner ist ein Zotac N100 Passiv-PC mit 8GB RAM, der andere ist eine virtueller PC (Hyper-V) mit nur einem Kern. Wenn es noch langsamer wird (z.B. Pi3 oder weniger) könnte das der Grund sein? Ich habe mal bei dem virtuellen PC folgenden Code verwendet:

  graph_span: 10h
  span:
    start: day
    offset: +7h

Damit gibt es keine Verzögerung. Da muss man halt jeden Monat einmal umstellen.
Alternativ könnte man mit der config-template-card arbeiten, die ist wohl etwas schlanker.
mfg
Rainer Pache

Nachtrag:
Hallo Ottokar,
versuch doch mal diesen Code im Apex-Chart:
Dazu musst Du aber die config-template-card integrieren. Lädt um ein vielfaches schneller.

type: custom:config-template-card
variables:
  span: (states['sensor.prog_tageslicht'].state)
  offset: (states['sensor.prog_mitternacht_sonnenaufgang'].state)
entities:
  - sensor.prog_tageslicht
  - sensor.prog_mitternacht_sonnenaufgang
card:
  type: custom:apexcharts-card
  experimental:
    color_threshold: true
  cache: true
  update_interval: 115sec
  apex_config:
    chart:
      tickAmount: 10
      height: 240px
    tooltip:
      enabled: false
    legend:
      show: false
  header:
    title: Meteo Solarprognose heute
    show: true
    standard_format: false
    show_states: true
    colorize_states: true
  graph_span: ${span}
  span:
    start: day
    offset: ${offset}
  now:
    show: true
    color: khaki
    label: ""
  yaxis:
    - id: kwh
      decimals: 0
      apex_config:
        tickAmount: 5
    - id: header_only
      decimals: 1
  series:
    - entity: sensor.energy_production_today
      yaxis_id: kwh
      type: area
      curve: smooth
      name: Forecast Power
      color: yellow
      color_threshold:
        - value: 100
          color: darkred
        - value: 800
          color: red
        - value: 1800
          color: orange
        - value: 3600
          color: green
        - value: 6400
          color: yellow
      opacity: 0.6
      data_generator: |
        return Object.entries(entity.attributes.watts).map(
          ([key, value]) => [new Date(key).getTime(), value]
        );
      show:
        legend_value: false
        in_header: false
      stroke_width: 0.35
      float_precision: 2
      extend_to: false
      statistics:
        type: mean
        period: 5minute
        align: start
    - entity: sensor.energy_production_today
      yaxis_id: header_only
      name: Prognose heute
      color: orange
      show:
        legend_value: false
        in_header: raw
        in_chart: false
      unit: "\_\_kWh"

Du mußt dann aber auch die Templates ändern (+ und h anhängen bwz vorhängen). Das wäre wahrscheinlich auch innerhalb der Variablen lösbar, habe aber auf die Schnelle nichts gefunden.

##Stunden von Mitternacht bis Sonnenaufgang - Offset
      - name: "prog mitternacht sonnenaufgang"
        unique_id: "prog_mitternacht_sonnenaufgang"
        state: >
          {% set ns   = as_timestamp(state_attr('sensor.home_sun_rising','today')) -%}
          {% set mid  = as_timestamp(today_at(0))|float(0)  -%}
          +{{ (((ns - mid) / (3600)))|round(1) }}h
          
##Stunden zwischen Sonnenaufgang und Sonnenuntergang  - Spanne
      - name: "prog tageslicht"
        unique_id: "prog_tageslicht"
        state: >
          {% set ns   = state_attr('sensor.home_sun_daylight','today') -%}
          {{ (((ns)))|round(2) }}h

Ich habe mal solar-midnight in 0.00 Uhr geändert.
Welche der beiden Template-Lösungen nun wirklich besser oder schlechter ist kann ich nicht sagen. Vielleicht gibt es ja auch eine völlig andere Lösung.
Du kannst ja mal berichten.
mfg
Rainer

:crayon:by HarryP: Zusammenführung Doppelpost (bitte “bearbeiten” Funktion nutzen)

Guten Abend Rainer,
mit der config-template-card habe ich es jetzt fast hinbekommen. Danke für die Tipps! :+1:
Es sind noch kleinere Einstellungen notwendig, die ich noch nicht gefunden habe.



Die Werte der y-Achse bekomme ich nicht richtig angepasst. Der Wert der Tagesprognose hat sich mehrfach geändert. :thinking:
Den Wert des tatsächlichen Ertrages wird auch nicht mit angezeigt.
Bei der Prognose für morgen wird, außer im Header, nichts angezeigt.

Hallo Ottokar,
das Diagramm für morgen hat vielleicht keinen Offset.

  series:
    - entity: sensor.meteo_production_tomorrow_sum
      yaxis_id: kwh
      offset: +24h
      type: area

Die Dezimalstelle bei der Leistung bekomme ich auch nicht weg. Oder willst Du in der Y-Achse fest Werte. Das funktioniert mit min und max.

t  yaxis:
    - id: kwh
      decimals: 0
      apex_config:
        tickAmount: 5
      min: 0
      max: 3000

Wenn Du ein paar Minuten in der X-Achse verschieben willst, einfach den die Stunden in Dezimal-Zahl addieren (hier 0.5 = 30 Minuten):

##Stunden von Mitternacht bis Sonnenaufgang - Offset
      - name: "prog mitternacht sonnenaufgang"
        unique_id: "prog_mitternacht_sonnenaufgang"
        state: >
          {% set ns   = as_timestamp(state_attr('sensor.home_sun_rising','today')) -%}
          {% set mid  = as_timestamp(today_at(0))|float(0)  -%}
          +{{ (((ns - mid) / (3600)+0.5))|round(1) }}h

Hier nochmal mein jetziger Apex-Chart-Code:

type: custom:config-template-card
variables:
  span: (states['sensor.prog_tageslicht'].state)
  offset: (states['sensor.prog_mitternacht_sonnenaufgang'].state)
entities:
  - sensor.prog_tageslicht
  - sensor.prog_mitternacht_sonnenaufgang
card:
  type: custom:apexcharts-card
  experimental:
    color_threshold: true
  cache: true
  update_interval: 115sec
  apex_config:
    chart:
      tickAmount: 10
      height: 240px
    tooltip:
      enabled: false
    legend:
      show: false
  header:
    title: Meteo Solarprognose heute
    show: true
    standard_format: false
    show_states: true
    colorize_states: true
  graph_span: ${span}
  span:
    start: day
    offset: ${offset}
  now:
    show: true
    color: khaki
    label: ""
  yaxis:
    - id: kwh
      decimals: 0
      apex_config:
        tickAmount: 5
    - id: header_only
      decimals: 1
  series:
    - entity: sensor.watt_solar_sum_tag
      yaxis_id: kwh
      name: Solar Power
      type: line
      float_precision: 1
      color: lime
      opacity: 0.6
      stroke_width: 1.5
      unit: "\_\_W"
      extend_to: now
      show:
        legend_value: false
        in_header: false
      group_by:
        func: median
        duration: 15m
    - entity: sensor.meteo_production_today_sum
      offset: "-7.5m"
      yaxis_id: kwh
      type: area
      curve: smooth
      name: Forecast Power
      color: yellow
      color_threshold:
        - value: 100
          color: darkred
        - value: 800
          color: red
        - value: 1800
          color: orange
        - value: 3600
          color: green
        - value: 6400
          color: yellow
      opacity: 0.6
      data_generator: |
        return Object.entries(entity.attributes.watts).map(
          ([key, value]) => [new Date(key).getTime(), value]
        );
      show:
        legend_value: false
        in_header: false
      stroke_width: 0.35
      float_precision: 0
      extend_to: false
      statistics:
        type: mean
        period: 5minute
        align: start
    - entity: sensor.meteo_production_today_sum
      yaxis_id: header_only
      name: Prognose heute
      color: orange
      show:
        legend_value: false
        in_header: raw
        in_chart: false
      unit: "\_\_kWh"
      float_precision: 1
    - entity: sensor.meteo_production_today_remaining_sum
      yaxis_id: header_only
      name: Heute verbleibend
      color: lightgreen
      show:
        legend_value: true
        in_header: raw
        in_chart: false
    - entity: sensor.meteo_production_next_hour
      yaxis_id: header_only
      name: nächste Stunde
      color: green
      show:
        legend_value: false
        in_header: raw
        in_chart: false
      unit: "\_\_kWh"
    - entity: sensor.gesamt_pv_tag
      yaxis_id: header_only
      name: Ertrag heute
      color: green
      show:
        legend_value: true
        in_header: raw
        in_chart: false

Der tatsächliche Ertrag wird doch bei Dir oben rechts angezeigt.
Wir hatten hier in Lübeck heute nur 1,4 Kw Solarertrag. 8 Felder Südost, 20 Felder Nordwest. Sieht bei Dir irgendwie freundlicher aus.
Hast Du eigentlich mehrere Solarfelder? Summierst Du die?
mfg
Rainer

Jo, sieht besser aus. :+1:

War davon ausgegangen, dass die grüne Linie in Deiner Karte den tatsächlichen Ertrag als Vergleich zur Prognose anzeigt.

Nein, nur 14 SSW.

Ich wollte der Prognose heute morgen nicht glauben; ab Mittag zog dann der Nebel davon. Auf alle Fälle kein Vergleich zur Forecast Solar Prognose. Die lautete 1,4 kWh. :face_with_raised_eyebrow:

Hi,
die grüne Linie ist die momentane Leistung in Watt nicht KW-Ertrag.
Deswegen auch eine 15minütige Statistik.

  series:
    - entity: sensor.watt_solar_sum_tag
      yaxis_id: kwh
      name: Solar Power
      type: line
      float_precision: 1
      color: lime
      opacity: 0.6
      stroke_width: 1.5
      unit: "\_\_W"
      extend_to: now
      show:
        legend_value: false
        in_header: false
      group_by:
        func: median
        duration: 15m

Min/max habe ich wieder verworfen, da ich ja kann wieder regelmäßig nachjustieren müsste. So aber gibt die grüne Linie die Scala vor.
Mit Forecast bin ich auch nicht so wirklich froh gewesen. Ein Kumpel von mir in Bochum hat fast exakte Werte von Forecast. So unterschiedlich kann das sein. Da ich meine Akku-Ladung über Tibber und das Warmwasser in Abhängigkeit der Solar-Prognose steuere habe ich die Tagesprognosen von OpenMeteo, Solcast (da hättest Du 10 Abfragen pro Tag frei) und Solarprognose.de (der Betreiber ist sehr nett aber auch richtig krank und kann deswegen da auch nicht weiterprogrammieren) gemittelt und fahre ganz gut damit. Wenn man nur die nächsten 2-3 Tage schön grafisch sehen will ist das wohl nicht nötig.
mfg
Rainer

Die heutige Prognose war fast eine Punktlandung:

Die Prognose stand heute morgen zwischenzeitlich auf 13.2 kWh.

Ab ca, 14 Uhr habe ich die grüne Linie mit der aktuellen PV-Leistung hinbekommen. Sie wird allerdings erst angezeigt, wenn man eine andere Karte auswählt und dann wieder zurück wechselt.

Hast Du die Prognose von Solarprognose.de auch in HA eingebunden? Hatte es heute Mittag mal versucht. Mit dem Yaml-Code wurde dann in kürzester Zeit die Zahl der maximal erlaubten API-Abrufe (20) überschritten:

sensor:
  - platform: rest
    name: "Solarprognose"
    resource: "https://www.solarprognose.de/web/solarprediction/api/v1?access-token=xxxxxxxxxxxxxxxx&type=daily"
    scan_interval: 14400
    value_template: >
      {% set data = value | regex_findall('<data>.*?</data>', multiline=True) %}
      {% set first_item = data[0] | regex_findall('<item>\\s*<item>.*?</item>\\s*<item>(.*?)</item>\\s*</item>', multiline=True) %}
      {{ first_item[0] if first_item else '0' }}
    headers:
      Content-Type: application/xml
    icon: mdi:solar-power
    unit_of_measurement: "kWh"

Hallo @ottokar,
ist ja prima, das du immer näher rankommst.

Sie wird allerdings erst angezeigt, wenn man eine andere Karte auswählt und dann wieder zurück wechselt

Nimm mal den Cache=true Eintrag aus dem Apex-Chart raus, hilft vielleicht.
Hardware?
Mit welchem Browser arbeitest Du. Für mich funktioniert Chrome am besten. Allerdings muss ich den Cache hin und wieder leeren. Funktioniert durch drücken der F12-Taste, dann 3 Sekunden auf den Rundpfeil für das Aktualisieren gedrückt halten und dann den Cache leeren. Und schon öffnen alle Fenster ganz geschmeidig.

Ich habe bei solarprognose.de das große Paket gebucht, weil ich eine Wochenaufstellung der Prognosen darstelle. Ich habe da mal mit dem Entwickler gesprochen. Solange er nicht weiterentwickelt (kann er wohl wegen der Krankheit nicht) will er auch kein Geld für die einzelnen Tarife. Ich habe darum eine Kleinigkeit gespendet. Ich versuche auch, zu unterschiedlichen Zeiten abzuholen. Mein Rest-Code sieht aber etwas anders aus:

rest:
  - scan_interval: 24449
    resource: https://www.solarprognose.de/web/solarprediction/api/v1?access-token=677b56cb0f4271xxxxxxxxx769f&project=rainer@xxx&type=daily&_format=json&algorithm=mosmix&day=0
    sensor:
      - name: "Solarprognose T0 = heute"
        value_template: "{{ ((value_json.data).values() | list) [0] |round(1)}}"
        icon: mdi:solar-power
        state_class: "measurement"
        unit_of_measurement: "kwh"
  - scan_interval: 24446
    resource: https://www.solarprognose.de/web/solarprediction/api/v1?access-token=677b56cbxxxxxxxxxx480e91b725769f&project=rainer@xxx&type=daily&_format=json&algorithm=mosmix&day=1
    sensor:
      - name: "Solarprognose T1 = morgen"
        value_template: "{{ ((value_json.data).values() | list)[0] |round(1) }}"
        icon: mdi:solar-power
        state_class: "measurement"
        unit_of_measurement: "kwh"

usw. für weitere 5 Tage.
Ich habe das nur in HA, um ein Mittel zu errechnen. Sonst mache ich nichts mit der Vorhersage. Mein Solarertrag war heute bei 2KW, Open-Meteo bei 2,2 KW und Solcast auch bei glatt 2 KW. Im Allgemeinen ist Open-Meteo immer näher dran.
So sieht meine Wochendarstellung aus. Obere Leiste = Open-Meteo, untere Leiste = das Mittel aus 3 Prognosen (ist mit der template-entity-row -Card gemacht):

mfg
Rainer

Hallo, finde das recht interessant, was ihr hier gemacht habe. Allerdings geht es mir wie Otokar zu begin:

https://community.simon42.com/uploads/default/original/3X/0/9/0940320eda212a84373dbd4d8c710a1222f99869.png

Wärt ihr so nett und veröffentlicht mal den aktuellen Code mit der Prognose, dem Verbleibenden Ertrag und der nächsten Stunde? Irgendwie drehe ich mich im Kreis und komme einfach nicht weiter.

Vielen Dank!!

VG!

Hallo @lehen02
hier ist mal mein aktueller Apex-Chart-Code:

type: custom:config-template-card
variables:
  span: (states['sensor.prog_tageslicht'].state)
  offset: (states['sensor.prog_mitternacht_sonnenaufgang'].state)
entities:
  - sensor.prog_tageslicht
  - sensor.prog_mitternacht_sonnenaufgang
card:
  type: custom:apexcharts-card
  experimental:
    color_threshold: true
  update_interval: 115sec
  apex_config:
    chart:
      tickAmount: 10
      height: 240px
    tooltip:
      enabled: false
    legend:
      show: false
  header:
    title: Meteo Solarprognose heute
    show: true
    standard_format: false
    show_states: true
    colorize_states: true
  graph_span: ${span}
  span:
    start: day
    offset: ${offset}
  now:
    show: true
    color: khaki
    label: ""
  yaxis:
    - id: kwh
      decimals: 0
      apex_config:
        tickAmount: 5
    - id: header_only
      decimals: 1
  series:
    - entity: sensor.watt_solar_sum_tag
      yaxis_id: kwh
      name: Solar Power
      type: line
      float_precision: 1
      color: lime
      opacity: 0.6
      stroke_width: 1.5
      unit: "\_\_W"
      extend_to: now
      show:
        legend_value: false
        in_header: false
      group_by:
        func: median
        duration: 15m
    - entity: sensor.meteo_production_today_sum
      yaxis_id: kwh
      type: area
      curve: smooth
      name: Forecast Power
      color: yellow
      color_threshold:
        - value: 100
          color: darkred
        - value: 800
          color: red
        - value: 1800
          color: orange
        - value: 3600
          color: green
        - value: 6400
          color: yellow
      opacity: 0.6
      data_generator: |
        return Object.entries(entity.attributes.watts).map(
          ([key, value]) => [new Date(key).getTime(), value]
        );
      show:
        legend_value: false
        in_header: false
      stroke_width: 0.35
      float_precision: 0
      extend_to: false
      statistics:
        type: mean
        period: 5minute
        align: start
    - entity: sensor.meteo_production_today_sum
      yaxis_id: header_only
      name: Prognose heute
      color: orange
      show:
        legend_value: false
        in_header: raw
        in_chart: false
      unit: "\_\_kWh"
      float_precision: 1
    - entity: sensor.meteo_production_today_remaining_sum
      yaxis_id: header_only
      name: Heute verbleibend
      color: lightgreen
      show:
        legend_value: true
        in_header: raw
        in_chart: false
    - entity: sensor.meteo_production_next_hour
      yaxis_id: header_only
      name: nächste Stunde
      color: green
      show:
        legend_value: false
        in_header: raw
        in_chart: false
      unit: "\_\_kWh"
    - entity: sensor.gesamt_pv_tag
      yaxis_id: header_only
      name: Ertrag heute
      color: green
      show:
        legend_value: true
        in_header: raw
        in_chart: false

Ich rechne allerdings 2 Dächer zusammen, bei nur einem Solarfeld müßtest Du bei meinem Code noch das _sum wegnehmen.
Ich weiß nicht, wie Ottokar seinen schmalen Streifen zu einer richtigen Grafik gemacht hat. Ich hatte das Problem ja nicht. Wir sind allerdings vom card-templater weggegangen und zur config-template-card gewechselt.
Meine Vermutung war ja, das die Hardware nicht schnell genug war.
Kann sein, daß das die Lösung war. Aber da wird Dir Ottokar sicherlich Auskunft geben, seit wann seine Grafik funktionierte.
Vielleicht noch ein Tipp:
Versuch mal anstelle der Variablen einfach diese Einträge:

  graph_span: 10h
  span:
    start: day
    offset: +7h

Dann weißt Du, ob der Fehler an den Variablen liegt.
mfg
Rainer

Guten Morgen,
es hatte bei mir mit

graph_span: 10h
  span:
    start: day
    offset: +7h

funktioniert, bin dann aber zu der config-template-card gewechselt.

Meine Yaml-Codes sehen aktuell so aus:

Heute:

type: custom:config-template-card
variables:
  span: (states['sensor.prog_tageslicht'].state)
  offset: (states['sensor.prog_mitternacht_sonnenaufgang'].state)
entities:
  - sensor.prog_tageslicht
  - sensor.prog_mitternacht_sonnenaufgang
card:
  type: custom:apexcharts-card
  experimental:
    color_threshold: true
  update_interval: 115sec
  apex_config:
    chart:
      tickAmount: 10
      height: 240px
    tooltip:
      enabled: false
    legend:
      show: false
  header:
    show: true
    standard_format: false
    show_states: true
    colorize_states: true
  graph_span: ${span}
  span:
    start: day
    offset: ${offset}
  now:
    show: true
    color: khaki
    label: ""
  yaxis:
    - id: kwh
      decimals: 0
      apex_config:
        tickAmount: 5
      min: 0
      max: 3000
    - id: header_only
      decimals: 1
  series:
    - entity: sensor.pv1inwatt
      yaxis_id: kwh
      name: Solar Power
      type: line
      float_precision: 1
      color: lime
      opacity: 0.6
      stroke_width: 1.5
      unit: "\_\_W"
      extend_to: now
      show:
        legend_value: true
        in_header: false
      group_by:
        func: median
        duration: 15m
    - entity: sensor.energy_production_today
      yaxis_id: kwh
      type: area
      curve: smooth
      name: Forecast Power
      color: yellow
      color_threshold:
        - value: 100
          color: darkred
        - value: 800
          color: red
        - value: 1800
          color: orange
        - value: 3600
          color: green
        - value: 6400
          color: yellow
      opacity: 0.6
      data_generator: |
        return Object.entries(entity.attributes.watts).map(
          ([key, value]) => [new Date(key).getTime(), value]
        );
      show:
        legend_value: false
        in_header: false
      stroke_width: 0.35
      float_precision: 2
      extend_to: false
      statistics:
        type: mean
        period: 5minute
        align: start
    - entity: sensor.load_energy_today
      yaxis_id: kwh
      type: area
      curve: smooth
      name: PV Power
      color: green
      color_threshold:
        - value: 100
          color: darkred
        - value: 800
          color: red
        - value: 1800
          color: orange
        - value: 3600
          color: green
        - value: 6400
          color: yellow
      opacity: 0.6
      data_generator: |
        return Object.entries(entity.attributes.watts).map(
          ([key, value]) => [new Date(key).getTime(), value]
        );
      show:
        legend_value: false
        in_header: false
      stroke_width: 0.35
      float_precision: 2
      extend_to: false
      statistics:
        type: mean
        period: 5minute
        align: start
    - entity: sensor.energy_production_today
      yaxis_id: header_only
      name: Prognose heute
      color: orange
      show:
        legend_value: false
        in_header: raw
        in_chart: false
      unit: "\_\_kWh"
    - entity: sensor.energy_production_today_remaining
      yaxis_id: header_only
      name: Heute verbleibend
      color: green
      show:
        legend_value: false
        in_header: raw
        in_chart: false
      unit: "\_\_kWh"
    - entity: sensor.energy_next_hour
      yaxis_id: header_only
      name: nächste Stunde
      color: green
      show:
        legend_value: false
        in_header: raw
        in_chart: false
      unit: "\_\_kWh"
    - entity: sensor.solar_energy_today
      yaxis_id: header_only
      name: Ertrag heute
      color: green
      show:
        legend_value: false
        in_header: raw
        in_chart: false
      unit: "\_\_kWh"

Die Variablen prog_tageslicht und prog_mitternacht_sonnenaufgang habe ich jeweils als Helfer > Template > Sensor > (Zustandstemplate) angelegt:

Code für tageslicht:

{% set ns   = state_attr('sensor.home_sun_daylight','today') -%}
          {{ (((ns)))|round(2) }}h

Code für mitternacht_sonnenaufgang:

{% set ns   = as_timestamp(state_attr('sensor.home_sun_rising','today')) -%}
          {% set mid  = as_timestamp(today_at(0))|float(0)  -%}
          +{{ (((ns - mid) / (3600)))|round(1) }}h

Guten Morgen!

Vielen Dank für eure Unterstützung! :grinning:

Jetzt klappt es soweit mit den Daten. Einzig die Relationen in der mittleren Karte passen noch nicht ganz. Habt ihr da noch ein Tipp für mich?

Hallo @lehen02
nimm mal die min max Einträge raus.
Du scheinst 4 Solarfelder zu haben, die kannst Du auch zusammenrechnen.

mfg
Rainer Pache

Hallo Rainer,

daran lag es. Danke!
Die 4 Panels habe ich schon zusammengerechnet. Muss jetzt die nächsten Tage mich mal mit den einzelnen Prognosewerten beschäftigen, da alle 4 Panels eine unterschiedliche Ausrichtung haben, wird das etwas dauern. Ost/West und dann noch unterschiedliche Neigung…

Aber zumindest hstimmt schon mal die Optik :slight_smile:

Nachtrag:
Doch noch eine Frage :innocent:
Wie habt ihr das mit graph_span und span für die Prognose Morgen/Übermorgen gemacht? Da hänge ich gerade noch.

VG!

:crayon:by HarryP: Zusammenführung Doppelpost (bitte “bearbeiten” Funktion nutzen)

Hallo @lehen02
Span und Offset habe ich nicht großartig auf morgen oder übermorgen angepasst. Die paar Minuten Unterschied sind für mich nicht wichtig. Ich habe einfach für Span(ne) und Offset eine halbe Stunde hinzugefügt bzw. verkürzt, damit auch die Dämmerung mit drin ist. Kann man nach eigenem Gusto ändern.

##Stunden von Mitternacht bis Sonnenaufgang - Offset
      - name: "prog mitternacht sonnenaufgang"
        unique_id: "prog_mitternacht_sonnenaufgang"
        state: >
          {% set ns   = as_timestamp(state_attr('sensor.home_sun_rising','today')) -%}
          {% set mid  = as_timestamp(today_at(0))|float(0)  -%}
          +{{ (((ns - mid) / (3600)-0.5))|round(1) }}h
          
##Stunden zwischen Sonnenaufgang und Sonnenuntergang  - Spanne
      - name: "prog tageslicht"
        unique_id: "prog_tageslicht"
        state: >
          {% set ns   = state_attr('sensor.home_sun_daylight','today') -%}
          {{ (((ns)+0.5))|round(2) }}h

Für Morgen und Übermorgen muss man natürlich bei mehreren Panelflächen auch die Tage entsprechend zusammenzählen. Ich habe mich dabei für das Attribut “watts” (ist dann viertelstündlich, bei “wh” wäre es stündlich)
entschieden. Sieht bei mir so aus:

##Open-Meteo-Solar Prognose
      - name: "meteo production today sum"
        unique_id: "meteo_production_today_sum"
        unit_of_measurement: "kWh"
        device_class: energy
        state: >
          {% set sensor1 = states('sensor.energy_production_today') |float -%}
          {% set sensor2 = states('sensor.energy_production_today_2') |float -%}
          {{  ((sensor1 + sensor2)*1)|float(0)|round(1) }}
        attributes:
          temp: >-
          watts: >-
            {% set sensor1 = state_attr('sensor.energy_production_today', 'watts') -%}
            {% set sensor2 = state_attr('sensor.energy_production_today_2', 'watts') -%}
            {% set ns = namespace(output={}) -%}
            {% for time, value in sensor1.items() -%}
              {% set sum_value = value + sensor2[time] %}
              {% set ns.output = dict({time: sum_value}, **ns.output) %}
            {% endfor %}
            {{ ns.output }}

      - name: "meteo production tomorrow sum"
        unique_id: "meteo_production_tomorrow_sum"
        unit_of_measurement: "kWh"
        device_class: energy
        state: >
          {% set sensor1 = states('sensor.energy_production_tomorrow') |float -%}
          {% set sensor2 = states('sensor.energy_production_tomorrow_2') |float -%}
          {{ ((sensor1 + sensor2)*1)|float(0)|round(1) }}
        attributes:
          temp: >-
          watts: >-
            {% set sensor1 = state_attr('sensor.energy_production_tomorrow', 'watts') %}
            {% set sensor2 = state_attr('sensor.energy_production_tomorrow_2', 'watts') %}
            {% set ns = namespace(output={}) -%}
            {% for time, value in sensor1.items() %}
              {% set sum_value = value + sensor2[time] -%}
              {% set ns.output = dict({time: sum_value}, **ns.output) -%}
            {% endfor %}
            {{ ns.output }}

      - name: "meteo production ubermorgen sum"
        unique_id: "meteo_production_ubermorgen_sum"
        unit_of_measurement: "kWh"
        device_class: energy
        state: >
          {% set sensor1 = states('sensor.energy_production_d2') |float -%}
          {% set sensor2 = states('sensor.energy_production_d2_2') |float -%}
          {{ ((sensor1 + sensor2)*1)|float(0)|round(1) }}
        attributes:
          temp: >-
          watts: >-
            {% set sensor1 = state_attr('sensor.energy_production_d2', 'watts') -%}
            {% set sensor2 = state_attr('sensor.energy_production_d2_2', 'watts') -%}
            {% set ns = namespace(output={}) %}
            {% for time, value in sensor1.items() %}
              {% set sum_value = value + sensor2[time] %}
              {% set ns.output = dict({time: sum_value}, **ns.output) %}
            {% endfor %}
            {{ ns.output }}

Für Morgen bzw. Übermorgen ist natürlich der Offset von +24h oder +48h
wichtig:

  series:
    - entity: sensor.meteo_production_tomorrow_sum
      yaxis_id: kwh
      offset: +24h
      type: area

3 Tage als grafische Vorschau reichen mir.
Kannst ja mal Deine komplette Grafik zeigen.
mfg
Rainer

DANKE! Das war zu naheliegend. :grinning: Jetzt haut alles hin!

Hier ist mein Beispiel für die Prognose Übermorgen:

2024-12-28 15_05_09-Solar – Home Assistant

type: custom:config-template-card
variables:
  span: (states['sensor.prog_tageslicht'].state)
  offset: (states['sensor.prog_mitternacht_sonnenaufgang'].state)
entities:
  - sensor.prog_tageslicht
  - sensor.prog_mitternacht_sonnenaufgang
card:
  type: custom:apexcharts-card
  experimental:
    color_threshold: true
  cache: true
  update_interval: 115sec
  apex_config:
    chart:
      tickAmount: 10
      height: 240px
    tooltip:
      enabled: false
    legend:
      show: false
  header:
    show: true
    standard_format: false
    show_states: true
    colorize_states: true
  graph_span: ${span}
  span:
    start: day
    offset: ${offset}
  yaxis:
    - id: kwh
      decimals: 0
      apex_config:
        tickAmount: 5
    - id: header_only
      decimals: 1
  series:
    - entity: sensor.energy_production_d2
      yaxis_id: kwh
      offset: +48h
      type: area
      curve: smooth
      name: Forecast Power
      color: yellow
      color_threshold:
        - value: 100
          color: red
        - value: 800
          color: green
        - value: 1800
          color: orange
        - value: 3600
          color: yellow
      opacity: 0.6
      data_generator: |
        return Object.entries(entity.attributes.watts).map(
          ([key, value]) => [new Date(key).getTime(), value]
        );
      show:
        legend_value: false
        in_header: false
      stroke_width: 0.35
      float_precision: 2
      extend_to: false
      statistics:
        type: mean
        period: 5minute
        align: start
    - entity: sensor.energy_production_d2
      yaxis_id: header_only
      name: übermorgen
      color: orange
      show:
        legend_value: false
        in_header: raw
        in_chart: false
      unit: "\_\_kWh"

Teste hier noch ohne min/max in der y-Achse, die sich dann wohl automatisch nach Wertgröße anpasst…

@rapahl
Auch ich möchte mich an dieser Stelle herzlich für Deine großartige Unterstützung und das Teilen des Codes bedanken! :+1:

Interessant wie nah die Prognose von Open-Meteo Solar Forecast jetzt einige Tage war. Heutige Prognose lag bei 0,6 kWh , tatsächlicher Ertrag 0,9 kWh. Forecast Solar lag heute bei 1,4 kWh, Solarprognose.de Mosmix bei 2,5 kWh und own-v1 bei 8,5 kWh.
Zur Ehrenrettung von Forecast Solar: Nach meiner Korrektur des Azimut-Wertes liegt die Prognose jetzt nicht mehr so krass daneben. :wink:

Hallo @rapahl
Ich habe für den Abruf der Prognosen von Solarprognose per API bei den Entitäten auch Intervalle angegeben. Der Abruf erfolgt jedoch nur sporadisch, bzw. nur, wenn ich die HA-Konfiguration neu lade. Ist hier vielleicht noch eine Automatisierung erforderlich, die den Abruf auslöst?