goodwe 0.4.5__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 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
- Power("ppv", 30128, "PV Power", Kind.PV),
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"),
@@ -114,6 +120,10 @@ class DT(Inverter):
114
120
  Integer("shadow_scan", 40326, "Shadow Scan", "", Kind.PV),
115
121
  Integer("grid_export", 40327, "Grid Export Enabled", "", Kind.GRID),
116
122
  Integer("grid_export_limit", 40328, "Grid Export Limit", "%", Kind.GRID),
123
+ Integer("start", 40330, "Start / Power On", "", Kind.GRID),
124
+ Integer("stop", 40331, "Stop / Power Off", "", Kind.GRID),
125
+ Integer("restart", 40332, "Restart", "", Kind.GRID),
126
+ Integer("grid_export_hw", 40345, "Grid Export Enabled (HW)", "", Kind.GRID),
117
127
  )
118
128
 
119
129
  # Settings for single phase inverters
@@ -196,6 +206,7 @@ class DT(Inverter):
196
206
  if ex.message == ILLEGAL_DATA_ADDRESS:
197
207
  logger.debug("Unsupported setting %s", setting.id_)
198
208
  self._settings.pop(setting.id_, None)
209
+ raise ValueError(f'Unknown setting "{setting.id_}"')
199
210
  return None
200
211
 
201
212
  async def write_setting(self, setting_id: str, value: Any):
goodwe/es.py CHANGED
@@ -174,11 +174,11 @@ class ES(Inverter):
174
174
  def _supports_eco_mode_v2(self) -> bool:
175
175
  if self.arm_version < 14:
176
176
  return False
177
- if "EMU" in self.serial_number:
177
+ if "EMU" in self.serial_number or "EMJ" in self.serial_number:
178
178
  return self.dsp1_version >= 11
179
- if "ESU" in self.serial_number:
179
+ if "ESU" in self.serial_number or "ESA" in self.serial_number:
180
180
  return self.dsp1_version >= 22
181
- if "BPS" in self.serial_number:
181
+ if "BPS" in self.serial_number or "BPU" in self.serial_number:
182
182
  return self.dsp1_version >= 10
183
183
  return False
184
184
 
@@ -188,7 +188,7 @@ class ES(Inverter):
188
188
  self.firmware = self._decode(response[0:5]).rstrip()
189
189
  self.model_name = self._decode(response[5:15]).rstrip()
190
190
  self.serial_number = self._decode(response[31:47])
191
- self.software_version = self._decode(response[51:63])
191
+ self.arm_firmware = self._decode(response[51:63]) # AKA software_version
192
192
  try:
193
193
  if len(self.firmware) >= 2:
194
194
  self.dsp1_version = int(self.firmware[0:2])
@@ -220,9 +220,12 @@ class ES(Inverter):
220
220
  elif setting_id.startswith("modbus"):
221
221
  response = await self._read_from_socket(self._read_command(int(setting_id[7:]), 1))
222
222
  return int.from_bytes(response.read(2), byteorder="big", signed=True)
223
- else:
223
+ elif setting_id in self._settings:
224
+ logger.debug("Reading setting %s", setting_id)
224
225
  all_settings = await self.read_settings_data()
225
226
  return all_settings.get(setting_id)
227
+ else:
228
+ raise ValueError(f'Unknown setting "{setting_id}"')
226
229
 
227
230
  async def _read_setting(self, setting: Sensor) -> Any:
228
231
  count = (setting.size_ + (setting.size_ % 2)) // 2
@@ -296,7 +299,7 @@ class ES(Inverter):
296
299
  try:
297
300
  mode = OperationMode(mode_id)
298
301
  except ValueError:
299
- logger.debug("Unknown work_mode value %d", mode_id)
302
+ logger.debug("Unknown work_mode value %s", mode_id)
300
303
  return None
301
304
  if OperationMode.ECO != mode:
302
305
  return mode
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
- # Sensors added in some ARM fw update, read when flag _has_meter_extended is on
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
@@ -332,7 +342,7 @@ class ET(Inverter):
332
342
  # Modbus registers of inverter settings, offsets are modbus register addresses
333
343
  __all_settings: Tuple[Sensor, ...] = (
334
344
  Integer("comm_address", 45127, "Communication Address", ""),
335
- Integer("modbus_baud_rate", 45132, "Modbus Baud rate", ""),
345
+ Long("modbus_baud_rate", 45132, "Modbus Baud rate", ""),
336
346
  Timestamp("time", 45200, "Inverter time"),
337
347
 
338
348
  Integer("sensitivity_check", 45246, "Sensitivity Check Mode", "", Kind.AC),
@@ -357,6 +367,8 @@ class ET(Inverter):
357
367
  Integer("work_mode", 47000, "Work Mode", "", Kind.AC),
358
368
  Integer("dred", 47010, "DRED/Remote Shutdown", "", Kind.AC),
359
369
 
370
+ Integer("meter_target_power_offset", 47120, "Meter Target Power Offset", "W", Kind.AC),
371
+
360
372
  Integer("battery_soc_protection", 47500, "Battery SoC Protection", "", Kind.BAT),
361
373
 
362
374
  Integer("grid_export", 47509, "Grid Export Enabled", "", Kind.GRID),
@@ -462,6 +474,7 @@ class ET(Inverter):
462
474
  self._READ_RUNNING_DATA: ProtocolCommand = self._read_command(0x891c, 0x007d)
463
475
  self._READ_METER_DATA: ProtocolCommand = self._read_command(0x8ca0, 0x2d)
464
476
  self._READ_METER_DATA_EXTENDED: ProtocolCommand = self._read_command(0x8ca0, 0x3a)
477
+ self._READ_METER_DATA_EXTENDED2: ProtocolCommand = self._read_command(0x8ca0, 0x7d)
465
478
  self._READ_BATTERY_INFO: ProtocolCommand = self._read_command(0x9088, 0x0018)
466
479
  self._READ_BATTERY2_INFO: ProtocolCommand = self._read_command(0x9858, 0x0016)
467
480
  self._READ_MPPT_DATA: ProtocolCommand = self._read_command(0x89e5, 0x3d)
@@ -470,6 +483,7 @@ class ET(Inverter):
470
483
  self._has_battery: bool = True
471
484
  self._has_battery2: bool = False
472
485
  self._has_meter_extended: bool = False
486
+ self._has_meter_extended2: bool = False
473
487
  self._has_mppt: bool = False
474
488
  self._sensors = self.__all_sensors
475
489
  self._sensors_battery = self.__all_sensors_battery
@@ -488,6 +502,11 @@ class ET(Inverter):
488
502
  """Filter to exclude extended meter sensors"""
489
503
  return s.offset < 36045
490
504
 
505
+ @staticmethod
506
+ def _not_extended_meter2(s: Sensor) -> bool:
507
+ """Filter to exclude extended meter sensors"""
508
+ return s.offset < 36058
509
+
491
510
  async def read_device_info(self):
492
511
  response = await self._read_from_socket(self._READ_DEVICE_VERSION_INFO)
493
512
  response = response.response_data()
@@ -518,9 +537,10 @@ class ET(Inverter):
518
537
  if is_2_battery(self) or self.rated_power >= 25000:
519
538
  self._has_battery2 = True
520
539
 
521
- if self.rated_power >= 15000:
540
+ if is_745_platform(self) or self.rated_power >= 15000:
522
541
  self._has_mppt = True
523
542
  self._has_meter_extended = True
543
+ self._has_meter_extended2 = True
524
544
  else:
525
545
  self._sensors_meter = tuple(filter(self._not_extended_meter, self._sensors_meter))
526
546
 
@@ -575,7 +595,21 @@ class ET(Inverter):
575
595
  else:
576
596
  raise ex
577
597
 
578
- if self._has_meter_extended:
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:
579
613
  try:
580
614
  response = await self._read_from_socket(self._READ_METER_DATA_EXTENDED)
581
615
  data.update(self._map_response(response, self._sensors_meter))
@@ -626,6 +660,7 @@ class ET(Inverter):
626
660
  if ex.message == ILLEGAL_DATA_ADDRESS:
627
661
  logger.debug("Unsupported setting %s", setting.id_)
628
662
  self._settings.pop(setting.id_, None)
663
+ raise ValueError(f'Unknown setting "{setting.id_}"')
629
664
  return None
630
665
 
631
666
  async def write_setting(self, setting_id: str, value: Any):
@@ -685,7 +720,7 @@ class ET(Inverter):
685
720
  try:
686
721
  mode = OperationMode(mode_id)
687
722
  except ValueError:
688
- logger.debug("Unknown work_mode value %d", mode_id)
723
+ logger.debug("Unknown work_mode value %s", mode_id)
689
724
  return None
690
725
  if OperationMode.ECO != mode:
691
726
  return mode
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/protocol.py CHANGED
@@ -482,7 +482,7 @@ class Aa55ProtocolCommand(ProtocolCommand):
482
482
  The last 2 bytes are again plain checksum of header+payload.
483
483
  """
484
484
 
485
- def __init__(self, payload: str, response_type: str):
485
+ def __init__(self, payload: str, response_type: str, offset: int = 0, value: int = 0):
486
486
  super().__init__(
487
487
  bytes.fromhex(
488
488
  "AA55C07F"
@@ -491,6 +491,8 @@ class Aa55ProtocolCommand(ProtocolCommand):
491
491
  ),
492
492
  lambda x: self._validate_aa55_response(x, response_type),
493
493
  )
494
+ self.first_address: int = offset
495
+ self.value = value
494
496
 
495
497
  @staticmethod
496
498
  def _checksum(data: bytes) -> bytes:
@@ -534,6 +536,17 @@ class Aa55ProtocolCommand(ProtocolCommand):
534
536
  """Trim raw response from header and checksum data"""
535
537
  return raw_response[7:-2]
536
538
 
539
+ def __repr__(self):
540
+ if self.request[4] == 1:
541
+ if self.request[5] == 2:
542
+ return f'READ device info ({self.request.hex()})'
543
+ elif self.request[5] == 6:
544
+ return f'READ runtime data ({self.request.hex()})'
545
+ elif self.request[5] == 9:
546
+ return f'READ settings ({self.request.hex()})'
547
+ else:
548
+ return self.request.hex()
549
+
537
550
 
538
551
  class Aa55ReadCommand(Aa55ProtocolCommand):
539
552
  """
@@ -541,7 +554,13 @@ class Aa55ReadCommand(Aa55ProtocolCommand):
541
554
  """
542
555
 
543
556
  def __init__(self, offset: int, count: int):
544
- super().__init__("011A03" + "{:04x}".format(offset) + "{:02x}".format(count), "019A")
557
+ super().__init__("011A03" + "{:04x}".format(offset) + "{:02x}".format(count), "019A", offset, count)
558
+
559
+ def __repr__(self):
560
+ if self.value > 1:
561
+ return f'READ {self.value} registers from {self.first_address} ({self.request.hex()})'
562
+ else:
563
+ return f'READ register {self.first_address} ({self.request.hex()})'
545
564
 
546
565
 
547
566
  class Aa55WriteCommand(Aa55ProtocolCommand):
@@ -550,7 +569,10 @@ class Aa55WriteCommand(Aa55ProtocolCommand):
550
569
  """
551
570
 
552
571
  def __init__(self, register: int, value: int):
553
- super().__init__("023905" + "{:04x}".format(register) + "01" + "{:04x}".format(value), "02B9")
572
+ super().__init__("023905" + "{:04x}".format(register) + "01" + "{:04x}".format(value), "02B9", register, value)
573
+
574
+ def __repr__(self):
575
+ return f'WRITE {self.value} to register {self.first_address} ({self.request.hex()})'
554
576
 
555
577
 
556
578
  class Aa55WriteMultiCommand(Aa55ProtocolCommand):
@@ -560,7 +582,7 @@ class Aa55WriteMultiCommand(Aa55ProtocolCommand):
560
582
 
561
583
  def __init__(self, offset: int, values: bytes):
562
584
  super().__init__("02390B" + "{:04x}".format(offset) + "{:02x}".format(len(values)) + values.hex(),
563
- "02B9")
585
+ "02B9", offset, len(values) // 2)
564
586
 
565
587
 
566
588
  class ModbusRtuProtocolCommand(ProtocolCommand):
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
 
@@ -364,7 +375,7 @@ class Decimal(Sensor):
364
375
  return read_decimal2(data, self.scale)
365
376
 
366
377
  def encode_value(self, value: Any, register_value: bytes = None) -> bytes:
367
- return int.to_bytes(int(value * self.scale), length=2, byteorder="big", signed=True)
378
+ return int.to_bytes(int(float(value) * self.scale), length=2, byteorder="big", signed=True)
368
379
 
369
380
 
370
381
  class Float(Sensor):
@@ -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:
@@ -868,7 +887,7 @@ def read_voltage(buffer: ProtocolResponse, offset: int = None) -> float:
868
887
 
869
888
  def encode_voltage(value: Any) -> bytes:
870
889
  """Encode voltage value to raw (2 unsigned bytes) payload"""
871
- return int.to_bytes(int(value * 10), length=2, byteorder="big", signed=False)
890
+ return int.to_bytes(int(float(value) * 10), length=2, byteorder="big", signed=False)
872
891
 
873
892
 
874
893
  def read_current(buffer: ProtocolResponse, offset: int = None) -> float:
@@ -889,12 +908,12 @@ def read_current_signed(buffer: ProtocolResponse, offset: int = None) -> float:
889
908
 
890
909
  def encode_current(value: Any) -> bytes:
891
910
  """Encode current value to raw (2 unsigned bytes) payload"""
892
- return int.to_bytes(int(value * 10), length=2, byteorder="big", signed=False)
911
+ return int.to_bytes(int(float(value) * 10), length=2, byteorder="big", signed=False)
893
912
 
894
913
 
895
914
  def encode_current_signed(value: Any) -> bytes:
896
915
  """Encode current value to raw (2 signed bytes) payload"""
897
- return int.to_bytes(int(value * 10), length=2, byteorder="big", signed=True)
916
+ return int.to_bytes(int(float(value) * 10), length=2, byteorder="big", signed=True)
898
917
 
899
918
 
900
919
  def read_freq(buffer: ProtocolResponse, offset: int = None) -> float:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: goodwe
3
- Version: 0.4.5
3
+ Version: 0.4.7
4
4
  Summary: Read data from GoodWe inverter via local network
5
5
  Home-page: https://github.com/marcelblijleven/goodwe
6
6
  Author: Martin Letenay, Marcel Blijleven
@@ -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,,
@@ -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=oGbkdVHP51KnlwQraKeebmiP6AtJ1S67aLB7euNRIoE,11743
4
- goodwe/es.py,sha256=iVK8EMCaAJJFihZLntJZ_Eu4sQWoZTVtTROp9mHFG6o,22730
5
- goodwe/et.py,sha256=CiX-PE7wouDnj1RnPnOyqiNE4FELhOGdyPUOm9VCzUw,43890
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=Ry1B-kki5F-AnsmpeUWuhP3eCCH1wrKKfDuT9BKfmvE,29140
11
- goodwe/sensor.py,sha256=buPG8BcgZmRDqaMrLQUACLHB85U134qG6qo_ggsu48A,37679
12
- goodwe-0.4.5.dist-info/LICENSE,sha256=aZAhk3lRdYT1YZV-IKRHISEcc_KNUmgfuNO3QhRamNM,1073
13
- goodwe-0.4.5.dist-info/METADATA,sha256=9MoleSeCTePnmqw6x_u5WcBE0GXwVvCtxF-9s4hqEHw,3376
14
- goodwe-0.4.5.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
15
- goodwe-0.4.5.dist-info/top_level.txt,sha256=kKoiqiVvAxDaDJYMZZQLgHQj9cuWT1MXLfXElTDuf8s,7
16
- goodwe-0.4.5.dist-info/RECORD,,
File without changes