# Can't get forecast.solar forecast to line up with my production

Have you correctly set all other variables?
It looks like the forecast is following the production, but the figures are of.

This is my graph:

I think it’s in de “Total Watt Peak Power”, when I change the “Total Watt Peak Power of your solar modules” from my 4820 to 2000 the graph will look like this:

The “Total Watt Peak Power” has been provided the company that installed my panels, it’s based on all kinds of factors like the azimuth, angle of the panels, shading factors (tree, buildings, other solarpanels, etc. etc.), maximum power of the panels and probably some more.

1 Like

If you don’t know the “Total Watt Peak Power” because that figure hasn’t been provided or you’ve installed the panels yourself, you could always try to get retrieve the value from HA; it’s the highest wattage the entity has.

1 Like

Thanks for that!
I believe I got it right but it’s weird:
I have 1 on South and 1 on East, 5 400W panels and 5 microinverters (which I believe have a maximum peak power of 295W each) on South then 6 400W panels and 6 microinverters on East.
The calculation I did (which I hope it’s correct) was multiplying number of inverters per max wattage of each (which gives me 1.475 at South and 1.770 East) for max AC and 5 x 400W(solar panels - 2kW total) South and 6 x 400W (2.4kW) East for DC.
GPS coords are correct and using SunCalc, I believe the azimuth is also correct.
Unless my calculations here are wrong (which is also possible!).

I assume you’ve entered 4400 in the “Total Watt peak power…” field and 3245 in the "Inverter size (Watt) field. I would enter 3245 in both fields and my reasoning is:

• the “Total Watt peak power…” of your panels can not be higher than your “Inverter size (Watt)”,
• because in your case there is a “big” difference between, what the panels can generate and the inverter can invert, I don’t think you have to take into account any limiting factors.

In my case I’ve got 14 405W panels with 7 two channel inverters capable of 730W (max per inverter). I theory my panels should be capable of providing 5670W. My supplier has determined that 4820 is a more realistic number, taking all variables into account because I don’t live in a labaratory with the most optimal conditions. So I’ve entered 4820 in the “Total Watt peak power…” field and 5110 in the "Inverter size (Watt) field.

1 Like

Thanks! That makes sense, I will play with the numbers, see how it goes and give you an update.

1 Like

I just realised that this is for forecast.solar and not solcast but the principle is the same
Thanks a lot for the help, @hebom , it’s much better now than it was before.

1 Like

Hi I am not trying to do something as complicated, but this does look great.

I just want to compare previous days pv forecast, with actual daily pv output on a graph or bar chart.
I only have the default energy_production_today, and my pv_day_energy (which is at its peak at the end of the day, so say 9pm)
I would like to see both on a bar chart to compare pv_day_energy at 9pm, to forecast at around 11pm -2am the night before.
a bit like the graphs @Biscuit has.

any help really appreciated.

Sounds simple… Yes it would be nice to know, as the sun sinks below the horizon, just how accurate that forecast really was. I am working on this with a long-term database, but here is one solution. Hope this helps.

The forecast.solar integration in HA pulls in 48 hours of data covering the full period for today and tomorrow, ‘randomly’ each hour. The sensor energy_production today/tomorrow is the sum of each 24 hours. The base forecast data is updated every 15 mins, the HA integration entity every hour, and the ‘total today/tomorrow’ can change sometimes hourly (but not always) as a result.

See above my history for the forecast integration. My update is happening at 58 minutes past each hour (but it could happen at any point in the hour). Up to midnight, tomorrow is tomorrow, but sometime between 00:00 and 01:00 local time, tomorrow becomes today, thus to get “the forecast” for today requires obtaining ‘tomorrow’ from yesterday, and/or ‘today’ from today. Whilst ‘tomorrow’ changes during the day, it is always a forecast. ‘today’ also changes during the day, and therefore gradually becomes more of an historic record, so by the end of the day is it a “hindcast”.

Quite therefore what you pick out of that to be the ‘forecast’ is a bit of a guess. At the moment (over the past summer) I am finding for myself that the average of the first five hourly values for ‘today’ is the best resulting match to my actual value (at the end of the solar day). In the graph above, the orange line is the ‘tomorrow’, and the blue line is ‘today’, so if we look at the 3rd October, the blue ‘today’ averages around ‘3’ at the start of the day before it starts to change over the active solar day, and the orange ‘yesterday’ (over the 2nd October) averages about the same.

HA entity values are stored in history, and with a bit of effort past state values can be retrieved using the available HA API call. There is an SQL integration now, but even when asking for an array of values, this only returns on the most recent value.

https://developers.home-assistant.io/docs/api/rest/#get-apihistory

I use Node-RED for these things as I find it a) quicker b) easier and c) more powerful.

I have managed to put together up the following flow, which triggers after 22:00 each day, pulls in the last 48 hour records of the necessary entities, and processes the data. I have two planes (forecast.solar integrations) so it does this for both, and it does this for ‘today’ and for ‘tomorrow’ (four sensor entities in total).

I use JSONata to pick out today from today, and tomorrow from yesterday. I have opted here to pick only the first five records from today (pre sunrise) and for all from tomorrow-yesterday, averaged across all planes. This gives me the average forecast for today - from part of today - and the average forecast for today - from all of yesterday.

I then pick up the solar PV actual value (as pulled in from my inverter by Modbus read), and finally calculate a ratio, based on solar PV / forecast-today. The result can be passed back to HA in a sensor node (both state and attributes) and then HA will record the entity state/attribute values in history so it is easy to plot these values on an apex graph.

This is my current data. In the summer months the ratio (actual / forecast) was better, but this does suggest that my forecast is roughly a consistent 3 kWh too low. I am storing this data in a long term database, so once I have a full solstice to solstice dataset perhaps I can work out how to ‘adjust’ the forecast to better match the resulting actual.

Node-RED flow:

``````[{"id":"fe9e80e0ad137e77","type":"group","z":"95dab86a0bf42ced","name":"Calculate Solar Forecast to Actual Ratio","style":{"label":true},"nodes":["7a1df2413cd1c7ab","35296f1b09346067","cbf4985441778907","34585541521986ca","786207faf91b25ae","38e37a8043b02cc4"],"x":54,"y":959,"w":972,"h":122},{"id":"7a1df2413cd1c7ab","type":"api-get-history","z":"95dab86a0bf42ced","g":"fe9e80e0ad137e77","name":"forecast history","server":"","version":0,"startdate":"","enddate":"","entityid":"sensor.energy_production_today,sensor.energy_production_tomorrow,sensor.energy_production_today_2,sensor.energy_production_tomorrow_2","entityidtype":"is","useRelativeTime":true,"relativeTime":"48 hours","flatten":true,"output_type":"array","output_location_type":"msg","output_location":"payload","x":180,"y":1040,"wires":[["38e37a8043b02cc4"]]},{"id":"35296f1b09346067","type":"inject","z":"95dab86a0bf42ced","g":"fe9e80e0ad137e77","name":"At 22:15","props":[],"repeat":"","crontab":"15 22 * * *","once":false,"onceDelay":0.1,"topic":"","x":160,"y":1000,"wires":[["7a1df2413cd1c7ab"]]},{"id":"cbf4985441778907","type":"api-current-state","z":"95dab86a0bf42ced","g":"fe9e80e0ad137e77","name":"Solar Today","server":"","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.mb_solar_e_today","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload.solar","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":530,"y":1040,"wires":[["34585541521986ca"]]},{"id":"34585541521986ca","type":"change","z":"95dab86a0bf42ced","g":"fe9e80e0ad137e77","name":"Add ratio and save","rules":[{"t":"set","p":"payload.ratio","pt":"msg","to":"\$round(payload.solar/payload.fcToday,2)","tot":"jsonata"},{"t":"set","p":"solar","pt":"flow","to":"payload","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":710,"y":1040,"wires":[["786207faf91b25ae"]]},{"id":"786207faf91b25ae","type":"ha-sensor","z":"95dab86a0bf42ced","g":"fe9e80e0ad137e77","name":"Solar v Forecast","entityConfig":"3ab8194663a50d4b","version":0,"state":"payload.ratio","stateType":"msg","attributes":[{"property":"date","value":"payload.date","valueType":"msg"},{"property":"solar","value":"payload.solar","valueType":"msg"},{"property":"fctoday","value":"payload.fcToday","valueType":"msg"},{"property":"fcyesterday","value":"payload.fcYesterday","valueType":"msg"}],"inputOverride":"allow","outputProperties":[],"x":920,"y":1040,"wires":[[]],"server":""},{"id":"38e37a8043b02cc4","type":"change","z":"95dab86a0bf42ced","g":"fe9e80e0ad137e77","name":"Get FC figures","rules":[{"t":"set","p":"payload","pt":"msg","to":"(\t\t/* FUNCTION: extract individual plane and day from returned 48 hour history, uses entity_id */\t/*           to look for given plane [_\"1\" or _\"2\" etc] and day [_\"today\" or \"tomorrow\"]    */\t    \$pday:= function(\$plane, \$day){(\t        \$x:=\$array[\$contains(entity_id, \$plane) and \$contains(entity_id, \$day)];\t        \$x.{\"time\": last_updated, \"uts\": \$toMillis(last_updated), \"value\": state}^(>time)\t    )};\t\t/* have to deal with possible multiple integrations, so assume there are two or more                */\t/* look at entity 'sensor.energy_production_today' and where there is no number suffix, append \"_1\" */\t/* for each plane we have, and for both 'today' and 'tomorrow', built table to search               */\t    \$array:=payload~>|\$|{\"entity_id\": \$count(\$split(entity_id,\"_\"))<4 ? entity_id & \"_1\"}|;\t    \$table:=\$distinct(\$array.entity_id).\$substringAfter(\"production_\");\t    \$results:=\$table.(\t        \$x:=\$split(\$,\"_\");\t        {\"plane\": \$x[1], \"day\": \$x[0], \"forecast\": \$pday(\$x[1], \$x[0])}\t    );\t\t/* need number of planes for later */\t    \$planes:=\$count(\$distinct(\$results.plane));\t\t/* get last & previous midnight UTC as millisec and use to pick today (from today) and tomorrow (from yesterday) */\t    \$timestamp:=\$results[0].forecast[0].time;\t    \$midnight:=\$toMillis(\$substringBefore(\$timestamp,\"T\") & \"T\" & \"00:00:00\");\t    \$daybefore:=\$midnight-24*60*60*1000;\t\t/* forecast for today: get both 'today' today and 'tomorrow' yesterday */\t    \$today:=(\$results[day=\"today\"].forecast)^(uts);\t    \$tomorrow:=\$results[day=\"tomorrow\"].forecast^(uts);\t    \$today_today:=\$today[uts>\$midnight]^(time);\t    \$tomorrow_yesterday:=\$tomorrow[uts>\$daybefore and uts<\$midnight]^(time);\t\t/* decide what we want to get a figure for 'forecast' across today-today and tomorrow-yesterday */\t/* for myself, pick first 5 from today (only), average and summ (across all planes)             */\t/* and also take whole of yesterday (tomorrow) average and sum for all planes                   */\t\t    \$pick:=5;\t    \$range:=[0..\$pick*\$planes-1];\t\t    \$fctd:=\$today_today[\$range].\$number(value);\t    \$fcyd:=\$tomorrow_yesterday.\$number(value);\t    \$fcToday:=\$round(\$sum(\$fctd)*\$planes/\$count(\$fctd),1);\t    \$fcYsday:=\$round(\$sum(\$fcyd)*\$planes/\$count(\$fcyd),1);\t    {\"date\": \$substringBefore(\$timestamp,\"T\") ,\"fcToday\": \$fcToday, \"fcYesterday\": \$fcYsday};\t\t\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":1040,"wires":[["cbf4985441778907"]]},{"id":"3ab8194663a50d4b","type":"ha-entity-config","server":"","deviceConfig":"","name":"SC HA2 Solar v Forecast","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Solar v Forecast"},{"property":"icon","value":""},{"property":"entity_category","value":""},{"property":"entity_picture","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false}]
``````

Usual rules apply. Has been scrubbed (so add in your own HA server), set up for two integrations (so remove second if you don’t need), change entity name for solar PV actual to match your own. Code should work out for itself how many integrations you have but this is only tested for my setup.

Should manage to work over DST changes but as yet untested. Deals with the current (at the time of writing) websocket API History node ‘include’ error by listing the entities as a string - modify this as required.

Apex Chart config used

``````type: custom:apexcharts-card
graph_span: 7d
span:
end: day
offset: '-1d'
show: true
title: Solar Actual Vs Forecast
show_states: true
colorize_states: true
yaxis:
- id: ratio
min: 0.5
max: 4
decimals: 1
apex_config:
tickAmount: 7
- id: energy
min: 0
max: 25
decimals: 0
apex_config:
tickAmount: 5
series:
- entity: sensor.solar_v_forecast
yaxis_id: ratio
type: line
stroke_width: 3
name: Ratio
- entity: sensor.solar_v_forecast
yaxis_id: energy
type: line
stroke_width: 3
attribute: solar
name: Solar PV
- entity: sensor.solar_v_forecast
yaxis_id: energy
type: line
stroke_width: 3
attribute: fctoday
name: Forecast
``````

Errors and omissions excepted.

1 Like

Hi all, I’ve put in my 2 arrays, and I’m getting very low forecasts:

I add these together, and you can see actual is 4kw higher right now

we actually have other things like cloud cover I would have expected forecast to be higher than actual.

I’m trying to use something like the forecast next hour to control my automation instead of using actual instant generation which will be affected by cloud cover can be more volatile

One array ‘front’ and one array ‘rear’ suggest, like myself, that they face 180 degrees apart, yet your peak production is only 2 hours apart. Assuming Australia, around solar noon, you appear to have both arrays facing South to West.

Configuration settings must be accurate. Location, elevation from horizontal, array peak generation, and azimuth (which is measured differently in Forecast Solar) are critical. Then the inverter capacity figure limits the solar forecast should this exceed the maximum the inverter can deal with.

After that, it is a forecast. Based on clear sky estimates for your location / array orientation, but reduced for weather and atmospheric conditions. On a clear sky sunny day, with the correct settings, the actual should match the forecast. Issues with alignment have been noted.

Weather accuracy is another subject. Note that the integration uses an EU based estimate / forecast, which may not be as appropriate when in the Southern Hemisphere.

In my experience, ratio of actual production to day forecast can vary from around 0.5 to 2, and for myself averaging at around 1.3 over time as my array is shaded early & late.

Hourly forecast figures can be very inaccurate. I continue to collect daily solar and weather forecast and actuals in the hope that I might find a model that can be used to better estimate day and hour ahead values.

I have solar analytics setup and I have copied all these figures fromthere.

my Orientation: 128 and 308
That’s what I should use right?

I need some way of working out how much solar I’m producing so that I don’t react to cloud cover like this

I thought the this hour or next hour would be the thing that could give a useful number.

The integration configuration in HA uses north 0 east 90 south 180 west 270, which is different to the forecast solar API and possibly everyone else. I suggest your figures may be incorrect.

To deal with sudden cloud cover, I have tested using statistics platform sensors, based on rolling averages or smoothing over a time period of 15-30 minutes.

There must be an issue in the integration.

However you can’t put -ve in HA.

In any case it’s clearly wrong I can’t have two panels facing opposite sides with peaks one hour apart as you said. Is the integration just clearly useless then?

WHat Statistics are you using? I’m not a mathematician I’m not sure what would smooth out the graph. Eg red line

Because in Home Assistant we apply a 1 to 360 degree value and in the code we then translate the value to what the API should use.

In that case my settings are correct the only number I’m not sure about is the inclination 25 which I copied from my system but I haven’t measured myself.

As you can see, it’s generally 1-2kW under real

As a first step, the settings have to be absolutely correct. My solar panels face east-north-east and west-south-west, so the HA integration azimuth figures used are 75 and 255.

The elevation should be measured with a clinometer or by depth-height to calculate an angle. Zero is flat, my UK house roof is 35 and quite shallow. Free standing ideal is I think closer to 50, so 25 maybe incorrect (and the flatter they are the closer the two array solar peaks will be).

The basic solar pv model is accurate for South facing arrays, but becomes increasingly unreliable away from due South. North of East and West seems to be particularly difficult since the sun faces the panels near dawn/dusk, when atmosphere and horizon shading are most prevalent. Solar noon gives the best sun and estimates, but the sun is glancing incident on the array.

The weather is unpredictable. Cloud will reduce solar pv to about 15% of clear sky.

My forecast for the past hour was 600 Wh, I got 200. On a clear, sunny day, outside of December to January, I get a good match.

Personally, I don’t see that the 'next hour forecast is accurate for my practical use.

In time, based on either the solar forecast, the’ clear sky’ estimates, and/or my own ‘best day’ history, used together with my local weather forecast, I can see an opportunity to develop a better-fit next-hour estimate by down-rating based on cloud cover forecast.

My cloud cover is 100%. All day. I expect about 1.8 kwh today, not the 5 kwh forecast.

To try and answer your other question, only forecasting will give you an idea of what the solar pv will be in the next hour.
However, the statistics platform can offer averages and other figures, sampled over a given time period. Using a linear average sampled over 1hour, periods of passing cloud for 5-10 minutes can be “averaged out”. This is very much back-casting, and assumes that the next hour will be about the same as the average of the last hour.

I am most certainly not a statistics wizard, so I continue to explore and experiment from time to time to see if I can get a better model. A simple linear average would be an easy place to start.

1 Like

Hi @Biscuit ,

Can you share more details about your dashboard , eg the solar vs forecast? I cover 3 of the 4 available side on my roof and I would like to mimic you dashboard with the 2 orientation group. Could you please share how you built your dashboard?

My solar forecast project is now almost 2 years old, and I did an update on the Node-RED code I used mid last year. This NR code is now too big to post in this forum, so I posted in the Node-RED forum

https://flows.nodered.org/flow/bbde517b1e592ce804f553da80dbb4c4

Looking at this, I probably should redo the documentation and pull everything together into a Github repository… Another job for another time.

Here is a link to the update post in the main thread regarding my work. You can find the details above / below this post if you care to dig through the thread.

https://community.home-assistant.io/t/access-data-from-forecast-solar/435964/50?u=biscuit

Hope this is of use to you.

Not sure whether you already tried, but judging from your nick this should fit your needs better than forecast.solar:

1 Like

I also have wrong graph shifted 1 hour. Please share which file you are touching.
I will just add +1 and solve all my graph problems.