Open-Meteo Solar Forecast

No offense, but perhaps others can easily help me out without effort and myself could be sitting hours with trial and error. I thought it was the purpose of a forum to help each other, maybe I know something that another user does not know and can help him, too. And I did already in other cases.

As I cannot see the result of this code-addition directly I may never know if it is working or not.

I can only guess: is this the right solution for a 3rd sensor?

{% set sensor1 = state_attr('sensor.energy_production_today_2', 'watts') %}
{% set sensor2 = state_attr('sensor.energy_production_today_3', 'watts') %}
{% set sensor3 = state_attr('sensor.energy_production_today_4', 'watts') %}
{% set ns = namespace(output={}) %}

{% for time, value in sensor1.items() %}
    {% set ns.output = dict({time: value}, **ns.output) %}
{% endfor %}

{% for time, value in sensor2.items() %}
    {% if time in ns.output %}
        {% set ns.output = dict({time: ns.output[time] + value}, **ns.output) %}
    {% else %}
        {% set ns.output = dict({time: value}, **ns.output) %}
    {% endif %}
{% endfor %}

{% for time, value in sensor3.items() %}
    {% if time in ns.output %}
        {% set ns.output = dict({time: ns.output[time] + value}, **ns.output) %}
    {% else %}
        {% set ns.output = dict({time: value}, **ns.output) %}
    {% endif %}
{% endfor %}
{{ ns.output }}

But there is a big difference between
“Please do this for me” or I tried this and it doesn’t work, I have a question. You have to show initiative or maybe it’s just the wrong system for you

Just letting other people do the work, I don’t think that’s the idea for a forum.

I think it is silly to modify a piece of code without having a clue just to present some kind of “own work”. To modify the code as I did I just had to copy and paste twice and change two numbers. That is not my understanding of “work”. If my addition of another sensor was right it was mere luck. Anybody else could have done that in a few seconds.
In the time you criticized me you could have done that a few times probably if this was the solution.
The problem for me is, that I do not know if my guess was right as I do not know how to confirm this either. The code is working so far even without this part.

By the way I did not say “please do this for me”, I just mentioned that I do not know how to add more sensors. If anything I just asked for a hint or an explanation.

@P1t try this

{% set sensor1 = state_attr('sensor.energy_production_today_2', 'watts') %}
{% set sensor2 = state_attr('sensor.energy_production_today_3', 'watts') %}
{% set sensor3 = state_attr('sensor.energy_production_today_4', 'watts') %}
{% set sensor4 = state_attr('sensor.energy_production_today_5', 'watts') %}

{% set ns = namespace(output={}) %}

{% for time, value in sensor1.items() %}
  {% set sum_value = value %}
  {% if time in sensor2 %}
    {% set sum_value = sum_value + sensor2[time] %}
  {% endif %}
  {% if time in sensor3 %}
    {% set sum_value = sum_value + sensor3[time] %}
  {% endif %}
  {% if time in sensor4 %}
    {% set sum_value = sum_value + sensor4[time] %}
  {% endif %}
  {% set ns.output = dict(ns.output, **{time: sum_value}) %}
{% endfor %}

{% for time, value in sensor2.items() %}
  {% if time not in sensor1 %}
    {% set sum_value = value %}
    {% if time in sensor3 %}
      {% set sum_value = sum_value + sensor3[time] %}
    {% endif %}
    {% if time in sensor4 %}
      {% set sum_value = sum_value + sensor4[time] %}
    {% endif %}
    {% set ns.output = dict(ns.output, **{time: sum_value}) %}
  {% endif %}
{% endfor %}

{% for time, value in sensor3.items() %}
  {% if time not in sensor1 and time not in sensor2 %}
    {% set sum_value = value %}
    {% if time in sensor4 %}
      {% set sum_value = sum_value + sensor4[time] %}
    {% endif %}
    {% set ns.output = dict(ns.output, **{time: sum_value}) %}
  {% endif %}
{% endfor %}

{% for time, value in sensor4.items() %}
  {% if time not in sensor1 and time not in sensor2 and time not in sensor3 %}
    {% set ns.output = dict(ns.output, **{time: value}) %}
  {% endif %}
{% endfor %}

{{ ns.output }}

2 Likes

I noticed a reoccurring pattern in the last couple of days: The integration overestimates for the next day, at least 10kWh or more.

The reason: It wildly overestimates in the morning.

Today, for example, it estimated that we’ll already have had a solar yield of 15kWh at only 7.30am. In reality we didn’t even have 1kWh yet. The sun only came out 41 minutes ago…

If I expose the raw variables that generate the prediction (temp, wind speed, irradiance, pressure, etc) in the diagnostics would you be willing to share it with me? Right now this is unactionable for me as I don’t have such an issue and cannot debug it.

At any rate, for it to be so wildly off do you think that all the parameters are correct?

2 Likes

@slipx06

Thank you, I will try but I do not know how to confirm that this addition is working correctly because I had no issues with the original code.

Kind regards

Hi all, I’m trying to replace my Solcast integration with this and while the data looks fine, I’m struggling to work out how to extract the half-hourly forecasts for my apexcharts-card graph. Here’s the code I’m using currently for Solcast:

data_generator: |
  var today = entity.attributes.detailedForecast.map((start, index) => {
    return [new Date(start["period_start"]).getTime(), entity.attributes.detailedForecast[index]["pv_estimate"]];
  });
  var data = today
  return data;

Obviously this integration doesn’t have a detailedForecast section in the forecast attributes, so how do I extract the correct data for the graph?

check here, or on github.
here it is my code:

type: custom:apexcharts-card
apex_config:
  chart:
    height: 350px
all_series_config:
  unit: ' kWh'
header:
  title: Solar forecast
  show: true
  standard_format: true
  show_states: true
  colorize_states: true
graph_span: 1d
span:
  start: day
  offset: '-0h'
now:
  show: true
  label: Now
  color: red
yaxis:
  - id: kwh
    min: 0
    apex_config:
      tickAmount: 4
  - id: header_only
    show: false
series:
  - entity: sensor.inverter_active_power
    name: Actual Power
    type: area
    float_precision: 1
    color: '#ff9800'
    opacity: 0.5
    stroke_width: 2
    yaxis_id: kwh
    unit: W
    extend_to: now
    show:
      legend_value: true
      in_header: false
    group_by:
      func: median
      duration: 5m
  - entity: sensor.energy_production_today
    yaxis_id: kwh
    type: area
    name: Forecast Power
    color: grey
    opacity: 0.3
    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: 2
    float_precision: 2
    extend_to: false
    group_by:
      func: median
      duration: 1m
  - entity: sensor.solcast_pv_forecast_forecast_today
    yaxis_id: kwh
    type: area
    name: Forecast Solcast Power
    color: green
    opacity: 0.1
    unit: W
    data_generator: |
      var today = entity.attributes.detailedForecast.map((start, index) => {
        return [new Date(start["period_start"]).getTime(), entity.attributes.detailedForecast[index]["pv_estimate"]*1000];
      });
      var data = today
      return data;
    show:
      legend_value: false
      in_header: false
    stroke_width: 2
    float_precision: 2
    extend_to: false
    group_by:
      func: median
      duration: 1m
  - entity: sensor.inverter_daily_yield
    yaxis_id: header_only
    name: PV Today
    color: orange
    show:
      legend_value: true
      in_header: true
      in_chart: false
  - entity: sensor.energy_production_today
    yaxis_id: header_only
    name: Forcast Today
    color: orange
    show:
      legend_value: true
      in_header: true
      in_chart: false
  - entity: sensor.energy_production_today_remaining
    yaxis_id: header_only
    name: Remaining Today
    color: orange
    show:
      legend_value: true
      in_header: true
      in_chart: false

1 Like

I wanted to mention that the Apex Charts Card slowed down my frontend extremely.

I do not know what caused this issue as I have got another Apex Charts Card without such problems.

type: custom:apexcharts-card
apex_config:
  chart:
    height: 350px
all_series_config:
  unit: ' kWh'
header:
  title: Solar forecast
  show: true
  standard_format: true
  show_states: true
  colorize_states: true
graph_span: 2d
span:
  start: day
  offset: '-0h'
now:
  show: true
  color: red
yaxis:
  - id: kwh
    min: 0
    apex_config:
      tickAmount: 4
  - id: header_only
    show: false
series:
  - entity: sensor.pv_produktion_gesamt
    name: Actual Power
    type: area
    float_precision: 1
    color: '#ff9800'
    opacity: 0.5
    stroke_width: 2
    yaxis_id: kwh
    unit: kW
    extend_to: now
    show:
      legend_value: true
      in_header: false
    group_by:
      func: median
      duration: 5m
  - entity: sensor.energy_production_today_all
    yaxis_id: kwh
    type: area
    name: Forecast Power
    color: grey
    opacity: 0.3
    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: 2
    float_precision: 2
    extend_to: false
    group_by:
      func: median
      duration: 1m
  - entity: sensor.energy_production_tomorrow_all
    yaxis_id: kwh
    type: area
    name: Tomorrow
    color: light_grey
    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: 3
    float_precision: 2
    extend_to: false
  - entity: sensor.pv_kwh_daily
    yaxis_id: header_only
    name: PV Today
    color: orange
    show:
      legend_value: true
      in_header: true
      in_chart: false
  - entity: sensor.open_meteo_solar_forecast_geschatzte_energieproduktion_heute_gesamt
    yaxis_id: header_only
    name: Forecast Today
    color: orange
    show:
      legend_value: true
      in_header: true
      in_chart: false
  - entity: >-
      sensor.open_meteo_solar_forecast_verbleibende_energieproduktion_heute_gesamt
    yaxis_id: header_only
    name: Remaining Today
    color: orange
    show:
      legend_value: true
      in_header: true
      in_chart: false
  - entity: sensor.meteo_solar_forecast_geschatzte_energieproduktion_morgen_gesamt
    yaxis_id: header_only
    name: Forecast Tomorrow
    color: grey
    show:
      legend_value: true
      in_header: true
      in_chart: false

Hello,
I also had the problem of the slow Apex card. I then created a horizontal stack and divided the Apex charts into today and tomorrow. Made it a little nicer for my wife and the washing machine. You have to set the threshold for yourself. My Apex chart card is here.
I no longer have any delay.
You could probably display a whole week like this.
Greetings
Rainer

type: horizontal-stack
cards:
  - type: custom:apexcharts-card
    experimental:
      color_threshold: true
    apex_config:
      chart:
        height: 260px
        tickAmount: 10
    all_series_config:
      unit: ' kWh'
    header:
      title: Prognose heute
      show: true
      standard_format: true
      show_states: true
      colorize_states: true
    graph_span: 20h
    span:
      start: day
      offset: +4h
    now:
      label: ''
      show: true
      color: white
    yaxis:
      - id: kwh
        min: 0
        apex_config:
          tickAmount: 8
      - id: header_only
        show: false
    series:
      - entity: sensor.energy_production_today
        yaxis_id: kwh
        type: area
        curve: smooth
        name: Forecast Heute
        color: lightgreen
        color_threshold:
          - value: 300
            color: darkred
          - value: 1000
            color: red
          - value: 2500
            color: orange
          - value: 4500
            color: green
          - value: 6000
            color: yellow
        opacity: 0.5
        data_generator: |
          return Object.entries(entity.attributes.wh_period).map(
            ([key, value]) => [new Date(key).getTime(), value]
          );    
        show:
          legend_value: false
          in_header: false
        stroke_width: 2
        float_precision: 1
        extend_to: false
      - entity: sensor.energy_production_today
        yaxis_id: header_only
        name: Forcast Today
        color: orange
        show:
          legend_value: true
          in_header: true
          in_chart: false
      - entity: sensor.energy_production_today_remaining
        yaxis_id: header_only
        name: Remaining Today
        color: orange
        show:
          legend_value: true
          in_header: true
          in_chart: false
      - entity: sensor.energy_production_tomorrow
        yaxis_id: header_only
        name: Forecast Tomorrow
        color: lightblue
        show:
          legend_value: true
          in_header: true
          in_chart: false
  - type: custom:apexcharts-card
    experimental:
      color_threshold: true
    apex_config:
      chart:
        height: 305px
        tickAmount: 10
    all_series_config:
      unit: ' kWh'
    header:
      title: Prognose morgen
      show: true
      standard_format: true
      show_states: true
      colorize_states: true
    graph_span: 20h
    span:
      start: day
      offset: +28h
    now:
      label: ''
      show: true
      color: white
    yaxis:
      - id: kwh
        min: 0
        apex_config:
          tickAmount: 10
      - id: header_only
        show: false
    series:
      - entity: sensor.energy_production_tomorrow
        yaxis_id: kwh
        type: area
        name: Tomorrow
        color: lightblue
        color_threshold:
          - value: 300
            color: darkred
          - value: 1000
            color: red
          - value: 2500
            color: orange
          - value: 4500
            color: green
          - value: 6000
            color: yellow
        curve: smooth
        data_generator: |
          return Object.entries(entity.attributes.wh_period).map(
            ([key, value]) => [new Date(key).getTime(), value]
          );
        show:
          legend_value: false
          in_header: false
        opacity: 0.4
        stroke_width: 2
        float_precision: 2
        extend_to: false
      - entity: sensor.energy_production_tomorrow
        yaxis_id: header_only
        name: Forecast Tomorrow
        color: lightblue
        show:
          legend_value: false
          in_header: false
          in_chart: false

2 Likes

So far, the predicted solar from this integration is way too high compared to what my panels are generating (e.g. today is still 32 kWh predicted, actual will be ~23 kWh), and way higher than the Solcast integration predicted. Is this common? I set it up with identical settings to Solcast.

1 Like

Not identical settings, check azimuth conversion.

Ah well my Solcast azimuth is 155, which I think means I need 205 for this integration? I changed it to 205 and the predicted solar actually went up by 2.5 kWh…

this has been raised/flagged anecdotally before and rany has made a suggestion to change the Integration to allow him check this out…not sure anyone replied or took him up so maybe you want to get involved…

this link and post above it too

For the “today” value i am more or less happy the value from this addon. Mostly they are not farther away than 4% (at an 140kWh energy production)
Do not forget this is a forecast, even weather forecasts (temperature/precipitation) only have a probability between 70-90% for the next 24h.

Which had confused me first, was that this addon and solcast have different names for the sensors for the days after tomorrow.
Solcast uses like “sensor.solcast_pv_forecast_prognose_tag_3” while this addon uses “sensor.owsun_fc_energy_d2” for the 3rd forcasted day.

Trying to compare all available predictions. All have the same setting.

image

3 Likes

I have some changes I’ll make public that should improve the accuracy further, and thanks for the comparison with Solcast. Right now they’re just a WIP, most likely I’ll dump it with the multiple PV array changes.

2 Likes

I just don’t want to release it right now and bother people with many updates, I think I’ve made too many releases already :sweat_smile:

1 Like

Maybe I’m misunderstanding but your algorithm looks wrong. The description on the Solcast website:

The direction on the horizon the PV modules are facing, expressed in degrees. Values must be between -180 and 180. 0 is north, 180 is south. Eastward facing = negative values. Westward facing = positive values. For example, -90 is due east.

So for me (25 degrees west of south), I had to use 180-25 = 155. This open-meteo integration says:

360 degrees, 0 = North, 90 = East, 180 = South, 270 = West

So for me that’d be 180+25 = 205.