diff --git a/solax/inverters/x1_lite_lv.py b/solax/inverters/x1_lite_lv.py index f2fef33..5bb0638 100644 --- a/solax/inverters/x1_lite_lv.py +++ b/solax/inverters/x1_lite_lv.py @@ -3,8 +3,8 @@ import voluptuous as vol from solax.inverter import Inverter -from solax.units import DailyTotal, Total, Units -from solax.utils import div10, div100, pack_u16, to_signed, to_signed32, twoway_div10 +from solax.units import Total, Units +from solax.utils import div10, div100, pack_u16, to_signed, twoway_div10 class X1LiteLV(Inverter): @@ -12,14 +12,12 @@ class X1LiteLV(Inverter): _schema = vol.Schema( { vol.Required("type"): int, - vol.Required( - "sn", - ): str, + vol.Required("sn"): str, vol.Required("ver"): str, vol.Required("data"): vol.Schema( vol.All( [vol.Coerce(float)], - vol.Length(min=200, max=200), + vol.Length(min=200, max=300), ) ), vol.Required("information"): vol.Schema(vol.All(vol.Length(min=1, max=15))), @@ -29,7 +27,7 @@ class X1LiteLV(Inverter): @classmethod def build_all_variants(cls, host, port, pwd=""): - versions = [cls._build(host, port, pwd)] + versions = [cls._build(host, port, pwd), cls._build(host, port, pwd, False)] return versions @classmethod @@ -39,14 +37,14 @@ def response_decoder(cls): """ return { "AC Voltage": (0, Units.V, div10), - "AC Output Current": (1, Units.A, twoway_div10), - "AC Output Power": (2, Units.W, to_signed), + "AC Current": (1, Units.A, twoway_div10), + "AC Power": (2, Units.W, to_signed), "AC Frequency": (3, Units.HZ, div100), "Grid PF": (4, Units.PERCENT, div10), ################################### "AC Voltage Out": (97, Units.V, div10), - # "AC current Out": (98, Units.A, twoway_div10), - # "AC power Out": (99, Units.W, to_signed), + # "AC Current Out": (98, Units.A, twoway_div10), + # "AC Power Out": (99, Units.W, to_signed), "AC Frequency Out": (101, Units.HZ, div10), # "Inverter Status 1 ?": (15, Units.NONE), # 2 - Normal Mode, 7 - EPSMode # "Inverter Status 2 ?": (16, Units.NONE), # 4 - Normal Mode, 5 - EPSMode @@ -54,7 +52,7 @@ def response_decoder(cls): "Grid Power": (32, Units.W, twoway_div10), # "Grid power 1": (33, Units.W, twoway_div10), # "Grid power 2": (34, Units.W, twoway_div10), - "Hourly Energy": (51, DailyTotal(Units.KWH), div100), + "Hourly Energy": (51, Total(Units.KWH), div100), ############################### "PV1 Voltage": (5, Units.V, div10), "PV2 Voltage": (7, Units.V, div10), @@ -65,13 +63,18 @@ def response_decoder(cls): "PV1 Power": (11, Units.W), "PV2 Power": (12, Units.W), "PV3 Power": (13, Units.W), - "Total PV Power": (14, Total(Units.KWH), to_signed), - "Today's PV Energy": (52, DailyTotal(Units.KWH), twoway_div10), + "Total PV Power": (14, Units.W), + "Daily PV Energy": (52, Total(Units.KWH), twoway_div10), "Total PV Energy": (53, Total(Units.KWH), twoway_div10), ################################ + "Inverter Temperature": (68, Units.C, div10), + "Inverter Temperature 1": (69, Units.C, div10), + "Inverter Temperature 2": (70, Units.C, div10), + "Inverter Temperature 3": (71, Units.C, div10), + ################################ "Battery Type": (27, Units.NONE), # Undefined - "Battery voltage": (23, Units.V, div10), - "Battery current": (24, Units.A, twoway_div10), + "Battery Voltage": (23, Units.V, div10), + "Battery Current": (24, Units.A, twoway_div10), "Total Battery power": (25, Units.W, twoway_div10), ########################### "Battery SoC": (75, Units.PERCENT, div10), @@ -80,28 +83,58 @@ def response_decoder(cls): "Battery Temperature 3": (74, Units.C), "Battery Temperature 4": (78, Units.C), "Battery Temperature": (79, Units.C), - "Battery Charge total": (pack_u16(26, 27), Units.KWH, div10), - "Battery Discharge total": (pack_u16(28, 29), Units.KWH, div10), - "Battery Charge today": (30, Units.KWH, div10), - "Battery Discharge today": (31, Units.KWH, div10), - "Charging Duration": (pack_u16(80, 81), Units.NONE, to_signed32), - "Today's Battery Discharge": (30, DailyTotal(Units.KWH), div10), + #################################### + "Daily Battery Charge": (30, Total(Units.KWH), div10), + "Total Battery Charge": ( + pack_u16(26, 27), + Total(Units.KWH), + twoway_div10, + ), + "Daily Battery Discharge": (31, Total(Units.KWH), div10), "Total Battery Discharge": ( pack_u16(28, 29), Total(Units.KWH), twoway_div10, ), - "Today's Battery Charge": (31, DailyTotal(Units.KWH), div10), - "Total Battery Charge": (pack_u16(26, 27), Total(Units.KWH), twoway_div10), ################ - "Today's Generated Energy": (21, DailyTotal(Units.KWH), div10), - "Total Generated Energy": (pack_u16(17, 18), Total(Units.KWH), div10), - "Today's EPS Energy": (46, DailyTotal(Units.KWH), div10), - "Total EPS Energy": (pack_u16(47, 48), Total(Units.KWH), div10), - "Today's Import Energy": (40, DailyTotal(Units.KWH), div10), - "Total Import Energy": (pack_u16(36, 37), Total(Units.KWH), div10), + "Daily Inverter Output": (21, Total(Units.KWH), div10), + "Total Inverter Output": ( + pack_u16(17, 18), + Total(Units.KWH), + div10, + ), + "Daily Inverter EPS Energy": (46, Total(Units.KWH), div10), + "Total Inverter EPS Energy": ( + pack_u16(47, 48), + Total(Units.KWH), + div10, + ), + "Daily Imported Energy": (40, Total(Units.KWH), div10), + "Total Imported Energy": ( + pack_u16(36, 37), + Total(Units.KWH), + div10, + ), } + @classmethod + def dongle_serial_number_getter(cls, response: Dict[str, Any]) -> Optional[str]: + info = response.get("information", []) + return info[2] if len(info) > 2 else None + @classmethod def inverter_serial_number_getter(cls, response: Dict[str, Any]) -> Optional[str]: - return response["information"][2] + info = response.get("information", []) + return info[2] if len(info) > 2 else None + + # @classmethod + # def inverter_versions_getter( + # cls, response: Dict[str, Any] + # ) -> Optional[Dict[str, str]]: + # i = response["information"] + # return { + # "Main DSP": f"{i[4]:03.2f}", + # "Slave DSP": f"{i[5]:03.2f}", + # "ARM": f"{i[6]:03.2f}-{i[7]:03.2f}", + # "Module version": response["ver"], + # } diff --git a/tests/fixtures.py b/tests/fixtures.py index 0d7c2eb..62ac18c 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -12,7 +12,6 @@ X1_BOOST_VALUES_V3, X1_HYBRID_G4_V_3_018_VALUES, X1_HYBRID_G4_VALUES, - X1_LITE_LV_80_VALUES, X1_MINI_G4_VALUES, X1_MINI_VALUES, X1_MINI_VALUES_V34, @@ -30,6 +29,8 @@ X3V34_HYBRID_VALUES_EPS_MODE, X3V34_HYBRID_VALUES_NEGATIVE_POWER, XHYBRID_VALUES, + X1_LITE_LV_80_v002_VALUES, + X1_LITE_LV_80_v005_VALUES, ) from tests.samples.responses import ( QVOLTHYBG33P_RESPONSE_V34, @@ -42,7 +43,6 @@ X1_HYBRID_G3_RESPONSE, X1_HYBRID_G4_RESPONSE, X1_HYBRID_G4_V_3_018_RESPONSE, - X1_LITE_LV_80_RESPONSE, X1_MINI_G4, X1_MINI_RESPONSE_V34, X1_MINI_RESPONSE_V34_VER3, @@ -60,6 +60,8 @@ X3_ULTRA_RESPONSE, XHYBRID_DE01_RESPONSE, XHYBRID_DE02_RESPONSE, + X1_LITE_LV_80_v002_RESPONSE, + X1_LITE_LV_80_v005_RESPONSE, ) X_FORWARDED_HEADER = {"X-Forwarded-For": "5.8.8.8"} @@ -203,9 +205,19 @@ def simple_http_fixture(httpserver): uri="/", method="POST", query_string="optType=ReadRealTimeData", - response=X1_LITE_LV_80_RESPONSE, + response=X1_LITE_LV_80_v002_RESPONSE, inverter=inverter.X1LiteLV, - values=X1_LITE_LV_80_VALUES, + values=X1_LITE_LV_80_v002_VALUES, + headers=None, + data=None, + ), + InverterUnderTest( + uri="/", + method="POST", + query_string="optType=ReadRealTimeData", + response=X1_LITE_LV_80_v005_RESPONSE, + inverter=inverter.X1LiteLV, + values=X1_LITE_LV_80_v005_VALUES, headers=None, data=None, ), diff --git a/tests/samples/expected_values.py b/tests/samples/expected_values.py index f76f1bf..e716de1 100644 --- a/tests/samples/expected_values.py +++ b/tests/samples/expected_values.py @@ -558,10 +558,10 @@ "Total Import Energy": 0.0, } -X1_LITE_LV_80_VALUES = { +X1_LITE_LV_80_v002_VALUES = { "AC Voltage": 239.7, - "AC Output Current": 0.9, - "AC Output Power": 1280, + "AC Current": 0.9, + "AC Power": 1280, "AC Frequency": 50.02, "Grid PF": 100.0, "AC Voltage Out": 229.5, @@ -578,11 +578,15 @@ "PV2 Power": 985.0, "PV3 Power": 0.0, "Total PV Power": 0.0, - "Today's PV Energy": 0.2, + "Daily PV Energy": 0.2, "Total PV Energy": 255.0, + "Inverter Temperature": 41.0, + "Inverter Temperature 1": 35.0, + "Inverter Temperature 2": 33.0, + "Inverter Temperature 3": 41.0, "Battery Type": 0.0, - "Battery voltage": 52.6, - "Battery current": -7.3, + "Battery Voltage": 52.6, + "Battery Current": -7.3, "Total Battery power": -38.8, "Battery SoC": 62.0, "Battery Temperature 1": 19.0, @@ -590,21 +594,63 @@ "Battery Temperature 3": 22.0, "Battery Temperature 4": 19.0, "Battery Temperature": 19.0, - "Battery Charge total": 111.4, - "Battery Discharge total": 163.0, - "Battery Charge today": 0.0, - "Battery Discharge today": 4.0, - "Charging Duration": 0.0, - "Today's Battery Discharge": 0.0, - "Total Battery Discharge": 163.0, - "Today's Battery Charge": 4.0, + "Daily Battery Charge": 0.0, "Total Battery Charge": 111.4, - "Today's Generated Energy": 0.0, - "Total Generated Energy": 120.6, - "Today's EPS Energy": 4.7, - "Total EPS Energy": 224.5, - "Today's Import Energy": 3.2, - "Total Import Energy": 282.9, + "Daily Battery Discharge": 4.0, + "Total Battery Discharge": 163.0, + "Daily Inverter Output": 0.0, + "Total Inverter Output": 120.6, + "Daily Inverter EPS Energy": 4.7, + "Total Inverter EPS Energy": 224.5, + "Daily Imported Energy": 3.2, + "Total Imported Energy": 282.9, +} +X1_LITE_LV_80_v005_VALUES = { + "AC Voltage": 0, + "AC Current": 0, + "AC Power": 0, + "AC Frequency": 0, + "Grid PF": 100.0, + "AC Voltage Out": 228.5, + "AC Frequency Out": 49.9, + "Grid Power": 0.0, + "Hourly Energy": 97.28, + "PV1 Voltage": 346.6, + "PV2 Voltage": 287.5, + "PV3 Voltage": 0.0, + "PV1 Current": 7.3, + "PV2 Current": 0.6, + "PV3 Current": 0.0, + "PV1 Power": 2544.0, + "PV2 Power": 182.0, + "PV3 Power": 0.0, + "Total PV Power": 2726.0, + "Daily PV Energy": 5.2, + "Total PV Energy": 1560.4, + "Inverter Temperature": 43.0, + "Inverter Temperature 1": 45.0, + "Inverter Temperature 2": 45.0, + "Inverter Temperature 3": 51.0, + "Battery Type": 0.0, + "Battery Voltage": 53.8, + "Battery Current": 48.0, + "Total Battery power": 258.7, + "Battery SoC": 94.0, + "Battery Temperature 1": 26.0, + "Battery Temperature 2": 37.0, + "Battery Temperature 3": 39.0, + "Battery Temperature 4": 26.0, + "Battery Temperature": 26.0, + "Daily Battery Charge": 5.2, + "Total Battery Charge": 919.0, + "Daily Battery Discharge": 0.1, + "Total Battery Discharge": 346.5, + "Daily Inverter Output": 0.0, + "Total Inverter Output": 581.0, + "Daily Inverter EPS Energy": 6.3, + "Total Inverter EPS Energy": 1143.9, + "Daily Imported Energy": 0.0, + "Total Imported Energy": 116.1, } QVOLTHYBG33P_VALUES = { diff --git a/tests/samples/responses.py b/tests/samples/responses.py index 88ac781..84fcf64 100644 --- a/tests/samples/responses.py +++ b/tests/samples/responses.py @@ -1613,7 +1613,7 @@ "Information": [3.000, 18, "XXXXXXX", 8, 0.16, 0.00, 0.23, 0.00, 0.00, 1], } -X1_LITE_LV_80_RESPONSE = { +X1_LITE_LV_80_v002_RESPONSE = { "sn": "XXXXXXX", "ver": "1.002.09", "type": 103, @@ -1832,6 +1832,325 @@ 1, ], } +X1_LITE_LV_80_v005_RESPONSE = { + "sn": "XXXXXXX", + "ver": "1.005.04", + "type": 103, + "Data": [ + 0, + 0, + 0, + 0, + 1000, + 3466, + 73, + 2875, + 6, + 0, + 0, + 2544, + 182, + 0, + 2726, + 7, + 5, + 5810, + 0, + 116, + 0, + 0, + 0, + 538, + 480, + 2587, + 9190, + 0, + 3465, + 0, + 52, + 1, + 0, + 0, + 10, + 0, + 1161, + 0, + 0, + 0, + 0, + 0, + 2288, + 6, + 139, + 5000, + 63, + 11439, + 0, + 6409, + 778, + 9728, + 52, + 15604, + 0, + 256, + 0, + 536, + 476, + 2555, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 430, + 450, + 450, + 510, + 26, + 37, + 39, + 940, + 171, + 237, + 26, + 26, + 0, + 0, + 0, + 1000, + 0, + 0, + 0, + 15, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2285, + 0, + 0, + 0, + 499, + 1, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 255, + 184, + 0, + 0, + 420, + 1180, + 44, + 65, + 187, + 722, + 3398, + 2580, + 34043, + 0, + 0, + 0, + 0, + 0, + 0, + 427, + 4, + 6399, + 7, + 2613, + 1, + 0, + 65, + 0, + 0, + 3, + 30, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + "Information": [ + 8.000, + 103, + "XXXXXXX", + 13, + 25.10, + 0.00, + 25.10, + 1.13, + 0.00, + 1, + ], +} X3_MIC_RESPONSE = { "type": "X3-MIC",