You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(solis): guard battery_scaling against a documented 0% SOH API response (#4500)
* fix(solis): guard battery_scaling against a documented 0% SOH API response (#4494)
A Solis Cloud API batteryHealthSoh of 0 is a documented, valid response (not
"no battery"), but was previously treated as falsy in automatic_config()'s
battery detection and, once bound to the live SOH sensor, fed straight into
soc_max = nominal_capacity * battery_scaling - collapsing soc_max to 0 and
making best_soc_keep permanently unreachable, forcing continuous grid
charging regardless of price. Reported with full root-cause trace by
@jibbej.
- inverter.py: a battery_scaling reading of 0 or negative is ambiguous
(flaky API vs a genuinely unhealthy battery), so rather than asserting
either extreme, retain the last value that was actually read as valid
(mirrors the existing soc_max_nominal fallback pattern), falling back to
1.0 only if nothing valid has ever been read.
- solis.py automatic_config(): a battery_soh of 0 no longer excludes the
inverter from configuration the same way a genuinely missing field does,
which previously caused automatic_config() to abandon configuration
entirely (load_today/charge_start_time left unset) and crash-loop.
* feat(components): warn once when auto-discovery overrides an apps.yaml value (#4494 follow-up)
Reviewer feedback on PR #4500 (jibbej): battery_scaling being silently
discarded was fixed, but the underlying discoverability problem is
generic - automatic_config() (in any cloud integration) always wins over
an explicit apps.yaml value via set_arg(), with zero indication to the
user that their setting was ignored.
Adds ComponentBase.set_arg_auto(), a drop-in replacement for set_arg()
intended for auto-discovery code: if the key had a different value in
the user's raw apps.yaml (snapshotted at the very start of
PredBat.initialize(), before Predbat's own defaulting or any component
touches self.args), logs a one-time note naming both values, then applies
the auto-discovered value exactly as before - precedence is unchanged,
only the visibility of the override is new.
Wired up for all of solis.py's automatic_config() bindings, since the
same silent-override behaviour applies equally to every key it touches,
not just battery_scaling. Other integrations are untouched for now - the
helper lives on the shared ComponentBase so adopting it elsewhere is a
follow-up, not a redesign.
self.log(f"Note: apps.yaml sets '{arg}: {raw_value}' but auto-discovery is using '{value}' instead - auto-discovery always wins currently; remove the apps.yaml entry to avoid this message")
self.log("Warn: Inverter {} battery_scaling read as {} which is not a valid scaling factor, retaining last known value {} for this cycle".format(self.id, self.battery_scaling, last_known))
print("ERROR: battery_scaling should fall back to 1.0 when source reads {} and no prior value exists, got {}".format(bad_scaling, inv.battery_scaling))
2137
+
failed=True
2138
+
2139
+
# A valid reading passes through unchanged, and is remembered
2140
+
my_predbat.args["battery_scaling"] = [0.72]
2141
+
inv=Inverter(my_predbat, 0)
2142
+
ifinv.battery_scaling!=0.72:
2143
+
print("ERROR: battery_scaling should pass a valid value through unchanged, got {}".format(inv.battery_scaling))
2144
+
failed=True
2145
+
2146
+
# A subsequent invalid reading retains the last known-good value (0.72), not 1.0 - it must
2147
+
# not be assumed the battery is now "fully healthy" just because the reading is unusable
0 commit comments