goodwe 0.4.6__py3-none-any.whl → 0.4.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- goodwe/dt.py +7 -1
- goodwe/et.py +35 -3
- goodwe/model.py +4 -0
- goodwe/sensor.py +19 -0
- {goodwe-0.4.6.dist-info → goodwe-0.4.7.dist-info}/METADATA +1 -1
- goodwe-0.4.7.dist-info/RECORD +16 -0
- goodwe-0.4.6.dist-info/RECORD +0 -16
- {goodwe-0.4.6.dist-info → goodwe-0.4.7.dist-info}/LICENSE +0 -0
- {goodwe-0.4.6.dist-info → goodwe-0.4.7.dist-info}/WHEEL +0 -0
- {goodwe-0.4.6.dist-info → goodwe-0.4.7.dist-info}/top_level.txt +0 -0
goodwe/dt.py
CHANGED
|
@@ -35,6 +35,12 @@ class DT(Inverter):
|
|
|
35
35
|
Calculated("ppv3",
|
|
36
36
|
lambda data: round(read_voltage(data, 30107) * read_current(data, 30108)),
|
|
37
37
|
"PV3 Power", "W", Kind.PV),
|
|
38
|
+
# ppv1 + ppv2 + ppv3
|
|
39
|
+
Calculated("ppv",
|
|
40
|
+
lambda data: (round(read_voltage(data, 30103) * read_current(data, 30104))) + (round(
|
|
41
|
+
read_voltage(data, 30105) * read_current(data, 30106))) + (round(
|
|
42
|
+
read_voltage(data, 30107) * read_current(data, 30108))),
|
|
43
|
+
"PV Power", "W", Kind.PV),
|
|
38
44
|
# Voltage("vpv4", 14, "PV4 Voltage", Kind.PV),
|
|
39
45
|
# Current("ipv4", 16, "PV4 Current", Kind.PV),
|
|
40
46
|
# Voltage("vpv5", 14, "PV5 Voltage", Kind.PV),
|
|
@@ -63,7 +69,7 @@ class DT(Inverter):
|
|
|
63
69
|
lambda data: round(read_voltage(data, 30120) * read_current(data, 30123)),
|
|
64
70
|
"On-grid L3 Power", "W", Kind.AC),
|
|
65
71
|
# 30127 reserved
|
|
66
|
-
|
|
72
|
+
PowerS("active_power", 30128, "Active Power", Kind.AC),
|
|
67
73
|
Integer("work_mode", 30129, "Work Mode code"),
|
|
68
74
|
Enum2("work_mode_label", 30129, WORK_MODES, "Work Mode"),
|
|
69
75
|
Long("error_codes", 30130, "Error Codes"),
|
goodwe/et.py
CHANGED
|
@@ -257,7 +257,8 @@ class ET(Inverter):
|
|
|
257
257
|
Apparent4("meter_apparent_power_total", 36041, "Meter Apparent Power Total", Kind.GRID),
|
|
258
258
|
Integer("meter_type", 36043, "Meter Type", "", Kind.GRID), # (0: Single phase, 1: 3P3W, 2: 3P4W, 3: HomeKit)
|
|
259
259
|
Integer("meter_sw_version", 36044, "Meter Software Version", "", Kind.GRID),
|
|
260
|
-
|
|
260
|
+
|
|
261
|
+
# Sensors added in some ARM fw update (or platform 745/753), read when flag _has_meter_extended is on
|
|
261
262
|
Power4S("meter2_active_power", 36045, "Meter 2 Active Power", Kind.GRID),
|
|
262
263
|
Float("meter2_e_total_exp", 36047, 1000, "Meter 2 Total Energy (export)", "kWh", Kind.GRID),
|
|
263
264
|
Float("meter2_e_total_imp", 36049, 1000, "Meter 2 Total Energy (import)", "kWh", Kind.GRID),
|
|
@@ -268,6 +269,15 @@ class ET(Inverter):
|
|
|
268
269
|
Current("meter_current1", 36055, "Meter L1 Current", Kind.GRID),
|
|
269
270
|
Current("meter_current2", 36056, "Meter L2 Current", Kind.GRID),
|
|
270
271
|
Current("meter_current3", 36057, "Meter L3 Current", Kind.GRID),
|
|
272
|
+
|
|
273
|
+
Energy8("meter_e_total_exp1", 36092, "Meter Total Energy (export) L1", Kind.GRID),
|
|
274
|
+
Energy8("meter_e_total_exp2", 36096, "Meter Total Energy (export) L2", Kind.GRID),
|
|
275
|
+
Energy8("meter_e_total_exp3", 36100, "Meter Total Energy (export) L3", Kind.GRID),
|
|
276
|
+
Energy8("meter_e_total_exp", 36104, "Meter Total Energy (export)", Kind.GRID),
|
|
277
|
+
Energy8("meter_e_total_imp1", 36108, "Meter Total Energy (import) L1", Kind.GRID),
|
|
278
|
+
Energy8("meter_e_total_imp2", 36112, "Meter Total Energy (import) L2", Kind.GRID),
|
|
279
|
+
Energy8("meter_e_total_imp3", 36116, "Meter Total Energy (import) L3", Kind.GRID),
|
|
280
|
+
Energy8("meter_e_total_imp", 36120, "Meter Total Energy (import)", Kind.GRID),
|
|
271
281
|
)
|
|
272
282
|
|
|
273
283
|
# Inverter's MPPT data
|
|
@@ -464,6 +474,7 @@ class ET(Inverter):
|
|
|
464
474
|
self._READ_RUNNING_DATA: ProtocolCommand = self._read_command(0x891c, 0x007d)
|
|
465
475
|
self._READ_METER_DATA: ProtocolCommand = self._read_command(0x8ca0, 0x2d)
|
|
466
476
|
self._READ_METER_DATA_EXTENDED: ProtocolCommand = self._read_command(0x8ca0, 0x3a)
|
|
477
|
+
self._READ_METER_DATA_EXTENDED2: ProtocolCommand = self._read_command(0x8ca0, 0x7d)
|
|
467
478
|
self._READ_BATTERY_INFO: ProtocolCommand = self._read_command(0x9088, 0x0018)
|
|
468
479
|
self._READ_BATTERY2_INFO: ProtocolCommand = self._read_command(0x9858, 0x0016)
|
|
469
480
|
self._READ_MPPT_DATA: ProtocolCommand = self._read_command(0x89e5, 0x3d)
|
|
@@ -472,6 +483,7 @@ class ET(Inverter):
|
|
|
472
483
|
self._has_battery: bool = True
|
|
473
484
|
self._has_battery2: bool = False
|
|
474
485
|
self._has_meter_extended: bool = False
|
|
486
|
+
self._has_meter_extended2: bool = False
|
|
475
487
|
self._has_mppt: bool = False
|
|
476
488
|
self._sensors = self.__all_sensors
|
|
477
489
|
self._sensors_battery = self.__all_sensors_battery
|
|
@@ -490,6 +502,11 @@ class ET(Inverter):
|
|
|
490
502
|
"""Filter to exclude extended meter sensors"""
|
|
491
503
|
return s.offset < 36045
|
|
492
504
|
|
|
505
|
+
@staticmethod
|
|
506
|
+
def _not_extended_meter2(s: Sensor) -> bool:
|
|
507
|
+
"""Filter to exclude extended meter sensors"""
|
|
508
|
+
return s.offset < 36058
|
|
509
|
+
|
|
493
510
|
async def read_device_info(self):
|
|
494
511
|
response = await self._read_from_socket(self._READ_DEVICE_VERSION_INFO)
|
|
495
512
|
response = response.response_data()
|
|
@@ -520,9 +537,10 @@ class ET(Inverter):
|
|
|
520
537
|
if is_2_battery(self) or self.rated_power >= 25000:
|
|
521
538
|
self._has_battery2 = True
|
|
522
539
|
|
|
523
|
-
if self.rated_power >= 15000:
|
|
540
|
+
if is_745_platform(self) or self.rated_power >= 15000:
|
|
524
541
|
self._has_mppt = True
|
|
525
542
|
self._has_meter_extended = True
|
|
543
|
+
self._has_meter_extended2 = True
|
|
526
544
|
else:
|
|
527
545
|
self._sensors_meter = tuple(filter(self._not_extended_meter, self._sensors_meter))
|
|
528
546
|
|
|
@@ -577,7 +595,21 @@ class ET(Inverter):
|
|
|
577
595
|
else:
|
|
578
596
|
raise ex
|
|
579
597
|
|
|
580
|
-
if self.
|
|
598
|
+
if self._has_meter_extended2:
|
|
599
|
+
try:
|
|
600
|
+
response = await self._read_from_socket(self._READ_METER_DATA_EXTENDED2)
|
|
601
|
+
data.update(self._map_response(response, self._sensors_meter))
|
|
602
|
+
except RequestRejectedException as ex:
|
|
603
|
+
if ex.message == ILLEGAL_DATA_ADDRESS:
|
|
604
|
+
logger.info("Extended meter values not supported, disabling further attempts.")
|
|
605
|
+
self._has_meter_extended2 = False
|
|
606
|
+
self._sensors_meter = tuple(filter(self._not_extended_meter2, self._sensors_meter))
|
|
607
|
+
response = await self._read_from_socket(self._READ_METER_DATA_EXTENDED)
|
|
608
|
+
data.update(
|
|
609
|
+
self._map_response(response, self._sensors_meter))
|
|
610
|
+
else:
|
|
611
|
+
raise ex
|
|
612
|
+
elif self._has_meter_extended:
|
|
581
613
|
try:
|
|
582
614
|
response = await self._read_from_socket(self._READ_METER_DATA_EXTENDED)
|
|
583
615
|
data.update(self._map_response(response, self._sensors_meter))
|
goodwe/model.py
CHANGED
|
@@ -48,3 +48,7 @@ def is_2_battery(inverter: Inverter) -> bool:
|
|
|
48
48
|
def is_745_platform(inverter: Inverter) -> bool:
|
|
49
49
|
return any(model in inverter.serial_number for model in PLATFORM_745_LV_MODELS) or any(
|
|
50
50
|
model in inverter.serial_number for model in PLATFORM_745_HV_MODELS)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def is_753_platform(inverter: Inverter) -> bool:
|
|
54
|
+
return any(model in inverter.serial_number for model in PLATFORM_753_MODELS)
|
goodwe/sensor.py
CHANGED
|
@@ -197,6 +197,17 @@ class Energy4(Sensor):
|
|
|
197
197
|
return float(value) / 10 if value is not None else None
|
|
198
198
|
|
|
199
199
|
|
|
200
|
+
class Energy8(Sensor):
|
|
201
|
+
"""Sensor representing energy [kWh] value encoded in 8 bytes"""
|
|
202
|
+
|
|
203
|
+
def __init__(self, id_: str, offset: int, name: str, kind: Optional[SensorKind]):
|
|
204
|
+
super().__init__(id_, offset, name, 8, "kWh", kind)
|
|
205
|
+
|
|
206
|
+
def read_value(self, data: ProtocolResponse):
|
|
207
|
+
value = read_bytes8(data)
|
|
208
|
+
return float(value) / 100 if value is not None else None
|
|
209
|
+
|
|
210
|
+
|
|
200
211
|
class Apparent(Sensor):
|
|
201
212
|
"""Sensor representing apparent power [VA] value encoded in 2 bytes"""
|
|
202
213
|
|
|
@@ -840,6 +851,14 @@ def read_bytes4_signed(buffer: ProtocolResponse, offset: int = None) -> int:
|
|
|
840
851
|
return int.from_bytes(buffer.read(4), byteorder="big", signed=True)
|
|
841
852
|
|
|
842
853
|
|
|
854
|
+
def read_bytes8(buffer: ProtocolResponse, offset: int = None, undef: int = None) -> int:
|
|
855
|
+
"""Retrieve 8 byte (unsigned int) value from buffer"""
|
|
856
|
+
if offset is not None:
|
|
857
|
+
buffer.seek(offset)
|
|
858
|
+
value = int.from_bytes(buffer.read(8), byteorder="big", signed=False)
|
|
859
|
+
return undef if value == 0xffffffffffffffff else value
|
|
860
|
+
|
|
861
|
+
|
|
843
862
|
def read_decimal2(buffer: ProtocolResponse, scale: int, offset: int = None) -> float:
|
|
844
863
|
"""Retrieve 2 byte (signed float) value from buffer"""
|
|
845
864
|
if offset is not None:
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
goodwe/__init__.py,sha256=8fFGBBvBpCo6Ew4puTtW0kYo2hVPKUx6z5A-TA4Tbvc,5795
|
|
2
|
+
goodwe/const.py,sha256=yhWk56YV7k7-MbgfmWEMYNlqeRNLOfOpfTqEfRj6Hp8,7934
|
|
3
|
+
goodwe/dt.py,sha256=TxjJ4iqvtRiHGKwlfLoYWblN-COVZ3i48PPk4z4xJcc,12482
|
|
4
|
+
goodwe/es.py,sha256=vvHmxcFykp8nhR1I8p7SF0YcYpvdCKBYacgcolbVHXI,23009
|
|
5
|
+
goodwe/et.py,sha256=Sdgqj13DXIg36NptkHMKxuP78oo4aUQ_6zlToyt78qI,46002
|
|
6
|
+
goodwe/exceptions.py,sha256=dKMLxotjoR1ic8OVlw1joIJ4mKWD6oFtUMZ86fNM5ZE,1403
|
|
7
|
+
goodwe/inverter.py,sha256=86aMJzJjNOr1I_tCF5H6mBwzDTjLbGDKUL2hbi0XSxg,10459
|
|
8
|
+
goodwe/modbus.py,sha256=Mg_s_v8kbZgqXZM6ZUUxkZx2boAG8LkuDG5OiFKK2X4,8402
|
|
9
|
+
goodwe/model.py,sha256=OAKfw6ggClgLR9JIdNd7tQ4pnh_7o_UqVdm1KOVsm-Y,2200
|
|
10
|
+
goodwe/protocol.py,sha256=gnQ1vV4U_lPpaNq5-jmzJO6ngJEDFVo0jWXVujSyu_0,30083
|
|
11
|
+
goodwe/sensor.py,sha256=xeDZIwjJ_176ULrRXVCTYvVXx6o2_pWgS0KuR3PPQdg,38435
|
|
12
|
+
goodwe-0.4.7.dist-info/LICENSE,sha256=aZAhk3lRdYT1YZV-IKRHISEcc_KNUmgfuNO3QhRamNM,1073
|
|
13
|
+
goodwe-0.4.7.dist-info/METADATA,sha256=qzKMdlhzJDyLdHfqp5_x7jFZMI2B15mTnBhN_UksJzM,3376
|
|
14
|
+
goodwe-0.4.7.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
15
|
+
goodwe-0.4.7.dist-info/top_level.txt,sha256=kKoiqiVvAxDaDJYMZZQLgHQj9cuWT1MXLfXElTDuf8s,7
|
|
16
|
+
goodwe-0.4.7.dist-info/RECORD,,
|
goodwe-0.4.6.dist-info/RECORD
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
goodwe/__init__.py,sha256=8fFGBBvBpCo6Ew4puTtW0kYo2hVPKUx6z5A-TA4Tbvc,5795
|
|
2
|
-
goodwe/const.py,sha256=yhWk56YV7k7-MbgfmWEMYNlqeRNLOfOpfTqEfRj6Hp8,7934
|
|
3
|
-
goodwe/dt.py,sha256=8lbc-G1vQUxtYZRDAHi6QW04bFJRW7l4OjBVDp0EjZc,12093
|
|
4
|
-
goodwe/es.py,sha256=vvHmxcFykp8nhR1I8p7SF0YcYpvdCKBYacgcolbVHXI,23009
|
|
5
|
-
goodwe/et.py,sha256=f4XWaV8Ltywlca1GYJCUM46ziQCtKleser34rO09WQg,44053
|
|
6
|
-
goodwe/exceptions.py,sha256=dKMLxotjoR1ic8OVlw1joIJ4mKWD6oFtUMZ86fNM5ZE,1403
|
|
7
|
-
goodwe/inverter.py,sha256=86aMJzJjNOr1I_tCF5H6mBwzDTjLbGDKUL2hbi0XSxg,10459
|
|
8
|
-
goodwe/modbus.py,sha256=Mg_s_v8kbZgqXZM6ZUUxkZx2boAG8LkuDG5OiFKK2X4,8402
|
|
9
|
-
goodwe/model.py,sha256=dWBjMFJMnhZoUdDd9fGT54DERDANz4TirK0Wy8kWMbk,2068
|
|
10
|
-
goodwe/protocol.py,sha256=gnQ1vV4U_lPpaNq5-jmzJO6ngJEDFVo0jWXVujSyu_0,30083
|
|
11
|
-
goodwe/sensor.py,sha256=gns0508zi3dCQ4C01RIUQ8aH-2b8TDpCjW71CFEVEiY,37707
|
|
12
|
-
goodwe-0.4.6.dist-info/LICENSE,sha256=aZAhk3lRdYT1YZV-IKRHISEcc_KNUmgfuNO3QhRamNM,1073
|
|
13
|
-
goodwe-0.4.6.dist-info/METADATA,sha256=jKbTn5rYaHEb6B8TpTYNqhE1F9dDApMFpBiwvJjMoPQ,3376
|
|
14
|
-
goodwe-0.4.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
15
|
-
goodwe-0.4.6.dist-info/top_level.txt,sha256=kKoiqiVvAxDaDJYMZZQLgHQj9cuWT1MXLfXElTDuf8s,7
|
|
16
|
-
goodwe-0.4.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|