Skip to content

fix(octopus): choose on purpose between conflicting catalogue entries for a car (#5438) - #5439

Open
bootc wants to merge 2 commits into
springfall2008:mainfrom
bootc:5438-octopus-catalogue-ambiguous
Open

bootc wants to merge 2 commits into
springfall2008:mainfrom
bootc:5438-octopus-catalogue-ambiguous

Conversation

@bootc

@bootc bootc commented Oct 8, 2026

Copy link
Copy Markdown

Octopus's charge-point and vehicle catalogue isn't unique by make and model, and the device lookup kept whichever match came last. So a 7.4 kW zappi was planned at 22 kW: the catalogue lists Myenergi / zappi (all models) at both 7.400 and 22.000 kW. And because fetch.py takes the larger of the Octopus figure and car_charging_rate, the user's own setting couldn't bring it back down. In the catalogue cached on my system, 142 of 311 charge-point make+model pairs and 169 of 1322 vehicle pairs map to more than one value.

Closes #5438.

The change

  • catalogue_value() gathers every matching value, and when they disagree it picks one on purpose:

    • Charge point: the lowest power listed, which is the most every variant can do. Octopus's figure only ever raises input_number.predbat_car_charging_rate, so a user with a faster charger still gets their rate by setting it.
    • Vehicle: the largest battery size listed, so the car's remaining charge is over-estimated rather than under-estimated.
  • The component warns once per make and model, naming the values and the one in use. For a charger the warning also names the setting that decides the rate; for a vehicle it says car_charging_battery_size can't change it. Example:

    Warn: OctopusAPI: Octopus's catalogue lists charge point Myenergi 'zappi (all models)' at more than one power (7.4, 22 kW) and Predbat can't tell which yours is, so it uses the lowest, 7.4 kW, unless input_number.predbat_car_charging_rate (_1, _2 for further cars) is higher. Set that to your charger's rate
    
  • The figures are converted to float. Values that are missing, non-numeric, non-finite or not above zero are ignored. GraphQL returns them as strings ("22.000"), which the discovery coordinator's typed ratings container dropped: Coordinator: octopus ratings.charge_point_power_kw value does not fit the container's type - dropped. The planner was unaffected by that part, because fetch.py already converts them.

  • The misleading # Take the max as Octopus over reports comment in fetch.py is corrected. The code under it is unchanged.

  • The Octopus direct-connection section of docs/car-charging.md now explains the lookup, what happens on an ambiguous entry, and which setting to change.

Where this departs from the issue

The issue suggested skipping an ambiguous catalogue value and using the configured settings, and letting a configured value override the catalogue. I didn't do either:

  • Skipping the value. For a charger, skipping is the same as taking the lowest, except when the configured rate is below every catalogue figure. For a vehicle it would fall back to car_charging_battery_size, which is 100 kWh when it isn't set. That's further off than any of the catalogue's own variants.
  • Letting car_charging_rate cap the Octopus figure. I've left fetch.py's max() as it is. It was added on purpose in Fix octopus intelligent slot crash #2855, and the default (7.4) can't be told apart from a rate the user set. Changing it could lower the rate for owners of faster chargers who rely on Octopus's figure.
  • Letting car_charging_battery_size win over Octopus's battery size. Four templates (givenergy_cloud, givenergy_ems, huawei, solaredge) ship car_charging_battery_size: [75] uncommented. Preferring the setting would swap the real size from Octopus for that placeholder.

Who sees a change

  • Owners of a charger whose model is listed at several powers, who had been getting a higher figure only because of catalogue order. They are now planned at the lowest figure, or at their configured rate if that's higher. Someone with a genuinely 22 kW zappi who left input_number.predbat_car_charging_rate at 7.4 now gets 7.4 kW, and the warning tells them what to set.
  • Owners of a vehicle whose model is listed at several battery sizes. They now get the largest size rather than the last one listed.
  • Unambiguous entries behave as before, except that the HA attribute is now a number rather than a string. fetch.py reads it with float() either way.

Tests

  • catalogue_value(): unique, agreeing and conflicting matches; strings converted; null, missing, non-numeric, NaN, infinite, negative and zero values ignored; no such make or model.
  • async_get_intelligent_devices() with the catalogue mocked: the lowest power or largest size is chosen for conflicting entries and the unique ones come through, all as floats. There's one warning per ambiguous make and model over two polls, and the ratings survive the coordinator.
  • End to end: the device goes through the component's own intelligent_dispatch sensor to the real fetch_sensor_data_cars(). It is planned at 7.4 kW, not 22. A configured 3.7 is raised to 7.4, and a configured 11 still wins.
  • I checked each guard by reintroducing the bug, and each makes the new tests fail with a message naming it: last match wins, first match wins, highest charger power, raw strings, no finite/positive check, no warn-once, warn-once keyed on the message alone, and fetch.py not applying the Octopus figure. The fixtures list the conflicting values in different orders, so neither first-match nor last-match wins can pass by luck.
  • test_octopus_catalogue_cache now expects the battery size as 57.5 rather than "57.5".

./run_all --quick and pre-commit run --all-files pass. One correction to the issue: the catalogue spells the make Myenergi, not myenergi.

🤖 Generated with Claude Code

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new warning hard-codes the default entity prefix, making its remediation incorrect for custom-prefix installations.

1 open finding
What changed in this PR

Fixes #5438 by deterministically resolving duplicate Octopus catalogue entries.

Changes:

  • Selects minimum charger power and maximum vehicle battery size.
  • Converts valid catalogue values to floats and logs ambiguities once.
  • Adds documentation and comprehensive regression tests.
File Description
apps/​predbat/​octopus.py Implements catalogue resolution and warnings.
apps/​predbat/​fetch.py Clarifies existing rate-selection behavior.
apps/​predbat/​tests/​test_octopus_intelligent_devices.py Tests conflicts, warnings, discovery, and planning.
apps/​predbat/​tests/​test_octopus_catalogue_cache.py Updates numeric-value expectation.
docs/​car-charging.md Documents catalogue lookup behavior.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/predbat/octopus.py Outdated
bootc and others added 2 commits October 9, 2026 22:45
… for a car (springfall2008#5438)

Octopus's charge-point and vehicle catalogue isn't unique by make and
model: myenergi's "zappi (all models)" is listed at both 7.400 and 22.000
kW, and 142 charge-point and 169 vehicle names in the current catalogue
map to more than one value. The device record gives only the make and
model to match on, and the lookup kept whichever match came last, so a
7.4 kW zappi was planned at 22 kW. fetch.py then takes the larger of that
and car_charging_rate, so the user's own setting couldn't bring it back
down.

catalogue_value() now gathers every matching value and, when they
disagree, picks one on purpose:

- A charge point gets the lowest power listed: the most every variant can
  do. Since Octopus's figure only ever raises car_charging_rate, a user
  with a faster charger can still set the rate higher, and the warning
  says so.
- A vehicle gets the largest battery size listed, so the car's remaining
  charge is over- rather than under-estimated. Using no value instead
  would fall back to car_charging_battery_size, which is 100 kWh when it
  isn't set.

The component warns once per make and model. The warning names the
values and the one in use. For a charger it also says that
input_number.predbat_car_charging_rate decides the rate when it's
higher; for a vehicle it says car_charging_battery_size can't change it.

It also converts the figures to float, ignoring any that are missing,
non-numeric, non-finite or not above zero. GraphQL returns them as
strings ("22.000"), which the discovery coordinator's ratings container
refused ("value does not fit the container's type - dropped"). The
planner was unaffected by that part, because fetch.py already converts
them.

Two things are deliberately left alone:

- fetch.py's max(rate, car_charging_rate), whose misleading "Octopus over
  reports" comment is corrected. It was added in springfall2008#2855, and the default
  car_charging_rate (7.4) can't be told apart from one the user set, so
  letting it cap the Octopus figure could lower the rate for owners of
  faster chargers who rely on it.
- An Octopus battery size still replaces car_charging_battery_size. The
  issue asked for the configured size to be able to win, but four
  templates (givenergy_cloud, givenergy_ems, huawei, solaredge) ship
  car_charging_battery_size: [75] uncommented. Users of those templates
  would lose the real size from Octopus for the template's placeholder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ix in use (springfall2008#5438)

The ambiguous-charger warning told the user to set
input_number.predbat_car_charging_rate, but the entity prefix is
configurable (apps.yaml prefix), so with a custom prefix it named an
entity that doesn't exist. It now uses the component's own prefix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bootc
bootc force-pushed the 5438-octopus-catalogue-ambiguous branch from 4857128 to c900c30 Compare October 9, 2026 21:48

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Octopus: 7.4 kW zappi planned at 22 kW: catalogue names aren't unique, and the last match wins

2 participants