goodwe 0.3.3__py3-none-any.whl → 0.3.5__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/es.py +12 -6
- goodwe/et.py +36 -19
- goodwe/inverter.py +3 -2
- goodwe/sensor.py +12 -11
- {goodwe-0.3.3.dist-info → goodwe-0.3.5.dist-info}/METADATA +1 -1
- goodwe-0.3.5.dist-info/RECORD +16 -0
- goodwe-0.3.3.dist-info/RECORD +0 -16
- {goodwe-0.3.3.dist-info → goodwe-0.3.5.dist-info}/LICENSE +0 -0
- {goodwe-0.3.3.dist-info → goodwe-0.3.5.dist-info}/WHEEL +0 -0
- {goodwe-0.3.3.dist-info → goodwe-0.3.5.dist-info}/top_level.txt +0 -0
goodwe/es.py
CHANGED
|
@@ -95,7 +95,7 @@ class ES(Inverter):
|
|
|
95
95
|
Power("pback_up", 81, "Back-up Power", Kind.UPS),
|
|
96
96
|
# pload + pback_up
|
|
97
97
|
Calculated("plant_power",
|
|
98
|
-
lambda data: round(read_bytes2(data, 47) + read_bytes2(data, 81)),
|
|
98
|
+
lambda data: round(read_bytes2(data, 47, 0) + read_bytes2(data, 81, 0)),
|
|
99
99
|
"Plant Power", "W", Kind.AC),
|
|
100
100
|
Decimal("meter_power_factor", 83, 1000, "Meter Power Factor", "", Kind.GRID), # modbus 0x531
|
|
101
101
|
# Integer("xx85", 85, "Unknown sensor@85"),
|
|
@@ -135,7 +135,7 @@ class ES(Inverter):
|
|
|
135
135
|
Integer("charge_i", 26, "Charge Current", "A", ),
|
|
136
136
|
Integer("discharge_i", 28, "Discharge Current", "A", ),
|
|
137
137
|
Decimal("discharge_v", 30, 10, "Discharge Voltage", "V"),
|
|
138
|
-
Calculated("dod", lambda data: 100 - read_bytes2(data, 32), "Depth of Discharge", "%"),
|
|
138
|
+
Calculated("dod", lambda data: 100 - read_bytes2(data, 32, 0), "Depth of Discharge", "%"),
|
|
139
139
|
Integer("battery_activated", 34, "Battery Activated"),
|
|
140
140
|
Integer("bp_off_grid_charge", 36, "BP Off-grid Charge"),
|
|
141
141
|
Integer("bp_pv_discharge", 38, "BP PV Discharge"),
|
|
@@ -285,19 +285,25 @@ class ES(Inverter):
|
|
|
285
285
|
async def get_operation_modes(self, include_emulated: bool) -> Tuple[OperationMode, ...]:
|
|
286
286
|
result = [e for e in OperationMode]
|
|
287
287
|
result.remove(OperationMode.PEAK_SHAVING)
|
|
288
|
+
result.remove(OperationMode.SELF_USE)
|
|
288
289
|
if not include_emulated:
|
|
289
290
|
result.remove(OperationMode.ECO_CHARGE)
|
|
290
291
|
result.remove(OperationMode.ECO_DISCHARGE)
|
|
291
292
|
return tuple(result)
|
|
292
293
|
|
|
293
294
|
async def get_operation_mode(self) -> OperationMode:
|
|
294
|
-
|
|
295
|
+
mode_id = await self.read_setting('work_mode')
|
|
296
|
+
try:
|
|
297
|
+
mode = OperationMode(mode_id)
|
|
298
|
+
except ValueError:
|
|
299
|
+
logger.debug("Unknown work_mode value %d", mode_id)
|
|
300
|
+
return None
|
|
295
301
|
if OperationMode.ECO != mode:
|
|
296
302
|
return mode
|
|
297
|
-
|
|
298
|
-
if
|
|
303
|
+
eco_mode = await self.read_setting('eco_mode_1')
|
|
304
|
+
if eco_mode.is_eco_charge_mode():
|
|
299
305
|
return OperationMode.ECO_CHARGE
|
|
300
|
-
elif
|
|
306
|
+
elif eco_mode.is_eco_discharge_mode():
|
|
301
307
|
return OperationMode.ECO_DISCHARGE
|
|
302
308
|
else:
|
|
303
309
|
return OperationMode.ECO
|
goodwe/et.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import Tuple
|
|
5
5
|
|
|
6
|
-
from .exceptions import RequestRejectedException
|
|
6
|
+
from .exceptions import RequestFailedException, RequestRejectedException
|
|
7
7
|
from .inverter import Inverter
|
|
8
8
|
from .inverter import OperationMode
|
|
9
9
|
from .inverter import SensorKind as Kind
|
|
@@ -35,10 +35,10 @@ class ET(Inverter):
|
|
|
35
35
|
# ppv1 + ppv2 + ppv3 + ppv4
|
|
36
36
|
Calculated("ppv",
|
|
37
37
|
lambda data:
|
|
38
|
-
max(0, read_bytes4(data, 35105)) +
|
|
39
|
-
max(0, read_bytes4(data, 35109)) +
|
|
40
|
-
max(0, read_bytes4(data, 35113)) +
|
|
41
|
-
max(0, read_bytes4(data, 35117)),
|
|
38
|
+
max(0, read_bytes4(data, 35105, 0)) +
|
|
39
|
+
max(0, read_bytes4(data, 35109, 0)) +
|
|
40
|
+
max(0, read_bytes4(data, 35113, 0)) +
|
|
41
|
+
max(0, read_bytes4(data, 35117, 0)),
|
|
42
42
|
"PV Power", "W", Kind.PV),
|
|
43
43
|
ByteH("pv4_mode", 35119, "PV4 Mode code", "", Kind.PV),
|
|
44
44
|
EnumH("pv4_mode_label", 35119, PV_MODES, "PV4 Mode", Kind.PV),
|
|
@@ -145,10 +145,10 @@ class ET(Inverter):
|
|
|
145
145
|
# ppv1 + ppv2 + ppv3 + ppv4 + pbattery1 - active_power
|
|
146
146
|
Calculated("house_consumption",
|
|
147
147
|
lambda data:
|
|
148
|
-
read_bytes4(data, 35105) +
|
|
149
|
-
read_bytes4(data, 35109) +
|
|
150
|
-
read_bytes4(data, 35113) +
|
|
151
|
-
read_bytes4(data, 35117) +
|
|
148
|
+
read_bytes4(data, 35105, 0) +
|
|
149
|
+
read_bytes4(data, 35109, 0) +
|
|
150
|
+
read_bytes4(data, 35113, 0) +
|
|
151
|
+
read_bytes4(data, 35117, 0) +
|
|
152
152
|
read_bytes4_signed(data, 35182) -
|
|
153
153
|
read_bytes2_signed(data, 35140),
|
|
154
154
|
"House Consumption", "W", Kind.AC),
|
|
@@ -482,8 +482,11 @@ class ET(Inverter):
|
|
|
482
482
|
self._settings.update({s.id_: s for s in self.__settings_arm_fw_19})
|
|
483
483
|
except RequestRejectedException as ex:
|
|
484
484
|
if ex.message == 'ILLEGAL DATA ADDRESS':
|
|
485
|
-
logger.debug("
|
|
485
|
+
logger.debug("EcoModeV2 settings not supported, switching to EcoModeV1.")
|
|
486
486
|
self._has_eco_mode_v2 = False
|
|
487
|
+
except RequestFailedException as ex:
|
|
488
|
+
logger.debug("Cannot read EcoModeV2 settings, switching to EcoModeV1.")
|
|
489
|
+
self._has_eco_mode_v2 = False
|
|
487
490
|
|
|
488
491
|
# Check and add Peak Shaving settings added in (ETU fw 22)
|
|
489
492
|
try:
|
|
@@ -491,8 +494,11 @@ class ET(Inverter):
|
|
|
491
494
|
self._settings.update({s.id_: s for s in self.__settings_arm_fw_22})
|
|
492
495
|
except RequestRejectedException as ex:
|
|
493
496
|
if ex.message == 'ILLEGAL DATA ADDRESS':
|
|
494
|
-
logger.debug("
|
|
497
|
+
logger.debug("PeakShaving setting not supported, disabling it.")
|
|
495
498
|
self._has_peak_shaving = False
|
|
499
|
+
except RequestFailedException as ex:
|
|
500
|
+
logger.debug("Cannot read _has_peak_shaving settings, disabling it.")
|
|
501
|
+
self._has_peak_shaving = False
|
|
496
502
|
|
|
497
503
|
async def read_runtime_data(self) -> Dict[str, Any]:
|
|
498
504
|
response = await self._read_from_socket(self._READ_RUNNING_DATA)
|
|
@@ -505,7 +511,7 @@ class ET(Inverter):
|
|
|
505
511
|
data.update(self._map_response(response, self._sensors_battery))
|
|
506
512
|
except RequestRejectedException as ex:
|
|
507
513
|
if ex.message == 'ILLEGAL DATA ADDRESS':
|
|
508
|
-
logger.warning("
|
|
514
|
+
logger.warning("Battery values not supported, disabling further attempts.")
|
|
509
515
|
self._has_battery = False
|
|
510
516
|
else:
|
|
511
517
|
raise ex
|
|
@@ -516,7 +522,7 @@ class ET(Inverter):
|
|
|
516
522
|
self._map_response(response, self._sensors_battery2))
|
|
517
523
|
except RequestRejectedException as ex:
|
|
518
524
|
if ex.message == 'ILLEGAL DATA ADDRESS':
|
|
519
|
-
logger.warning("
|
|
525
|
+
logger.warning("Battery 2 values not supported, disabling further attempts.")
|
|
520
526
|
self._has_battery2 = False
|
|
521
527
|
else:
|
|
522
528
|
raise ex
|
|
@@ -527,7 +533,7 @@ class ET(Inverter):
|
|
|
527
533
|
data.update(self._map_response(response, self._sensors_meter))
|
|
528
534
|
except RequestRejectedException as ex:
|
|
529
535
|
if ex.message == 'ILLEGAL DATA ADDRESS':
|
|
530
|
-
logger.warning("
|
|
536
|
+
logger.warning("Extended meter values not supported, disabling further attempts.")
|
|
531
537
|
self._has_meter_extended = False
|
|
532
538
|
self._sensors_meter = tuple(filter(self._not_extended_meter, self._sensors_meter))
|
|
533
539
|
response = await self._read_from_socket(self._READ_METER_DATA)
|
|
@@ -545,7 +551,7 @@ class ET(Inverter):
|
|
|
545
551
|
data.update(self._map_response(response, self._sensors_mppt))
|
|
546
552
|
except RequestRejectedException as ex:
|
|
547
553
|
if ex.message == 'ILLEGAL DATA ADDRESS':
|
|
548
|
-
logger.warning("
|
|
554
|
+
logger.warning("MPPT values not supported, disabling further attempts.")
|
|
549
555
|
self._has_mppt = False
|
|
550
556
|
else:
|
|
551
557
|
raise ex
|
|
@@ -604,19 +610,26 @@ class ET(Inverter):
|
|
|
604
610
|
result = [e for e in OperationMode]
|
|
605
611
|
if not self._has_peak_shaving:
|
|
606
612
|
result.remove(OperationMode.PEAK_SHAVING)
|
|
613
|
+
if not is_745_platform(self):
|
|
614
|
+
result.remove(OperationMode.SELF_USE)
|
|
607
615
|
if not include_emulated:
|
|
608
616
|
result.remove(OperationMode.ECO_CHARGE)
|
|
609
617
|
result.remove(OperationMode.ECO_DISCHARGE)
|
|
610
618
|
return tuple(result)
|
|
611
619
|
|
|
612
620
|
async def get_operation_mode(self) -> OperationMode:
|
|
613
|
-
|
|
621
|
+
mode_id = await self.read_setting('work_mode')
|
|
622
|
+
try:
|
|
623
|
+
mode = OperationMode(mode_id)
|
|
624
|
+
except ValueError:
|
|
625
|
+
logger.debug("Unknown work_mode value %d", mode_id)
|
|
626
|
+
return None
|
|
614
627
|
if OperationMode.ECO != mode:
|
|
615
628
|
return mode
|
|
616
|
-
|
|
617
|
-
if
|
|
629
|
+
eco_mode = await self.read_setting('eco_mode_1')
|
|
630
|
+
if eco_mode.is_eco_charge_mode():
|
|
618
631
|
return OperationMode.ECO_CHARGE
|
|
619
|
-
elif
|
|
632
|
+
elif eco_mode.is_eco_discharge_mode():
|
|
620
633
|
return OperationMode.ECO_DISCHARGE
|
|
621
634
|
else:
|
|
622
635
|
return OperationMode.ECO
|
|
@@ -644,6 +657,10 @@ class ET(Inverter):
|
|
|
644
657
|
await self.write_setting('work_mode', 4)
|
|
645
658
|
await self._set_offline(False)
|
|
646
659
|
await self._clear_battery_mode_param()
|
|
660
|
+
elif operation_mode == OperationMode.SELF_USE:
|
|
661
|
+
await self.write_setting('work_mode', 5)
|
|
662
|
+
await self._set_offline(False)
|
|
663
|
+
await self._clear_battery_mode_param()
|
|
647
664
|
elif operation_mode in (OperationMode.ECO_CHARGE, OperationMode.ECO_DISCHARGE):
|
|
648
665
|
if eco_mode_power < 0 or eco_mode_power > 100:
|
|
649
666
|
raise ValueError()
|
goodwe/inverter.py
CHANGED
goodwe/sensor.py
CHANGED
|
@@ -183,7 +183,7 @@ class Energy(Sensor):
|
|
|
183
183
|
|
|
184
184
|
def read_value(self, data: ProtocolResponse):
|
|
185
185
|
value = read_bytes2(data)
|
|
186
|
-
return float(value) / 10
|
|
186
|
+
return float(value) / 10 if value else None
|
|
187
187
|
|
|
188
188
|
|
|
189
189
|
class Energy4(Sensor):
|
|
@@ -194,7 +194,7 @@ class Energy4(Sensor):
|
|
|
194
194
|
|
|
195
195
|
def read_value(self, data: ProtocolResponse):
|
|
196
196
|
value = read_bytes4(data)
|
|
197
|
-
return float(value) / 10
|
|
197
|
+
return float(value) / 10 if value else None
|
|
198
198
|
|
|
199
199
|
|
|
200
200
|
class Apparent(Sensor):
|
|
@@ -308,7 +308,7 @@ class Integer(Sensor):
|
|
|
308
308
|
super().__init__(id_, offset, name, 2, unit, kind)
|
|
309
309
|
|
|
310
310
|
def read_value(self, data: ProtocolResponse):
|
|
311
|
-
return read_bytes2(data)
|
|
311
|
+
return read_bytes2(data, None, 0)
|
|
312
312
|
|
|
313
313
|
def encode_value(self, value: Any, register_value: bytes = None) -> bytes:
|
|
314
314
|
return int.to_bytes(int(value), length=2, byteorder="big", signed=False)
|
|
@@ -334,7 +334,7 @@ class Long(Sensor):
|
|
|
334
334
|
super().__init__(id_, offset, name, 4, unit, kind)
|
|
335
335
|
|
|
336
336
|
def read_value(self, data: ProtocolResponse):
|
|
337
|
-
return read_bytes4(data)
|
|
337
|
+
return read_bytes4(data, None, 0)
|
|
338
338
|
|
|
339
339
|
def encode_value(self, value: Any, register_value: bytes = None) -> bytes:
|
|
340
340
|
return int.to_bytes(int(value), length=4, byteorder="big", signed=False)
|
|
@@ -414,7 +414,7 @@ class EnumH(Sensor):
|
|
|
414
414
|
|
|
415
415
|
|
|
416
416
|
class EnumL(Sensor):
|
|
417
|
-
"""Sensor representing label from enumeration encoded in 1
|
|
417
|
+
"""Sensor representing label from enumeration encoded in 1 byte (low 8 bits of 16bit register)"""
|
|
418
418
|
|
|
419
419
|
def __init__(self, id_: str, offset: int, labels: Dict, name: str, kind: Optional[SensorKind] = None):
|
|
420
420
|
super().__init__(id_, offset, name, 1, "", kind)
|
|
@@ -433,7 +433,7 @@ class Enum2(Sensor):
|
|
|
433
433
|
self._labels: Dict = labels
|
|
434
434
|
|
|
435
435
|
def read_value(self, data: ProtocolResponse):
|
|
436
|
-
return self._labels.get(read_bytes2(data))
|
|
436
|
+
return self._labels.get(read_bytes2(data, None, 0))
|
|
437
437
|
|
|
438
438
|
|
|
439
439
|
class EnumBitmap4(Sensor):
|
|
@@ -464,7 +464,8 @@ class EnumBitmap22(Sensor):
|
|
|
464
464
|
raise NotImplementedError()
|
|
465
465
|
|
|
466
466
|
def read(self, data: ProtocolResponse):
|
|
467
|
-
return decode_bitmap(read_bytes2(data, self.offset) << 16 + read_bytes2(data, self._offsetL
|
|
467
|
+
return decode_bitmap(read_bytes2(data, self.offset, 0) << 16 + read_bytes2(data, self._offsetL, 0),
|
|
468
|
+
self._labels)
|
|
468
469
|
|
|
469
470
|
|
|
470
471
|
class EnumCalculated(Sensor):
|
|
@@ -785,12 +786,12 @@ def read_byte(buffer: ProtocolResponse, offset: int = None) -> int:
|
|
|
785
786
|
return int.from_bytes(buffer.read(1), byteorder="big", signed=True)
|
|
786
787
|
|
|
787
788
|
|
|
788
|
-
def read_bytes2(buffer: ProtocolResponse, offset: int = None) -> int:
|
|
789
|
+
def read_bytes2(buffer: ProtocolResponse, offset: int = None, undef: int = None) -> int:
|
|
789
790
|
"""Retrieve 2 byte (unsigned int) value from buffer"""
|
|
790
791
|
if offset is not None:
|
|
791
792
|
buffer.seek(offset)
|
|
792
793
|
value = int.from_bytes(buffer.read(2), byteorder="big", signed=False)
|
|
793
|
-
return
|
|
794
|
+
return undef if value == 0xffff else value
|
|
794
795
|
|
|
795
796
|
|
|
796
797
|
def read_bytes2_signed(buffer: ProtocolResponse, offset: int = None) -> int:
|
|
@@ -800,12 +801,12 @@ def read_bytes2_signed(buffer: ProtocolResponse, offset: int = None) -> int:
|
|
|
800
801
|
return int.from_bytes(buffer.read(2), byteorder="big", signed=True)
|
|
801
802
|
|
|
802
803
|
|
|
803
|
-
def read_bytes4(buffer: ProtocolResponse, offset: int = None) -> int:
|
|
804
|
+
def read_bytes4(buffer: ProtocolResponse, offset: int = None, undef: int = None) -> int:
|
|
804
805
|
"""Retrieve 4 byte (unsigned int) value from buffer"""
|
|
805
806
|
if offset is not None:
|
|
806
807
|
buffer.seek(offset)
|
|
807
808
|
value = int.from_bytes(buffer.read(4), byteorder="big", signed=False)
|
|
808
|
-
return
|
|
809
|
+
return undef if value == 0xffffffff else value
|
|
809
810
|
|
|
810
811
|
|
|
811
812
|
def read_bytes4_signed(buffer: ProtocolResponse, offset: int = None) -> int:
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
goodwe/__init__.py,sha256=PInrrZEpTmMOQKk494vIz8EKSaw_qLBNz-6t9eLIUcg,5642
|
|
2
|
+
goodwe/const.py,sha256=Nw-nd4UJuqUOLfbmOrxTHEdS1AuaTDSpZzQqR6tBb8w,7912
|
|
3
|
+
goodwe/dt.py,sha256=bI53MVdZjtxTYU2qJLO8icsvF6UiXrkgH95V3iUwXT0,10581
|
|
4
|
+
goodwe/es.py,sha256=XBP7txg9d4tMsFmHWs8LB4wdJmspKVD9ALfS9mePiJk,22650
|
|
5
|
+
goodwe/et.py,sha256=0XFwRMZeUdKZ4dhGANpw2o1EKsfgJGdGYsN95zhxV1s,40084
|
|
6
|
+
goodwe/exceptions.py,sha256=I6PHG0GTWgxNrDVZwJZBnyzItRq5eiM6ci23-EEsn1I,1012
|
|
7
|
+
goodwe/inverter.py,sha256=7DgIzSHimkVAfNyIkzALeukHOHkOuYjVyUIvuT0LHdE,10342
|
|
8
|
+
goodwe/modbus.py,sha256=ZPib-zKnOVE5zc0RNnhlf0w_26QBees1ScWGo6bAj0o,4685
|
|
9
|
+
goodwe/model.py,sha256=dWBjMFJMnhZoUdDd9fGT54DERDANz4TirK0Wy8kWMbk,2068
|
|
10
|
+
goodwe/protocol.py,sha256=pUkXTP2DqpKXGO7rbRfHq1x82Y1QM6OiRVx8cAtS0sM,13162
|
|
11
|
+
goodwe/sensor.py,sha256=vFbsz4Dp0yw0rBNdKqzkMUupuBJWC17YcxvBrjvFAjU,36990
|
|
12
|
+
goodwe-0.3.5.dist-info/LICENSE,sha256=aZAhk3lRdYT1YZV-IKRHISEcc_KNUmgfuNO3QhRamNM,1073
|
|
13
|
+
goodwe-0.3.5.dist-info/METADATA,sha256=aITPWNoquftA7VYNraUZqMoO8Bu-DXQ98ZAJxhsHtZM,3050
|
|
14
|
+
goodwe-0.3.5.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
15
|
+
goodwe-0.3.5.dist-info/top_level.txt,sha256=kKoiqiVvAxDaDJYMZZQLgHQj9cuWT1MXLfXElTDuf8s,7
|
|
16
|
+
goodwe-0.3.5.dist-info/RECORD,,
|
goodwe-0.3.3.dist-info/RECORD
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
goodwe/__init__.py,sha256=PInrrZEpTmMOQKk494vIz8EKSaw_qLBNz-6t9eLIUcg,5642
|
|
2
|
-
goodwe/const.py,sha256=Nw-nd4UJuqUOLfbmOrxTHEdS1AuaTDSpZzQqR6tBb8w,7912
|
|
3
|
-
goodwe/dt.py,sha256=bI53MVdZjtxTYU2qJLO8icsvF6UiXrkgH95V3iUwXT0,10581
|
|
4
|
-
goodwe/es.py,sha256=KZLBydRSzzAnbI8-o_-sKiJeunJGuCKr7N8V8_Ft__U,22434
|
|
5
|
-
goodwe/et.py,sha256=P4H5Q17Gx8V8Y9os5HfiECsVIZ1znx13pGRFzc93n54,39228
|
|
6
|
-
goodwe/exceptions.py,sha256=I6PHG0GTWgxNrDVZwJZBnyzItRq5eiM6ci23-EEsn1I,1012
|
|
7
|
-
goodwe/inverter.py,sha256=uiQdti_4lGVLrSG94GgxgALWuevY6hl9ekdHQTomR-0,10325
|
|
8
|
-
goodwe/modbus.py,sha256=ZPib-zKnOVE5zc0RNnhlf0w_26QBees1ScWGo6bAj0o,4685
|
|
9
|
-
goodwe/model.py,sha256=dWBjMFJMnhZoUdDd9fGT54DERDANz4TirK0Wy8kWMbk,2068
|
|
10
|
-
goodwe/protocol.py,sha256=pUkXTP2DqpKXGO7rbRfHq1x82Y1QM6OiRVx8cAtS0sM,13162
|
|
11
|
-
goodwe/sensor.py,sha256=cPZCC3_9gk5zPVTkzhuDa6byz_dM4xCyE8FtV5nxqgg,36845
|
|
12
|
-
goodwe-0.3.3.dist-info/LICENSE,sha256=aZAhk3lRdYT1YZV-IKRHISEcc_KNUmgfuNO3QhRamNM,1073
|
|
13
|
-
goodwe-0.3.3.dist-info/METADATA,sha256=0sEhEL3Uv3TSMsOTCqZSE1YEpeoDD609fcQodacEIvs,3050
|
|
14
|
-
goodwe-0.3.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
15
|
-
goodwe-0.3.3.dist-info/top_level.txt,sha256=kKoiqiVvAxDaDJYMZZQLgHQj9cuWT1MXLfXElTDuf8s,7
|
|
16
|
-
goodwe-0.3.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|