Solcast Solar Enhanced — built-in history, automatic PV tuning & adaptive shading dampening (companion to ha-solcast-solar)

Hi all :waving_hand:

I've been running BJReplay's excellent ha-solcast-solar integration for a while, and wanted three things on top of it: somewhere to keep my own actual-vs-forecast history, a way to work out my real panel tilt/azimuth from that history, and shading correction that tunes itself instead of me hand-editing dampening factors. So I built a companion integration that does exactly that — and figured others might find it useful.

Solcast Solar Enhanced is an add-on, not a replacement — it sits alongside the base Solcast integration and reads its forecast data (zero extra Solcast API calls). All credit to BJReplay for the foundation this builds on. :folded_hands:

What it does

:file_cabinet: Built-in historical storage — a zero-config SQLite database (stdlib sqlite3, lives in your HA config dir). It quietly records actual generation vs forecast every half-hour, so you finally have the history the smart features need.

:triangular_ruler: Automatic rooftop PV tuning — fits your real tilt and azimuth from clear-sky history using a numpy grid search. In my case it converged to within ~1° of my actual orientation.

:sun_behind_large_cloud: Adaptive shading dampening — computes per-hour dampening purely from your measured actual/forecast ratio and pushes it back to the base integration. It starts as a no-op and ramps toward the measured correction as confidence builds, so it never does anything silly with thin data.

Plus:

  • :house: Multi-site — multiple arrays on one property, auto-discovered, with DC-ratio apportionment for string inverters (e.g. Fronius) that share one AC output.

  • :sun: Curtailment-aware dampening — if you have an export limit, curtailed clear-sky days no longer get misread as "shading" (it clips the forecast to what was achievable).

  • :battery: Battery-aware, energy-counter or power-sensor inputs, optional history retention, OpenWeatherMap cloud cover for clear-sky filtering, and 11 languages.

Raspberry Pi friendly :strawberry:

No scipy (it has no Pi wheel and breaks under HA — see ha-solcast-solar #85), so the optimiser is a pure numpy grid search. numpy already ships with HA, storage is stdlib sqlite3 — so there's nothing extra to install.

Requirements

  • Home Assistant 2026.5.4+

  • The base ha-solcast-solar integration (hard dependency)

  • A free OpenWeatherMap API key (for the clear-sky cloud filter that tuning & dampening rely on)

  • A generation sensor (ideally a cumulative energy counter)

Install

Via HACS → Custom repositories → add https://github.com/JimboHamez/ha_solcast_solar_enhanced (category: Integration) → install → restart → add the integration and follow the setup wizard.

A peek at what's coming :microscope:

I'm working on hardware-based curtailment detection using per-MPPT DC telemetry — when an inverter curtails, string voltage climbs toward open-circuit while current collapses, which is a direct fingerprint of being held back (independent of the forecast or export limit). The current release captures that data (opt-in) so the detector has real history to learn from; the detection itself is the next milestone.

Repo & feedback

:backhand_index_pointing_right: GitHub - JimboHamez/ha_solcast_solar_enhanced: Adds solar dampening enhancements to @BJReplay/ha-solcast-solar · GitHub

This scratches my own itch (a multi-array Fronius setup with an export limit here in Melbourne), but I'd love feedback, bug reports, and to hear how it behaves on other hardware/inverters. Issues and PRs welcome.

Cheers!

6 Likes

:wrench: Question about multi-site support

Hi,

your integration sounds very interesting and exactly like what I am looking for.

My setup

I currently have two separate Solcast sites:

  • Fronius Gen24 → 2 MPPT / strings
  • Fronius Symo → 1 MPPT / string

Both sites are configured independently in Solcast and have:

  • different azimuth
  • different tilt (elevation)

My question

Is your integration able to handle multiple independent Solcast sites, or is it limited to a single system / aggregated coordinator?

Specifically, is the following supported:

  • separate dampening per Solcast site
  • separate statistics sensors per site
  • multiple independent config entries

Observation during setup

I already installed the integration and tried to configure it.

However, I could only find one set of parameters for:

  • azimuth
  • tilt

So it looks like the integration assumes one system only.


Clarification

Can your integration work with my setup as-is,
or would both sites need to be combined into a single system?


Thanks!

Hey Mate,

This is still very much is development for multi sites. If you are using one API key with the base Solcast Solar component then yes my integration should work seamlessly. Please download the current beta version as it has a lot of improvements built in. If you are using 2 or more Solcast API keys across different accounts, I might lean on you for some extra data to see how your site is setup. Cheers

Hey all :waving_hand:

Quick update on Solcast Solar Enhanced, the companion to BJReplay's ha-solcast-solar that adds its own history database, auto panel-tuning, and self-adjusting shading dampening. The latest beta (1.10.0) is mostly about making things much nicer if you've got more than one array — plus some quiet smarts that make the shading correction more accurate for everyone.

As always: it's an add-on, not a replacement. It sits next to the base Solcast integration, reads its forecast data, and makes zero extra Solcast API calls. All credit to BJReplay for the foundation. :folded_hands:

:sparkles: What's new

:house: Each array gets its own device & card. If you run multiple arrays (say a ground mount + a roof, or a string inverter feeding one meter), each one now shows up as its own tidy Home Assistant device instead of everything piling onto one giant card. Each array carries:

  • a PV Power sensor (that array's own generation),

  • a Shading sensor (how much that array is being held back), and

  • a Tuned Tilt sensor (the real tilt it worked out from your history).

So you can finally see "ground array vs roof array" at a glance, and even give each one a friendly name.

:sun_behind_large_cloud: Smarter shading correction. The dampening that learns your shading now picks its "clear sky" reference days using measured sunlight (via free, keyless Open-Meteo) instead of cloud-cover guesses. Cloud-cover readings tend to cry "overcast!" on perfectly clear days, which was throwing off exactly the days the correction needs most. This makes the learned correction noticeably more accurate — especially on partly-cloudy days.

:bar_chart: New "PV Forecast Confidence" sensor. A simple 0–100 score (high / medium / low) for how well your panels are actually tracking the forecast right now. High = the next few hours look trustworthy, so it's a good time to run the EV charger, pool pump, or hot water. Low = local conditions are drifting from the forecast, so maybe hold off. It's a decision aid, not a forecast — and it's never pushed back to Solcast.

:shuffle_tracks_button: Multi-array dampening that actually engages. Previously per-array shading correction was wired up but often starved of per-array forecast data. It now works properly — including across arrays that face different directions.

:strawberry: Still Raspberry Pi friendly

No scipy, nothing extra to install. The tuning is a pure numpy grid search (numpy already ships with HA), and the history database is plain stdlib SQLite. Just install and go.

:folded_hands: Give it a go — feedback very welcome

This is currently a beta, and I'd love more eyes on it — especially from people with different inverters and multi-array layouts than mine (I'm on a multi-array Fronius setup with an export limit here in Melbourne). If you try it, I'd genuinely love to hear how the per-array devices and the new dampening behave on your hardware.

:package: Installing the beta via HACS

Because this is a pre-release, there's one extra tick-box compared to a normal HACS install — you have to tell HACS to show beta versions.

If you don't have it yet (add the repo first):

  1. In Home Assistant, go to HACS.

  2. Click the ⋮ menu (top-right) → Custom repositories.

  3. Paste https://github.com/JimboHamez/ha_solcast_solar_enhanced, set Category: Integration, and click Add.

  4. Search for Solcast Solar Enhanced and open it.

Then grab the beta:

  1. Click Download (or the ⋮ → Redownload if it's already installed).

  2. In the version dialog, turn on "Show beta versions" — this is the important bit, or you'll only see stable releases.

  3. Pick the latest 1.10.0bX version from the dropdown and download it.

  4. Restart Home Assistant.

  5. Go to Settings → Devices & Services → Add Integration, search for Solcast Solar Enhanced, and follow the setup wizard.

:light_bulb: Already running it? Same idea — just Redownload, flip on Show beta versions, pick the 1.10.0 beta, and restart. Your config and history database carry over.

Needs the base ha-solcast-solar integration and a generation sensor (a cumulative energy counter is ideal). Issues and PRs welcome — cheers! :clinking_beer_mugs:

1 Like

@jimbohamez

Quick question, the battery sensor is that a energy meter (kWh) or sensor (W).

Also not sure if it is working properly, should i have data in tuned panel and tuned RMSE

Thanks

Hey Jim!

Thank you for your work in this integration. I’ve been using it for a while now and values are getting better.

After having updated the base integration to version 4.6.0, I encountered a problem.

sensor.<name>_base_integration_status reports not_detected even when the base solcast_solar (BJReplay/ha-solcast-solar) integration is installed, configured, and working correctly. All other functionality (forecasts, dampening, tuning) continues to work — this is a detection bug in the status sensor only.

Root cause:

solcast_solar (base) v4.x migrated its coordinator storage from hass.data[DOMAIN] to the config entry’s runtime_data attribute:

# solcast_solar/__init__.py
entry.runtime_data = _SolcastData(coordinator=coordinator)

solcast_solar_enhanced’s _get_base_coordinator() still only checks hass.data:

# coordinator.py
def _get_base_coordinator(self) -> Any | None:
    return self.hass.data.get(BASE_DOMAIN)

Since the base integration no longer writes to hass.data[BASE_DOMAIN], this always returns None, so _do_update() sets base_status = "not_detected" every cycle.

Note __init__.py’s own setup check already has a working fallback for this exact case:

if BASE_DOMAIN not in hass.data and not hass.config_entries.async_entries(BASE_DOMAIN):
    ...  # raises "not loaded"

— it treats the integration as present if there’s a config entry, even without hass.data. The coordinator’s _get_base_coordinator() doesn’t use the same fallback, so the status sensor and the setup check disagree.

To reproduce:

  1. Install solcast_solar v4.6.0+ (any version storing the coordinator via entry.runtime_data instead of hass.data[DOMAIN]).
  2. Install/reload solcast_solar_enhanced (reproduced on both v1.10.0b9 and v1.10.1).
  3. Observe base_integration_status sensor = not_detected.

Suggested fix:

def _get_base_coordinator(self) -> Any | None:
    coord = self.hass.data.get(BASE_DOMAIN)
    if coord is not None:
        return coord
    entries = self.hass.config_entries.async_entries(BASE_DOMAIN)
    return entries[0] if entries else None

Mirrors the fallback already used in __init__.py’s setup check. I patched this locally and confirmed it flips the sensor to connected after a full HA restart (a plain integration reload isn’t enough — Python modules aren’t reimported on reload, only async_unload_entry/async_setup_entry re-run).

Versions:

  • solcast_solar: v4.6.0
  • solcast_solar_enhanced: 1.10.0b9 → still present in 1.10.1
  • Home Assistant: 2026.7.4

Thanks again for maintaining this!

2 Likes

Hi, great stuff you made here, will need to take a look as something pointing towards same direction was in my own integration, but trying to solve by some statistics - I assume will be able to toss it out. One question I assume is already answered, as not yet, but soon will have multi panel on different location setup, so seem like is ready or getting ready for that support. However other question is does it have some kind of detection or way to inform of times which needs to get ignored. Use case is that my integration controls inverter according to netBilling use case, So I have times when I can not export (negative price of electricity) and if battery is full and no where to put energy, lack of generation is not due to imprecise orientation or shading, but rather lack of places to put energy.

Hey Jim! I think this sounds like a similar problem to what other described, but I am running a single inverter system (sigenergy). here goes!

So, I currently have 4 MPPTs, but only 2 arrays set up in solcast, since they’re grouped at 2 sets of similar angles, but across 4 strings because of the array sizes.

Is there a possibility of making the enhanced per-string power/current/voltage analysis work such that we can input more than one entity per site for the mapping? Basically my goal is combine 2 MPPTs into 1 solcast site (since I have 2 sites and 4 MPPTs, and for solcast I just grouped them).

Alternatively I guess another direction to go would be adding support for combining 4 solcast sites across 2 API keys, but that seems kind of sketchy.
Otherwise this looks great! It just falls a little short on that specific capability.

This looks great, as you can see my solcast forecast is consistently too high…and I have zero obstructions on my panels.

My question is how this would handle a zero-export restriction?
Our house is not yet approved for export (been on the list for 1 year waiting…), so often during the day our inverter status says “Grid-Connected, Grid connection with derating due to power rationing” which essentially means that their is excess power available but we are not consuming it.

How can I use the derating feature so I can pull down that Solcast forecast, but ignore the data when it is derated?


Hey Mate, have a similar issue with my place in that I have an 8kW system and 5kW export limit. With a Fronius Gen24 I can tell the export is the limiting factor for solar generation based on a 30min period with approx 5kWh output and voltage starts to increase over 400volts per string. As there is no real way to determine what the max output might have been currently I discard these records from any calculations and dampening. Open to ideas on how the integration could solve this. Cheers

Hey Mate,

Good news, you need less than you think. The per-string V/I capture already
takes two MPPTs per Solcast site, so your 4 MPPTs across 2 sites map straight in:
in the sites step each array gets its own “MPPT 1 voltage/current” and “MPPT 2
voltage/current” fields. Fair warning though, that telemetry is currently captured
and stored (one diagnostic sensor shows the latest), it’s groundwork for
curtailment/shading-mechanism detection rather than something that analyses anything
for you yet.

The field that does drive things is “DC/MPPT sensor (for split)” — that’s what
splits your shared inverter AC across the two arrays, as ac × dc_array / dc_total.
You’re right that it currently takes a single entity, and that’s the actual gap. Two
options:

Now: since only the ratio is used, a template sensor per array is
mathematically exact, not a fudge:

template:
  - sensor:
      - name: "Array A DC power"
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement
        state: >
          {{ (states('sensor.sigen_pv1_power') | float(0))
           + (states('sensor.sigen_pv2_power') | float(0)) }}

Same for Array B with MPPT 3+4, then point each array’s DC field at its template. If
Sigenergy only gives you volts and amps per string, use v1*i1 + v2*i2. Both arrays
just need the same unit as each other. And don’t worry about “sensor type” here — a
raw instantaneous power reading is fine for the DC field specifically, because it
only ever feeds the ratio (unlike the AC generation sensor, where a kWh counter is
strongly preferred).

Soon: letting that field accept multiple entities and summing them is a small
change, and your setup is a good argument for it. I’ll queue it up - then you can
drop the templates.

Cheers,
Jim

Hey Mate, The battery sensor is in kW. That said at this stage I do not have a battery to test. And TBH I am not sure it really adds any value to the integration or the calculations it performs.
Regards,
Jim

Thanks Mate,

Appreciate your work, resolved in 1.10.3

Regards,
Jim

Hey Mate,

Have released a beta for you to try. v1.11.0b1 (beta) — an array’s DC share can span several MPPTs it will be available in HACS shortly

Regards,
Jim

Hi all :waving_hand:

Quick update on Solcast Solar Enhanced — the companion integration for BJReplay’s ha-solcast-solar that keeps your own actual-vs-forecast history, tunes your panel geometry from it, and pushes a measured shading correction back to Solcast. It’s an add-on, not a replacement, and it makes zero extra Solcast API calls — it reads the forecast the base integration already fetched. All credit to BJReplay for the foundation. :folded_hands:

The 1.11.0 beta line has been rolling out over the last week and there’s a fair bit in it.

:world_map: The headline: a shading map of your roof (b3)

Until now, the integration measured shading by asking “how much less than forecast does this hour usually produce?” — and that question is asked in the wrong units.

Shading depends on where the sun is. But an hour on the clock is a completely different sun position in July than in December, so a real morning shadow gets averaged away across the season. On my own system the measured morning loss was 30–59% while the correction actually being applied was 0–3%.

The new Shading Loss (Measured) sensor asks the right question. Using the irradiance and output already sitting in your database, it works out how much direct sun each array is losing and from which part of the sky — reporting a compass bearing and a sun elevation. You get one for the whole property and one per array.

It also tells you what kind of shadow it is, from the per-tracker DC figures:

  • A shadow lying evenly across the panels drops the current while the voltage holds steady, and loses power roughly in proportion to the area covered.
  • One that trips the panels’ bypass diodes drops the voltage too, and doesn’t behave proportionally at all.

Only the first kind can be described by a simple correction factor, so the sensor tells you which you’ve got.

This is read-only. Nothing here is sent to Solcast and your dampening factors are untouched. It’s a diagnostic — the point is that you can see what your roof is doing before anything acts on it.

Two limits, both reported rather than hidden: below about 15° of sun elevation it can’t cleanly separate “the sun is blocked” from “the sky is blocked”, so results down there are flagged uncertain; and shading that dims every array equally is invisible to it, because there’s nothing left to compare against.

:electric_plug: One combined meter? There’s now an option for that (b4)

If your system reports all its solar through a single sensor with nothing per array — a Tesla Powerwall 3 being the clearest case, since Tesla removed per-string data from every consumer API — the setup wizard previously had no option that fitted, and you simply couldn’t get past the per-array page.

There’s now a third choice: “one combined meter, no per-array data.” It asks for nothing else and tracks your property as a single system.

You lose less than that sounds like. Dampening is worked out per hour, so with an east array and a west array, the east one dominates your morning total and the west one your afternoon — a morning shading loss still lands in the morning hours of the correction. What a single meter genuinely can’t give you is the per-array sensors and per-array tilt tuning.

:warning: Worth checking if you have a multi-array system. The same release fixed a bug that could quietly switch your dampening off. If you’d mapped the same generation sensor to two arrays — easy to do, because that field used to come pre-filled with it — each array recorded the whole property’s output. Every per-array ratio then read roughly double, and since a factor above 1 gets clamped back to 1, the result was no dampening at all. Nothing warned you. It’s now a clear error, and the field isn’t pre-filled where that suggestion was the trap. Open Configure and have a look at the per-array page.

:wrench: Also in the beta line

  • b1 — an array’s DC share can span several MPPTs. Reported by a Sigenergy owner running 4 MPPTs grouped into 2 Solcast sites. The DC field is now a multi-entity picker; select all of an array’s trackers and they’re summed. Only the ratio is used, so this is exact, not an approximation — and it replaces a template sensor per array.
  • b2 — better DC data collection. The per-tracker current column stored the interval minimum (deliberately, to catch inverter throttling), which turns out to be useless for measuring shade — one passing cloud pins the whole half hour near zero, worst at low sun. On a 74-day store that left 56 of 67 mornings with no usable 08:00 reading. There’s now a median alongside it. Forward-only, since a minimum can’t be turned back into a median after the fact.
  • b5 — documentation and tooling. No functional change. Two sensors were named inexactly in the docs; both are fixed and now enforced by tests. Also adds an offline tool for anyone with two arrays at the same tilt and azimuth, which measures shading by comparing the arrays against each other rather than against the forecast — that cancels the forecast’s own error out of the measurement entirely.

:package: HACS submission

The integration has been submitted to the HACS default repository (hacs/default#10336, in the queue since late August). If it’s accepted it’ll be installable directly from HACS without adding a custom repository first.

Please don’t comment on or react to that PR — HACS explicitly ask people not to, it doesn’t speed anything up, and it makes more work for volunteer reviewers. It’s processed oldest-first and it’ll get there. :slightly_smiling_face:

In the meantime, installing is still easy:

  1. HACS → ⋮ → Custom repositories
  2. Add https://github.com/JimboHamez/ha_solcast_solar_enhanced as an Integration
  3. Install, restart, then add it from Settings → Devices & services

For the 1.11.0 betas, enable “show beta versions” on the integration in HACS. Or stay on v1.10.3 if you’d rather have the stable line — the betas are all additive and read-only where it counts, but they’re betas.

:sparkles: Why you might want it

  • :satellite_antenna: No extra Solcast API calls. It reads what the base integration already fetched. Your poll budget is untouched.
  • :file_cabinet: History with no setup. Built-in SQLite in your HA config folder — no database server, no add-on, nothing to configure. It just starts recording.
  • :triangular_ruler: It works out your real tilt. From clear-sky history, via a physical irradiance model. And when the data can’t determine a tilt, it says so and reports nothing rather than handing you a confident wrong number to paste into Solcast. (Azimuth is deliberately not tuned — it isn’t recoverable from this data, so it’s reported back as configured rather than guessed.)
  • :sun_behind_large_cloud: Dampening that earns its confidence. It starts as a complete no-op and ramps toward the measured correction as evidence accumulates — it won’t do anything drastic on a fortnight of winter data.
  • :high_voltage: Curtailment-aware. If your inverter is export-limited, that throttled output isn’t mistaken for shading and dampened away.
  • :strawberry: Raspberry Pi friendly. numpy only — no scipy, which has no Pi wheel and fails to build under HA. numpy already ships with Home Assistant, so there’s nothing extra to install.
  • :key: No API key needed for irradiance. Open-Meteo is keyless and on by default. OpenWeatherMap is optional, and if you do enable it the setup wizard tests your key before storing it.
  • :house: Proper multi-array support. Arrays auto-discovered from Solcast, each on its own device, with per-array shading, tilt and dampening where your hardware can support it.
  • :globe_showing_europe_africa: Eleven languages, and every sensor name is translated rather than hard-coded to English.

:folded_hands: Feedback wanted

Two things I genuinely can’t test myself:

  • Powerwall 3 owners — the new combined-meter option was built from a user’s description of what those integrations expose. I don’t have one. If you try it, I’d love to know whether it goes through cleanly.
  • Anyone with heavy morning or afternoon shading — the shading map is the first release of a fairly involved bit of physics. It’s read-only so it can’t hurt your forecast, but I’d like to know whether the bearing and elevation it reports match what you can actually see from your roof.

Issues and questions: GitHub or reply here. :sun_with_face:

1 Like