Skip to content

Releases: code-imstillalive/nimbus

v0.94.485

Choose a tag to compare

@github-actions github-actions released this 23 Oct 08:02
e3206fc

What a new install sees: the EV, every controllable load and the daily figures on Topology, one SoC per battery, and a revised tab beside yours.

Found by setting Nimbus up from scratch on the test box, with only the
dashboard Nimbus generates.

  • Topology draws your EV (#2021). A battery participant was drawn only on
    an install with no inverters, strings or towers set up; it now appears as
    its own source and battery beside them.
  • Topology draws every controllable load (#2021): a heat pump, pool pump,
    hot water or appliance under Nimbus's control, as a dashed row after the
    Loads, with whether Nimbus has it on (or its live power, where it has a
    power sensor) and today's energy against its target. Before, none appeared.
  • Topology shows the whole house and today's solar, battery and load
    figures
    (#2021) with nothing to add. They needed a whole_house block in
    the card's YAML, which the generated dashboard never had; they now come from
    the Solver's whole-house sensor and household load forecast, and a
    whole_house block still replaces them.
  • The Grid box shows the grid on an install whose Power Signals were left at
    Role Other (#2021), from the Forecaster's own Grid and Battery sensors. A
    Role or a card setting still comes first.
  • One SoC per battery on the Solver tab (#2021). With an EV, "Battery,
    now" and "At a glance" showed every battery's charge together, a figure no
    meter reads; each battery now has its own row and ring under its own name.
    A single-battery install is unchanged.
  • A revised tab goes right beside your own tab of the same title (#2020),
    so the two can be compared, instead of at the end of the dashboard.
  • Devhub validation: confirmed live on devhub (HA 2026.10.2) at 3aa1bf0
    (release/0.94.485), installed via HACS and restarted at 17:57 AEST; all 126
    Nimbus entities carrying a version read 0.94.485, and the first solve at
    17:58:44 was optimal. sensor.nimbus_topology_config lists the test EV
    beside both inverters, all six controllable loads with their own Commanded
    State and today's sensors resolved, and the Forecaster's Grid and Battery
    sensors as forecaster_meters. On the Topology tab (after a hard reload):
    the whole-house headline with daily solar, battery and load; the Grid box at
    -11.2 kW with both signals at Role Other; the EV with its SoC; a dashed row
    per controllable load, the one commanded on lit. The Solver tab's "Battery,
    now" and "At a glance" show "SoC Home battery" and "SoC Test EV" in place of
    the fleet figure. No Nimbus ERROR or traceback in the log after the restart
    (the only tracebacks were the restart request's own connection closing).
    • Not observable on devhub: a revised tab placed beside a household tab of
      the same title (#2020) needs a dashboard where Nimbus finds a missing
      standard tab; carried by #2020's tests. A browser keeps the old card until
      the version changes or a hard reload.
  • Consumer check: display only. Topology gains the EV, controllable loads and
    the headline with nothing to configure; a card with its own whole_house or
    switchboard keeps them. A single-battery install's Solver tab is unchanged.

v0.94.484

Choose a tag to compare

@github-actions github-actions released this 22 Oct 21:31
cd6f0bf

Faster solves; a timestamp without a time zone is read in your own.

  • Solves are faster (#2010). The step that chooses between equally cheap
    plans (which hour a pool pump runs, for example) now gets at most 5 seconds.
    When it runs out, the plan keeps the better of the two it has, so its cost
    never changes. On 40 test sites shaped like a real install, the mean solve
    went from 21.1 s to 12.9 s; cost was identical on all 40, and the battery
    plan identical on 38 (on two it moved 2.4 kW in one period). A spent budget
    shows as Budget spent, not as a time-limit warning.
  • A price change during a solve gets one re-plan straight after it (#2010),
    instead of waiting for the next tick. Several in a row make one re-plan.
  • The final step of a long solve always gets its time (#2010). Before, a
    long solve could leave it none, and the plan fell back to its simpler form
    with a 5-minute cooldown.
  • A forecast timestamp without a time zone is read in your Home Assistant
    time zone, not UTC
    (#2008).
    A timestamp with its own offset (+10:00, Z) reads exactly as before.
    Every source checked carries an offset, so nothing changes for them.
  • Devhub validation: confirmed live on devhub (HA 2026.10.2) at 79238a5
    (release/0.94.484), installed via HACS and restarted at 07:25 AEST. The
    solver's first cycle published a full plan at 07:25:32 (version 0.94.484)
    with no plan-failing Repair, and the load forecast totals kept reading. No
    Budget spent, phase-breakdown or traceback line in the log, and no Nimbus
    ERROR beyond the devhub-only baseline (duplicate unique IDs held by the
    mirrored entities, the test EV's out-of-range SoC and unreachable departure
    target, residual-drift notes, recorder attribute sizes).
    • Not observable on devhub: the time each solve took (devhub's own solve
      entities share their ids with the mirrored ones), a phase 2 that runs past
      5 s, and a source with offset-less timestamps; each is carried by its PR's
      tests and #2010's 40-site measurement.
  • Consumer check: the plan's cost is unchanged by #2010; on a site where the
    tie-break search runs long, solves finish sooner and an equally cheap
    schedule may be kept. No current source changes under #2015.

v0.94.482

Choose a tag to compare

@github-actions github-actions released this 22 Oct 08:31
2c193b1

Solcast, Open-Meteo and LocalVolts are found by their integration, not by entity name.

  • Solcast, Open-Meteo and LocalVolts are found by their integration, not by entity name
    (#1994). Solar
    auto-include, the solar running-low check, the new-install default for
    auto-include and LocalVolts' stale-price check matched fixed entity IDs, so a
    renamed (or non-English) Solcast or Open-Meteo entity was silently lost: with no
    other solar source, every plan ran on 0 kW solar. They now find each source
    through Home Assistant's entity registry by integration and built-in unique ID,
    the way price auto-detection already did, so a rename changes nothing. An install
    that renamed nothing reads exactly the same entities as before. The whole-house
    load is now only the sensor set in the whole-house cross-check field; the old
    fallback to one fixed entity name is gone.
  • Devhub validation: confirmed live on devhub (HA 2026.10.2) at a1a95e4
    (release/0.94.482), installed via HACS and restarted at 18:24 AEST; Home
    Assistant was back by 18:25:49 and Nimbus loaded. The solver's 18:28 cycle was
    optimal, and its whole-house reading (1.477 kW) came from the configured
    whole-house cross-check sensor. No new Nimbus ERROR or traceback beyond the
    devhub-only baseline (duplicate unique IDs held by the mirrored entities,
    Forecaster renames left in place, residual-drift notes, recorder attribute sizes).
    • Not observable on devhub: a renamed Solcast or Open-Meteo entity. devhub
      renames none, so it reads the same entities as before, which is the
      no-change half of this release; the rename half is carried by #1997's tests.
  • Consumer check: an install that renamed nothing sees no change; one whose
    Solcast, Open-Meteo or LocalVolts entities were renamed now has them found.

v0.94.481

Choose a tag to compare

@github-actions github-actions released this 22 Oct 05:49
58c1455

Every offer-curve point is what a plan at its price would do.

  • Every offer-curve point is what a plan at its price would do
    (#1990). The sweep
    moved only period 0's import or export cost, but a real plan at another price
    also moves the battery's loss tie-break (#732), the emergency-import markup
    (#390), the P2P shortfall rate and a price-derived soft SoC penalty, and it
    re-solves a plan that imports and exports at once one-way (#238). So some
    points, and the price range published with each, described plans no solve
    would make. All of these now move with the swept price, each point is made
    one-way the way build_plan does it, and each plateau's end is checked
    against the real solve (bisected when it ends sooner). Dispatch is unchanged.
    The sweep costs more solves: about 0.14 s on the 24-period test day (under
    #494's 0.5 s bar) and several times main's figure on a full horizon, inside
    the one-minute solver tick.
  • Devhub validation: confirmed live on devhub (HA 2026.10.2) at f5579ba
    (release/0.94.481), installed via HACS and restarted at 15:17 AEST; Home
    Assistant was back at 15:17:43 and Nimbus loaded. Since then the solver has
    cycled with no solver failure, no #773 fallback and no new Nimbus ERROR or
    traceback against the pre-install log; the Forecaster sensors refreshed by 15:45.
    • Not observable on devhub: the offer curve itself. devhub's own
      offer-curve sensor cannot register (a mirrored entity holds its name), so
      the change this release makes is carried by #1993's tests, not by a devhub
      reading.
  • Consumer check: on an install with the offer curve switched on, each
    published import and export point, and the price range shown with it, now
    matches what a plan at that price would do; the plan itself is unchanged.

v0.94.480

Choose a tag to compare

@github-actions github-actions released this 22 Oct 01:25
17f933a

A battery above its Max SoC with terminal-value tiers set no longer loses the whole plan; two flex-signal fixes.

  • A battery's plan-consistent headroom never exceeds its physical headroom
    (#1985). For a battery
    already charging or discharging flat out, the flex signals'
    available_up_ranging_kw / available_down_ranging_kw could report room it
    did not have, read from the solver's ranging of the limit itself. They are now
    clamped to the physical figure. Dispatch is unchanged.

  • A battery above its Max SoC no longer loses the whole plan when terminal-value
    tiers are set
    (#1987).
    A live reading over Max SoC that could not discharge back under it by the tier
    period made every solve infeasible, so nothing was planned for any battery or
    load. The tier row now takes the excess off, as it already did below Min SoC
    (#328). Plans that end within Max SoC are unchanged.

  • A load's shut period always reads as degenerate
    (#1981). A period
    outside an adequacy load's window has a zero band, but its degenerate flag in
    the flex signals' load_signals followed the solver's unclamped ranging, so
    another load in the same solve could turn it off. It now follows the band.
    Dispatch is unchanged.

  • Devhub validation: confirmed live on devhub (HA 2026.10.2) at d74c74c
    (release/0.94.480), installed via HACS and restarted at 08:06 AEST. The new
    code is the one running: devhub's own log reports the departure-target warning
    from solver/network.py line 5213 (5192 in 0.94.479; #1987's tier change moved
    it). Its 08:15 solve came back optimal in every phase, and the Forecaster
    sensors refreshed by 08:20. No new Nimbus ERROR or traceback against the
    pre-install log; the rest is devhub's known baseline.

    • Not exercised on devhub: a battery above Max SoC with terminal-value
      tiers (#1987). devhub's battery is not over Max SoC; the tests in #1988 carry it.
  • Consumer check: nothing changes for a plan that stays within Max SoC. An install
    with terminal-value tiers set and a battery reading above Max SoC now gets a plan
    instead of none. On the Flex tab, a battery charging or discharging flat out no
    longer shows ranged headroom it does not have, and a load's shut periods always
    read as degenerate.

v0.94.479

Choose a tag to compare

@code-imstillalive code-imstillalive released this 21 Oct 08:57
5e7eb12

DC-006 slice 2: the Forecaster reads the device setup in active.

  • Device setup, the Forecaster in active (#1574, DC-006 slice 2). With the
    device setup in active, each Forecaster model reads its battery, grid and
    solar power inputs from the device setup: in the sign it was trained with,
    the last good reading held for up to its max age when one goes missing, and
    then the model's own training mean (never 0) until it returns. A model
    retrained in active learns the setup's sign (battery discharge-positive).
    legacy and shadow installs read exactly what they read before; on a
    healthy site a model trained in legacy is fed identical inputs in
    active.
  • Devhub validation: confirmed live on devhub (HA 2026.10.2) at ab0146b
    (release/0.94.479), installed via HACS and restarted at 18:40 AEST; devhub's
    own Forecaster sensors published by 18:40:59. devhub's device setup is
    active (revision 1, clean), so this release's code path is the one running.
    The log after the restart showed only devhub's known baseline (mirror
    duplicate-unique-ID notices, Forecaster rename notices).
    • Not claimed yet: a retrain in active (the model learning the setup's
      sign). devhub's models were last trained at 03:27; the first retrain on
      this release is checked on the day-long devhub run before slice 3.
  • Consumer check: on an install in legacy or shadow, the Forecaster tab's
    forecasts are unchanged from 0.94.478. In active, a battery, grid or solar
    sensor that drops out keeps its last reading for its max age instead of
    falling to 0.

v0.94.478

Choose a tag to compare

@code-imstillalive code-imstillalive released this 21 Oct 05:58
88e1208

The P2P export bonus is claimed in one block again.

  • The export bonus is claimed in one block again
    (#1964). With a
    flat bonus price and a cap that leaves one period partly claimed, the bonus
    could scatter ON/OFF/ON across the window (the lightning bolt dropping out),
    because its latest-first tie-break was smaller than the solver's own
    tolerance. It is now a tie-break on the secondary objective, as the other
    tie-breaks have been since #696, so it no longer meets a real price. A plan
    solved without the calibrated objective keeps the old tie-break.

  • Devhub validation: confirmed live on devhub (HA 2026.10.2) at 672a16e
    (release/0.94.478), installed via HACS and restarted at 15:53 AEST;
    devhub's own Nimbus sensors published 0.94.478 by 15:56. The log after the
    restart showed only devhub's known baseline (mirror duplicate-unique-ID
    notices). devhub's own plan entity is unavailable (its known limitation),
    so the bonus block is checked on production's first P2P window.

  • Consumer check: on the Solver tab's Whole Plan, the P2P export bonus
    (lightning bolt) runs as one unbroken block to the end of the window,
    without dropping out and back in.

v0.94.477

Choose a tag to compare

@code-imstillalive code-imstillalive released this 21 Oct 04:52
0a94b25

Price sources learn each source's steady premium. Another retailer's
fees no longer pull the blend up or count as forecast error.

  • Devhub validation: confirmed live on devhub (HA 2026.10.2) at 21639d0
    (release/0.94.477), installed via HACS and restarted at 14:46; devhub's
    own Nimbus sensors published 0.94.477 by 14:50. The log after the restart
    showed only devhub's known baseline (mirror duplicate-unique-ID notices,
    recorder attribute-size warnings, rename collisions); no price
    consolidation errors. devhub's own plan entity is unavailable (its known
    limitation), so the bias summary is checked on production's first plans.

  • Price sources: a steady premium is not forecast error (#1786). A source
    priced on another contract (e.g. a retailer that adds hedging and fees per
    kWh) sits a steady amount above the provider's settled price. Each source's
    signed error is now tracked per lead as a bias; its MAE scores what is left
    after removing it, and once a source has earned a weight it joins the blend
    with its bias removed, so the blend is no longer pulled up by another
    contract's fees. The table still shows each source's own price, spikes are
    still judged on raw prices, and the spread is unchanged. Shadow only while
    consolidation is off.

v0.94.476

Choose a tag to compare

@github-actions github-actions released this 21 Oct 03:59
b2e1205

The Now column shows your provider's price. On the first live plan with
0.94.475 the provider's cell under Now was a dash and the Gap was blank.

  • The Now column shows your provider's price and the Gap. On the first
    live plan with 0.94.475, the provider's cell under Now was a dash and the
    Gap under Now was blank: the provider's series covers only the periods its
    forecast does, and the running interval is settled. The provider's price
    for now is the price that settles for it, and the Now column shows it.

  • Devhub validation: confirmed live on devhub (HA 2026.10.2) at 43d97c1,
    installed untagged via HACS from release/0.94.476 and restarted (the
    recorder's run began 13:55:44 AEST, 21 Oct). devhub's own per-battery SoC
    sensors published on 0.94.476 at 13:56:25. The log shows only the
    devhub-only baseline (duplicate unique IDs, Forecaster entity renames left
    in place); nothing from this release.

    • Not claimed live: the provider's Now value. devhub's Price sources
      card reads production's mirrored plan. The defect was seen live on
      production's first 0.94.475 plan (13:36 AEST, now.sources.primary = None); the fix is covered by tests/test_consolidation_next_slots.py
      and the golden snapshots.
  • Consumer check: on the Solver tab, the Price sources Now column shows your
    provider's price for the interval running now (the Whole Plan's Buy price
    for that period) and a Gap under it.

v0.94.475

Choose a tag to compare

@github-actions github-actions released this 21 Oct 03:28
bc7701e

Going live, and three fixes you can see. A step-by-step guide and a
ready-made automation for letting Nimbus drive the battery; the Price sources
table's Now column as one column; Prices ahead full width on the first visit;
and a deferrable load's value per kWh counted again without windows.

  • The Price sources table's Now column is one column, no extra row
    (household, 21 Oct 2026). 0.94.474 added a Settled row under the header;
    it is gone. The Now column shows each source's own price for the interval
    running now, the blend, and the blend's gap to your provider, like every
    other column.

  • Prices ahead draws full width on the first visit. On the Solver tab
    the chart drew a third wide until you pressed F5: drawn from the plan alone,
    it drew before its section had a width. It now waits for one hidden series
    from history, as the battery chart above it does. Checked on devhub against
    an unchanged copy and a redraw-on-resize copy: only this one was full width
    on every first visit.

  • Going live, step by step, with a ready-made automation (1.0.0,
    #1930). A new
    Going live guide takes a household from shadow to Nimbus driving the
    battery: watch the plan in dry run, build your inverter's actions, create an
    arm switch, import the Nimbus battery dispatch blueprint
    (blueprints/automation/nimbus/battery_dispatch.yaml), and a supervised
    first trial. The blueprint works with any inverter you can command from
    Home Assistant: you give it your own actions for Charge, Discharge,
    Self-Consume, Hold and a fallback. Nothing moves unless its arm switch is
    on; switching it off runs the fallback; an unknown, failed or stale plan
    runs the fallback, never a power command; power is capped; a minimum dwell
    stops the battery flipping between modes; and spare solar is soaked up when
    Nimbus says so. Each mode command, the fallback included, is re-sent after
    a Home Assistant start and every 10 minutes (adjustable), so a lost command
    is put right (Mark Purcell's review). tests/test_battery_dispatch_blueprint.py
    runs the blueprint's own templates in CI and checks each of these
    properties.

  • A deferrable load's value per kWh counts again when it has no windows
    (#1837). Since
    0.94.206 a deferrable load set up with a value per kWh but without
    per-day windows ignored that value: with a cheap shortfall price it never
    ran, even where its value was well above the price, and with a dear one it
    ran only to avoid the shortfall. It now runs its target wherever its value
    beats the price, as a windowed load already did. Loads with windows, and
    loads with no value set, are unchanged.

  • Devhub validation: confirmed live on devhub (HA 2026.10.2) at 40af4d0,
    installed untagged via HACS from release/0.94.475 and restarted (the
    recorder's run began 13:23:30 AEST, 21 Oct). devhub's own per-battery SoC
    sensors published on 0.94.475 at 13:24:52. The log shows only the
    devhub-only baseline (duplicate unique IDs, Forecaster entity renames left
    in place); nothing from this release. Prices ahead's hidden history series
    was chosen by the household on devhub's own screen before this release:
    full width on three first visits running, where an unchanged copy and a
    redraw-on-resize copy needed a second visit. The one-column Price sources
    card is on devhub's Solver tab and renders without error.

    • Not claimed live: the Now column with real numbers. The card reads
      production's mirrored plan, which is 0.94.473 and publishes no now.
      Covered by tests/test_price_sources_card.py. The adequacy value credit:
      not exercised on a live load; covered by
      tests/v2/solver/test_adequacy_value_credit.py. The going-live blueprint
      was exercised on devhub for #1955 (logbook-only actions), not again here.
  • Consumer check: on the Solver tab, Prices ahead is full width on the first
    visit; the Price sources table's Now column is a single yellow column, with
    no Settled row, once the plan publishes now.