From b6917bcf3eb6e1f906daffae26716c11aa7a024b Mon Sep 17 00:00:00 2001 From: Robin Wohlers-Reichel Date: Sun, 11 Jun 2023 09:55:05 +1000 Subject: [PATCH] progress --- solax/inverter.py | 31 +++++++-------- solax/inverters/x1_boost.py | 4 +- solax/inverters/x3_hybrid_g4.py | 7 +++- tests/fixtures.py | 70 ++++++++++++++++++++++----------- 4 files changed, 70 insertions(+), 42 deletions(-) diff --git a/solax/inverter.py b/solax/inverter.py index b4393c2..4f8da9b 100644 --- a/solax/inverter.py +++ b/solax/inverter.py @@ -161,6 +161,15 @@ def map_response_v2( for k, mapping_instance in self.inverter_definition().mapping.items(): accumulator[k] = self.apply_transforms(data, mapping_instance) return accumulator + + _schema: vol.Schema = vol.Schema({}) + + @classmethod + def schema(cls) -> vol.Schema: + """ + Return schema + """ + return cls._schema def handle_response(self, resp: bytes) -> InverterResponse: """ @@ -176,7 +185,7 @@ def handle_response(self, resp: bytes) -> InverterResponse: raw_json = resp.decode("utf-8").replace(",,", ",0.0,").replace(",,", ",0.0,") json_response = loads(raw_json) try: - response = self.common_response_schema()(json_response) + response = self.schema()(json_response) except (Invalid, MultipleInvalid) as ex: _ = humanize_error(json_response, ex) raise @@ -192,22 +201,12 @@ def handle_response(self, resp: bytes) -> InverterResponse: ) def identify(self, response: bytes) -> bool: - inverter_response = self.handle_response(response) - actual_inverter_type = inverter_response.inverter_type - identification = self.inverter_definition().identification - self_inverter_type = identification.inverter_type - if actual_inverter_type != self_inverter_type: + try: + inverter_response = self.handle_response(response) + except (Invalid, MultipleInvalid) as ex: + _ = humanize_error(response, ex) return False - - actual_type = inverter_response.type - old_type_prefix = identification.old_type_prefix - if old_type_prefix is not None: - return isinstance(actual_type, str) and actual_type.startswith(old_type_prefix) - - # compare type and inverter_type, - # instead of type and type, since type and inverter_type - # should be the same value if 'type' is int - return actual_type == self_inverter_type + return True def __init__(self, http_client: HttpClient): self.http_client = http_client diff --git a/solax/inverters/x1_boost.py b/solax/inverters/x1_boost.py index 995758d..45f1e2d 100644 --- a/solax/inverters/x1_boost.py +++ b/solax/inverters/x1_boost.py @@ -54,8 +54,8 @@ def response_decoder(cls) -> ResponseDecoder: "Today's Generated Energy": (13, Total(Units.KWH), div10), "Inverter Temperature": (39, Units.C), "Exported Power": (48, Units.W, to_signed), - "Total Export Energy": ((41, 50), Total(Units.KWH), (max_float, div100)), - "Total Import Energy": ((42, 52), Total(Units.KWH), (max_float, div100)), + "Total Export Energy": (50, Total(Units.KWH), div100), + "Total Import Energy": (50, Total(Units.KWH), div100), } @classmethod diff --git a/solax/inverters/x3_hybrid_g4.py b/solax/inverters/x3_hybrid_g4.py index 585c02f..cdc525b 100644 --- a/solax/inverters/x3_hybrid_g4.py +++ b/solax/inverters/x3_hybrid_g4.py @@ -1,6 +1,6 @@ import voluptuous as vol -from solax.inverter import Inverter, ResponseDecoder +from solax.inverter import Inverter, InverterIdentification, ResponseDecoder from solax.units import Total, Units from solax.utils import div10, div100, to_signed, to_signed32, twoway_div10, u16_packer @@ -47,6 +47,11 @@ def _decode_run_mode(*arg: float): 9: "Idle", 10: "Standby", }.get(run_mode) + + + @classmethod + def inverter_identification(cls) -> InverterIdentification: + return InverterIdentification(14) @classmethod def response_decoder(cls) -> ResponseDecoder: diff --git a/tests/fixtures.py b/tests/fixtures.py index 9a1af4e..7698cab 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -1,6 +1,7 @@ from collections import namedtuple import pytest +import inspect import solax.inverters as inverter from tests.samples.expected_values import ( @@ -52,11 +53,29 @@ def simple_http_fixture(httpserver): InverterUnderTest = namedtuple( "InverterUnderTest", - "uri, method, query_string, response, inverter, values, headers, data, client", + "uri, method, query_string, response, inverter, values, headers, data, client, id", ) +def inverter_under_test_maker(uri: str, + method, + query_string, + response, + inverter, + values, + headers, + data, + client): + callers_local_vars = inspect.currentframe().f_back.f_locals.items() + response_var_name = [var_name for var_name, var_val in callers_local_vars if var_val is response] + assert len(response_var_name) == 1 + values_var_name = [var_name for var_name, var_val in callers_local_vars if var_val is values] + assert len(values_var_name) == 1 + id = f"{inverter.__name__}_http({client})_{response_var_name[0]}_produces_{values_var_name[0]}" + + return InverterUnderTest(uri, method, query_string, response, inverter, values, headers, data, client, id) + INVERTERS_UNDER_TEST = [ - InverterUnderTest( + inverter_under_test_maker( uri="/api/realTimeData.htm", method="GET", query_string=None, @@ -67,7 +86,7 @@ def simple_http_fixture(httpserver): data=None, client="get", ), - InverterUnderTest( + inverter_under_test_maker( uri="/api/realTimeData.htm", method="GET", query_string=None, @@ -78,7 +97,7 @@ def simple_http_fixture(httpserver): data=None, client="get", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string=None, @@ -89,7 +108,7 @@ def simple_http_fixture(httpserver): data="optType=ReadRealTimeData", client="post_data", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="optType=ReadRealTimeData", @@ -100,18 +119,18 @@ def simple_http_fixture(httpserver): data=None, client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="optType=ReadRealTimeData", response=X1_MINI_RESPONSE_V34, - inverter=inverter.X1Boost, + inverter=inverter.X1MiniV34, values=X1_MINI_VALUES_V34, headers=None, data=None, client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="optType=ReadRealTimeData", @@ -122,18 +141,18 @@ def simple_http_fixture(httpserver): data=None, client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="optType=ReadRealTimeData", response=X1_BOOST_RESPONSE, - inverter=inverter.X1Boost, + inverter=inverter.X1MiniV34, values=X1_BOOST_VALUES, headers=X_FORWARDED_HEADER, data=None, client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="optType=ReadRealTimeData", @@ -144,7 +163,7 @@ def simple_http_fixture(httpserver): data=None, client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="optType=ReadRealTimeData", @@ -155,7 +174,7 @@ def simple_http_fixture(httpserver): data=None, client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="optType=ReadRealTimeData", @@ -166,7 +185,7 @@ def simple_http_fixture(httpserver): data=None, client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="optType=ReadRealTimeData", @@ -177,7 +196,7 @@ def simple_http_fixture(httpserver): data=None, client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="optType=ReadRealTimeData", @@ -188,7 +207,7 @@ def simple_http_fixture(httpserver): data=None, client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="optType=ReadRealTimeData", @@ -199,7 +218,7 @@ def simple_http_fixture(httpserver): data=None, client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="optType=ReadRealTimeData", @@ -210,7 +229,7 @@ def simple_http_fixture(httpserver): data=None, client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="optType=ReadRealTimeData", @@ -221,7 +240,7 @@ def simple_http_fixture(httpserver): data=None, client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string=None, @@ -232,7 +251,7 @@ def simple_http_fixture(httpserver): data="optType=ReadRealTimeData", client="post_query", ), - InverterUnderTest( + inverter_under_test_maker( uri="/", method="POST", query_string="", @@ -246,12 +265,17 @@ def simple_http_fixture(httpserver): ] -@pytest.fixture(params=INVERTERS_UNDER_TEST) +def inverter_id_getter(val): + if isinstance(val, (InverterUnderTest,)): + return val.id + + +@pytest.fixture(params=INVERTERS_UNDER_TEST, ids=inverter_id_getter) def inverters_under_test(request): yield request.param.inverter -@pytest.fixture(params=INVERTERS_UNDER_TEST) +@pytest.fixture(params=INVERTERS_UNDER_TEST, ids=inverter_id_getter) def inverters_fixture(httpserver, request): httpserver.expect_request( uri=request.param.uri, @@ -268,7 +292,7 @@ def inverters_fixture(httpserver, request): ) -@pytest.fixture(params=INVERTERS_UNDER_TEST) +@pytest.fixture(params=INVERTERS_UNDER_TEST, ids=inverter_id_getter) def inverters_garbage_fixture(httpserver, request): httpserver.expect_request( uri=request.param.uri,