goodwe 0.4.5__py3-none-any.whl → 0.4.6__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
@@ -114,6 +114,10 @@ class DT(Inverter):
114
114
  Integer("shadow_scan", 40326, "Shadow Scan", "", Kind.PV),
115
115
  Integer("grid_export", 40327, "Grid Export Enabled", "", Kind.GRID),
116
116
  Integer("grid_export_limit", 40328, "Grid Export Limit", "%", Kind.GRID),
117
+ Integer("start", 40330, "Start / Power On", "", Kind.GRID),
118
+ Integer("stop", 40331, "Stop / Power Off", "", Kind.GRID),
119
+ Integer("restart", 40332, "Restart", "", Kind.GRID),
120
+ Integer("grid_export_hw", 40345, "Grid Export Enabled (HW)", "", Kind.GRID),
117
121
  )
118
122
 
119
123
  # Settings for single phase inverters
@@ -196,6 +200,7 @@ class DT(Inverter):
196
200
  if ex.message == ILLEGAL_DATA_ADDRESS:
197
201
  logger.debug("Unsupported setting %s", setting.id_)
198
202
  self._settings.pop(setting.id_, None)
203
+ raise ValueError(f'Unknown setting "{setting.id_}"')
199
204
  return None
200
205
 
201
206
  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
@@ -332,7 +332,7 @@ class ET(Inverter):
332
332
  # Modbus registers of inverter settings, offsets are modbus register addresses
333
333
  __all_settings: Tuple[Sensor, ...] = (
334
334
  Integer("comm_address", 45127, "Communication Address", ""),
335
- Integer("modbus_baud_rate", 45132, "Modbus Baud rate", ""),
335
+ Long("modbus_baud_rate", 45132, "Modbus Baud rate", ""),
336
336
  Timestamp("time", 45200, "Inverter time"),
337
337
 
338
338
  Integer("sensitivity_check", 45246, "Sensitivity Check Mode", "", Kind.AC),
@@ -357,6 +357,8 @@ class ET(Inverter):
357
357
  Integer("work_mode", 47000, "Work Mode", "", Kind.AC),
358
358
  Integer("dred", 47010, "DRED/Remote Shutdown", "", Kind.AC),
359
359
 
360
+ Integer("meter_target_power_offset", 47120, "Meter Target Power Offset", "W", Kind.AC),
361
+
360
362
  Integer("battery_soc_protection", 47500, "Battery SoC Protection", "", Kind.BAT),
361
363
 
362
364
  Integer("grid_export", 47509, "Grid Export Enabled", "", Kind.GRID),
@@ -626,6 +628,7 @@ class ET(Inverter):
626
628
  if ex.message == ILLEGAL_DATA_ADDRESS:
627
629
  logger.debug("Unsupported setting %s", setting.id_)
628
630
  self._settings.pop(setting.id_, None)
631
+ raise ValueError(f'Unknown setting "{setting.id_}"')
629
632
  return None
630
633
 
631
634
  async def write_setting(self, setting_id: str, value: Any):
@@ -685,7 +688,7 @@ class ET(Inverter):
685
688
  try:
686
689
  mode = OperationMode(mode_id)
687
690
  except ValueError:
688
- logger.debug("Unknown work_mode value %d", mode_id)
691
+ logger.debug("Unknown work_mode value %s", mode_id)
689
692
  return None
690
693
  if OperationMode.ECO != mode:
691
694
  return mode
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
@@ -364,7 +364,7 @@ class Decimal(Sensor):
364
364
  return read_decimal2(data, self.scale)
365
365
 
366
366
  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)
367
+ return int.to_bytes(int(float(value) * self.scale), length=2, byteorder="big", signed=True)
368
368
 
369
369
 
370
370
  class Float(Sensor):
@@ -868,7 +868,7 @@ def read_voltage(buffer: ProtocolResponse, offset: int = None) -> float:
868
868
 
869
869
  def encode_voltage(value: Any) -> bytes:
870
870
  """Encode voltage value to raw (2 unsigned bytes) payload"""
871
- return int.to_bytes(int(value * 10), length=2, byteorder="big", signed=False)
871
+ return int.to_bytes(int(float(value) * 10), length=2, byteorder="big", signed=False)
872
872
 
873
873
 
874
874
  def read_current(buffer: ProtocolResponse, offset: int = None) -> float:
@@ -889,12 +889,12 @@ def read_current_signed(buffer: ProtocolResponse, offset: int = None) -> float:
889
889
 
890
890
  def encode_current(value: Any) -> bytes:
891
891
  """Encode current value to raw (2 unsigned bytes) payload"""
892
- return int.to_bytes(int(value * 10), length=2, byteorder="big", signed=False)
892
+ return int.to_bytes(int(float(value) * 10), length=2, byteorder="big", signed=False)
893
893
 
894
894
 
895
895
  def encode_current_signed(value: Any) -> bytes:
896
896
  """Encode current value to raw (2 signed bytes) payload"""
897
- return int.to_bytes(int(value * 10), length=2, byteorder="big", signed=True)
897
+ return int.to_bytes(int(float(value) * 10), length=2, byteorder="big", signed=True)
898
898
 
899
899
 
900
900
  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.6
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=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,,
@@ -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