Skip to content

Commit 2c2feea

Browse files
Merge pull request #4555 from springfall2008/fix/solis-capacity-voltage-warned
2 parents e86772e + 9b5e1b4 commit 2c2feea

3 files changed

Lines changed: 27 additions & 2 deletions

File tree

‎apps/predbat/predbat.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import pytz
3636
import asyncio
3737

38-
THIS_VERSION = "v8.48.4"
38+
THIS_VERSION = "v8.48.5"
3939

4040
from download import predbat_update_move, predbat_update_download, check_install, DEFAULT_PREDBAT_REPOSITORY
4141
from const import MINUTE_WATT

‎apps/predbat/solis.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ def initialize(self, api_key=None, api_secret=None, inverter_sn=None, automatic=
334334

335335
# Tracking
336336
self.slots_reset = set() # Track which inverters had slots reset
337+
self.capacity_voltage_warned = set() # Inverters already warned about an estimated capacity voltage
337338

338339
self.log(f"Solis API: Initialised with inverter_sn={self.configured_inverter_sn}, automatic={automatic}")
339340

‎apps/predbat/tests/test_solis.py‎

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ def __init__(self, prefix="predbat"):
6666
# Cache structures
6767
self.cached_values = {}
6868
self.inverter_details = {}
69-
self.storage_modes = {}
7069
self.parallel_battery_count = {}
7170
self.max_charge_current = {}
7271
self.max_discharge_current = {}
@@ -778,6 +777,30 @@ def test_solis_activated_with_api_key():
778777
return failed
779778

780779

780+
def test_initialize_attribute_parity_with_mock():
781+
"""Every attribute MockSolisAPI stubs must also be set by the real SolisAPI.initialize().
782+
783+
MockSolisAPI replaces __init__ wholesale, so an attribute added to the mock but forgotten in
784+
the real initialize() passes every unit test here and then raises AttributeError against a
785+
live inverter — which is exactly how capacity_voltage_warned shipped broken in #4502.
786+
"""
787+
failed = False
788+
# Attributes that exist only to drive the test harness and have no production counterpart.
789+
test_only = {"_test_now_utc_exact", "log_messages", "dashboard_items", "read_and_write_cid_calls", "set_storage_mode_calls"}
790+
component = _init_solis_component({"solis_api_key": "k", "solis_api_secret": "s"})
791+
if component is None:
792+
print("ERROR: Solis should activate with api_key + api_secret")
793+
return True
794+
mock_attrs = set(vars(MockSolisAPI()).keys()) - test_only
795+
missing = sorted(attr for attr in mock_attrs if not hasattr(component, attr))
796+
if missing:
797+
print("ERROR: SolisAPI.initialize() does not set attributes stubbed by MockSolisAPI: {}".format(missing))
798+
failed = True
799+
if not failed:
800+
print("PASSED: SolisAPI.initialize() sets every attribute MockSolisAPI stubs")
801+
return failed
802+
803+
781804
def test_solis_activated_with_oauth_token():
782805
"""Solis activates in OAuth mode when auth_method=oauth + access_token are configured (no api_key)."""
783806
failed = False
@@ -1018,6 +1041,7 @@ def run_solis_tests(my_predbat):
10181041
failed |= test_solis_not_activated_without_credentials()
10191042
failed |= test_solis_activated_with_api_key()
10201043
failed |= test_solis_activated_with_oauth_token()
1044+
failed |= test_initialize_attribute_parity_with_mock()
10211045
failed |= asyncio.run(test_oauth_execute_request_refreshes_before_call())
10221046
failed |= asyncio.run(test_oauth_endpoint_namespace_translation())
10231047
failed |= asyncio.run(test_oauth_execute_request_aborts_when_token_missing())

0 commit comments

Comments
 (0)