# OPT-17 - the solar forecast from several entities, summed **Status: for review.** Tests: `test_opt17.py`. Two options added. A site whose forecast comes as several Home Assistant sensors (one per inverter or roof side) had to build a template sensor to sum them. Now each day can list them. ## Options - `pv_forecast_entities` and `pv_forecast_tomorrow_entities`: lists of sensors, default `[]`, the same shape as `pv_entities`. - `pv_forecast_entity` and `pv_forecast_tomorrow_entity` are unchanged. An install that uses them needs no edit. - **Why new keys, not "string or list" in the old ones.** Measured on Supervisor 2026.08.0 by `tools/supervisor_shape_probe.py` §J, as TEL-12's §G did for `pv_entity`. Declared as a list, each forecast key refuses the string an install already stores (`Invalid list for option 'pv_forecast_entity'`), and a `[]` default does not rescue it. The one spelling that takes both, `match(.*)?`, also takes the integer 417 and shows a plain text box, so a second sensor cannot be added in the UI. - §J also shows: a 0.17.0 blob validates unchanged with the lists at `[]`; the lists render as repeatable fields; a downgrade drops them and keeps the single keys. - `[]` in `options:` is load-bearing, as for `pv_entities`. ## Rules 1. **One key per day.** Setting the single key and the list for the same day is refused at start, with one message: keep the list, clear the single one. The list can hold that entity too. (TEL-12 lets `pv_entities` replace `pv_entity` with a caution row. Here the brief asked for a refusal: a doubled or dropped forecast changes what a battery buys, and no install has both keys yet, so the refusal breaks nothing.) 2. **Each member in its own unit.** Every member is read as one forecast sensor is today (`solarfc._day()`): Wh, kWh or MWh, never guessed. Then the day's kWh are added up. A repeated id counts once. 3. **One member not usable means the day is not usable.** Missing, unavailable, unknown, stale, not an energy unit, or a bad number: that day's sum is not used, exactly as when the single sensor reads that way. No today means no forecast (P3 option A). No tomorrow means today only. 4. **Hourly split.** If every member has a split, the splits are joined (overlapping periods add up). If any member has none, the sum is spread over the bell, as for a state-only sensor. 5. **Time.** The forecast is as old as its oldest member. 6. **One read.** All members of both days are read in one gather, inside the gather that reads the inverters, so a slow sensor does not delay control. 7. **Shown and logged once.** With two or more members, each one not usable is named on the status page by its place in the list (STYLE.md: no entity ids on the page), as a caution row titled "Solar forecast" on Home. The action log names the entity id, once when the set of failing members changes. 8. **One member is the single key.** A one-member list reads, plans, shows and logs exactly as the single key with that entity. ## Why - A partial sum is a smaller number that looks real. Two of three inverters' forecasts read as a duller day, and Leftover solar would then buy grid energy the sun was going to give. TEL-12 took the same rule for the same reason. No forecast is a known state with a tested fallback. - The bell for a mixed list: joining one member's hours with another's total has no honest shape, and the bell is the existing state-only rule. ## Cost - One flaky member costs the whole day's forecast. A site with three sensors loses the plan more often than one with a template sum that hides gaps. - Two more options (85). ## What this does not cover - No weighting or calibration per member; FCST-01 is still the own forecast. - Members on different integrations with different refresh times: each must be fresh (3 h) on its own; there is no wait for a lagging one. - The day plan itself, the trust and the house profile are unchanged. - The Batteries screen still says only "no solar forecast now". The member is named on the status page.