Open-Meteo Solar Forecast

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.

I’ll take a look but I think you’re right, I really misremembered how Solcast treats the Azimuth.

The biggest factor for solar production where I live (other than time of year) is cloud cover. Does this integration take this into account in forecasts?

Yes it does, but the compensation from Open-Meteo appears to be insufficient so I’ll need to add my own logic as well.

Important information:

Please switch back to the mainstream/flagship Open-Meteo API server: https://api.open-meteo.com. I am planning to make my instance non-public in the near future. I believe that the rate-limit issue is solved with version 0.1.11 (06/11/24).

Usually my “current hour” estimate ends up higher than the “remaining today” estimate in the evening, which clearly isn’t right. Anyone else have this? Maybe I’m misunderstanding and “remaining today” doesn’t include the current hour?

Remaining today doesn’t include the current hour.

1 Like

Cool, knowing that means my “slightly more accurate remaining solar” sensor actually works now. Not much cloud cover today so the estimate is looking good:


Not sure why the green lines always spike slighlty at night, the underlying data doesn’t so must be an issue with the averaging scheme.

If anyone is interested this will give you a more accurate estimate of remaining solar to the minute rather than it updating once per hour:

"{{ max(states('sensor.energy_production_today_remaining') | float + (60.0 - (as_timestamp(states('sensor.date_time_iso')) | timestamp_custom ('%M', false) | float)) / 60.0 * (states('sensor.energy_current_hour') | float), 0) }}"

1 Like