goodwe 0.3.6__tar.gz → 0.4.1__tar.gz
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-0.3.6/goodwe.egg-info → goodwe-0.4.1}/PKG-INFO +12 -7
- {goodwe-0.3.6 → goodwe-0.4.1}/README.md +11 -6
- goodwe-0.4.1/VERSION +1 -0
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe/__init__.py +32 -37
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe/const.py +1 -0
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe/dt.py +8 -12
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe/es.py +14 -14
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe/et.py +104 -79
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe/inverter.py +37 -38
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe/modbus.py +109 -7
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe/model.py +0 -4
- goodwe-0.4.1/goodwe/protocol.py +618 -0
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe/sensor.py +32 -24
- {goodwe-0.3.6 → goodwe-0.4.1/goodwe.egg-info}/PKG-INFO +12 -7
- {goodwe-0.3.6 → goodwe-0.4.1}/tests/test_dt.py +3 -3
- {goodwe-0.3.6 → goodwe-0.4.1}/tests/test_es.py +2 -16
- {goodwe-0.3.6 → goodwe-0.4.1}/tests/test_et.py +66 -48
- goodwe-0.4.1/tests/test_modbus.py +111 -0
- {goodwe-0.3.6 → goodwe-0.4.1}/tests/test_protocol.py +42 -33
- {goodwe-0.3.6 → goodwe-0.4.1}/tests/test_sensor.py +3 -10
- goodwe-0.3.6/VERSION +0 -1
- goodwe-0.3.6/goodwe/protocol.py +0 -338
- goodwe-0.3.6/tests/test_modbus.py +0 -66
- {goodwe-0.3.6 → goodwe-0.4.1}/LICENSE +0 -0
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe/exceptions.py +0 -0
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe.egg-info/SOURCES.txt +0 -0
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe.egg-info/dependency_links.txt +0 -0
- {goodwe-0.3.6 → goodwe-0.4.1}/goodwe.egg-info/top_level.txt +0 -0
- {goodwe-0.3.6 → goodwe-0.4.1}/pyproject.toml +0 -0
- {goodwe-0.3.6 → goodwe-0.4.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: goodwe
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
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
|
|
@@ -32,15 +32,21 @@ License-File: LICENSE
|
|
|
32
32
|
Library for connecting to GoodWe inverter over local network and retrieving runtime sensor values and configuration
|
|
33
33
|
parameters.
|
|
34
34
|
|
|
35
|
-
It has been reported to work
|
|
36
|
-
work
|
|
37
|
-
protocols.
|
|
35
|
+
It has been reported to work with GoodWe ET, EH, BT, BH, ES, EM, BP, DT, MS, D-NS, and XS families of inverters. It
|
|
36
|
+
should work with other inverters as well, as long as they listen on UDP port 8899 and respond to one of supported
|
|
37
|
+
communication protocols.
|
|
38
|
+
In general, if you can connect to your inverter with the official mobile app (SolarGo/PvMaster) over Wi-Fi (not
|
|
39
|
+
bluetooth), this library should work.
|
|
38
40
|
|
|
39
41
|
(If you can't communicate with the inverter despite your model is listed above, it is possible you have old ARM firmware
|
|
40
42
|
version. You should ask manufacturer support to upgrade your ARM firmware (not just inverter firmware) to be able to
|
|
41
|
-
communicate with the
|
|
43
|
+
communicate with the inverter via UDP.)
|
|
42
44
|
|
|
43
|
-
White-label (GoodWe manufactured) inverters may work as well, e.g. General Electric GEP (PSB, PSC) and GEH models
|
|
45
|
+
White-label (GoodWe manufactured) inverters may work as well, e.g. General Electric GEP (PSB, PSC) and GEH models are
|
|
46
|
+
know to work properly.
|
|
47
|
+
|
|
48
|
+
Since v0.4.x the library also supports standard Modbus/TCP over port 502.
|
|
49
|
+
This protocol is supported by the V2.0 version of LAN+WiFi communication dongle (model WLA0000-01-00P).
|
|
44
50
|
|
|
45
51
|
## Usage
|
|
46
52
|
|
|
@@ -72,4 +78,3 @@ asyncio.run(get_runtime_data())
|
|
|
72
78
|
- https://github.com/mletenay/home-assistant-goodwe-inverter
|
|
73
79
|
- https://github.com/yasko-pv/modbus-log
|
|
74
80
|
- https://github.com/tkubec/GoodWe
|
|
75
|
-
- https://github.com/OpenEMS/openems
|
|
@@ -8,15 +8,21 @@
|
|
|
8
8
|
Library for connecting to GoodWe inverter over local network and retrieving runtime sensor values and configuration
|
|
9
9
|
parameters.
|
|
10
10
|
|
|
11
|
-
It has been reported to work
|
|
12
|
-
work
|
|
13
|
-
protocols.
|
|
11
|
+
It has been reported to work with GoodWe ET, EH, BT, BH, ES, EM, BP, DT, MS, D-NS, and XS families of inverters. It
|
|
12
|
+
should work with other inverters as well, as long as they listen on UDP port 8899 and respond to one of supported
|
|
13
|
+
communication protocols.
|
|
14
|
+
In general, if you can connect to your inverter with the official mobile app (SolarGo/PvMaster) over Wi-Fi (not
|
|
15
|
+
bluetooth), this library should work.
|
|
14
16
|
|
|
15
17
|
(If you can't communicate with the inverter despite your model is listed above, it is possible you have old ARM firmware
|
|
16
18
|
version. You should ask manufacturer support to upgrade your ARM firmware (not just inverter firmware) to be able to
|
|
17
|
-
communicate with the
|
|
19
|
+
communicate with the inverter via UDP.)
|
|
18
20
|
|
|
19
|
-
White-label (GoodWe manufactured) inverters may work as well, e.g. General Electric GEP (PSB, PSC) and GEH models
|
|
21
|
+
White-label (GoodWe manufactured) inverters may work as well, e.g. General Electric GEP (PSB, PSC) and GEH models are
|
|
22
|
+
know to work properly.
|
|
23
|
+
|
|
24
|
+
Since v0.4.x the library also supports standard Modbus/TCP over port 502.
|
|
25
|
+
This protocol is supported by the V2.0 version of LAN+WiFi communication dongle (model WLA0000-01-00P).
|
|
20
26
|
|
|
21
27
|
## Usage
|
|
22
28
|
|
|
@@ -48,4 +54,3 @@ asyncio.run(get_runtime_data())
|
|
|
48
54
|
- https://github.com/mletenay/home-assistant-goodwe-inverter
|
|
49
55
|
- https://github.com/yasko-pv/modbus-log
|
|
50
56
|
- https://github.com/tkubec/GoodWe
|
|
51
|
-
- https://github.com/OpenEMS/openems
|
goodwe-0.4.1/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.4.1
|
|
@@ -2,8 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import logging
|
|
5
|
-
from typing import Type
|
|
6
5
|
|
|
6
|
+
from .const import GOODWE_TCP_PORT, GOODWE_UDP_PORT
|
|
7
7
|
from .dt import DT
|
|
8
8
|
from .es import ES
|
|
9
9
|
from .et import ET
|
|
@@ -26,8 +26,8 @@ DISCOVERY_COMMAND = Aa55ProtocolCommand("010200", "0182")
|
|
|
26
26
|
_SUPPORTED_PROTOCOLS = [ET, DT, ES]
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
async def connect(host: str, family: str = None, comm_addr: int = 0, timeout: int = 1,
|
|
30
|
-
do_discover: bool = True) -> Inverter:
|
|
29
|
+
async def connect(host: str, port: int = GOODWE_UDP_PORT, family: str = None, comm_addr: int = 0, timeout: int = 1,
|
|
30
|
+
retries: int = 3, do_discover: bool = True) -> Inverter:
|
|
31
31
|
"""Contact the inverter at the specified host/port and answer appropriate Inverter instance.
|
|
32
32
|
|
|
33
33
|
The specific inverter family/type will be detected automatically, but it can be passed explicitly.
|
|
@@ -41,24 +41,24 @@ async def connect(host: str, family: str = None, comm_addr: int = 0, timeout: in
|
|
|
41
41
|
|
|
42
42
|
Raise InverterError if unable to contact or recognise supported inverter.
|
|
43
43
|
"""
|
|
44
|
-
if family in ET_FAMILY:
|
|
45
|
-
inv = ET(host, comm_addr, timeout, retries)
|
|
44
|
+
if family in ET_FAMILY or port == GOODWE_TCP_PORT:
|
|
45
|
+
inv = ET(host, port, comm_addr, timeout, retries)
|
|
46
46
|
elif family in ES_FAMILY:
|
|
47
|
-
inv = ES(host, comm_addr, timeout, retries)
|
|
47
|
+
inv = ES(host, port, comm_addr, timeout, retries)
|
|
48
48
|
elif family in DT_FAMILY:
|
|
49
|
-
inv = DT(host, comm_addr, timeout, retries)
|
|
49
|
+
inv = DT(host, port, comm_addr, timeout, retries)
|
|
50
50
|
elif do_discover:
|
|
51
|
-
return await discover(host, timeout, retries)
|
|
51
|
+
return await discover(host, port, timeout, retries)
|
|
52
52
|
else:
|
|
53
53
|
raise InverterError("Specify either an inverter family or set do_discover True")
|
|
54
54
|
|
|
55
|
-
logger.debug("Connecting to %s family inverter at %s.", family, host)
|
|
55
|
+
logger.debug("Connecting to %s family inverter at %s:%s.", family, host, port)
|
|
56
56
|
await inv.read_device_info()
|
|
57
57
|
logger.debug("Connected to inverter %s, S/N:%s.", inv.model_name, inv.serial_number)
|
|
58
58
|
return inv
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
async def discover(host: str, timeout: int = 1, retries: int = 3) -> Inverter:
|
|
61
|
+
async def discover(host: str, port: int = GOODWE_UDP_PORT, timeout: int = 1, retries: int = 3) -> Inverter:
|
|
62
62
|
"""Contact the inverter at the specified value and answer appropriate Inverter instance
|
|
63
63
|
|
|
64
64
|
Raise InverterError if unable to contact or recognise supported inverter
|
|
@@ -67,28 +67,33 @@ async def discover(host: str, timeout: int = 1, retries: int = 3) -> Inverter:
|
|
|
67
67
|
|
|
68
68
|
# Try the common AA55C07F0102000241 command first and detect inverter type from serial_number
|
|
69
69
|
try:
|
|
70
|
-
logger.debug("Probing inverter at %s.", host)
|
|
71
|
-
response = await DISCOVERY_COMMAND.execute(host, timeout, retries)
|
|
70
|
+
logger.debug("Probing inverter at %s:%s.", host, port)
|
|
71
|
+
response = await DISCOVERY_COMMAND.execute(UdpInverterProtocol(host, port, timeout, retries))
|
|
72
72
|
response = response.response_data()
|
|
73
73
|
model_name = response[5:15].decode("ascii").rstrip()
|
|
74
74
|
serial_number = response[31:47].decode("ascii")
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
i: Inverter | None = None
|
|
77
77
|
for model_tag in ET_MODEL_TAGS:
|
|
78
78
|
if model_tag in serial_number:
|
|
79
79
|
logger.debug("Detected ET/EH/BT/BH/GEH inverter %s, S/N:%s.", model_name, serial_number)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
80
|
+
i = ET(host, port, 0, timeout, retries)
|
|
81
|
+
break
|
|
82
|
+
if not i:
|
|
83
|
+
for model_tag in ES_MODEL_TAGS:
|
|
84
|
+
if model_tag in serial_number:
|
|
85
|
+
logger.debug("Detected ES/EM/BP inverter %s, S/N:%s.", model_name, serial_number)
|
|
86
|
+
i = ES(host, port, 0, timeout, retries)
|
|
87
|
+
break
|
|
88
|
+
if not i:
|
|
89
|
+
for model_tag in DT_MODEL_TAGS:
|
|
90
|
+
if model_tag in serial_number:
|
|
91
|
+
logger.debug("Detected DT/MS/D-NS/XS/GEP inverter %s, S/N:%s.", model_name, serial_number)
|
|
92
|
+
i = DT(host, port, 0, timeout, retries)
|
|
93
|
+
break
|
|
94
|
+
if i:
|
|
91
95
|
await i.read_device_info()
|
|
96
|
+
logger.debug("Connected to inverter %s, S/N:%s.", i.model_name, i.serial_number)
|
|
92
97
|
return i
|
|
93
98
|
|
|
94
99
|
except InverterError as ex:
|
|
@@ -96,7 +101,7 @@ async def discover(host: str, timeout: int = 1, retries: int = 3) -> Inverter:
|
|
|
96
101
|
|
|
97
102
|
# Probe inverter specific protocols
|
|
98
103
|
for inv in _SUPPORTED_PROTOCOLS:
|
|
99
|
-
i = inv(host, 0, timeout, retries)
|
|
104
|
+
i = inv(host, port, 0, timeout, retries)
|
|
100
105
|
try:
|
|
101
106
|
logger.debug("Probing %s inverter at %s.", inv.__name__, host)
|
|
102
107
|
await i.read_device_info()
|
|
@@ -119,22 +124,12 @@ async def search_inverters() -> bytes:
|
|
|
119
124
|
Raise InverterError if unable to contact any inverter
|
|
120
125
|
"""
|
|
121
126
|
logger.debug("Searching inverters by broadcast to port 48899")
|
|
122
|
-
loop = asyncio.get_running_loop()
|
|
123
127
|
command = ProtocolCommand("WIFIKIT-214028-READ".encode("utf-8"), lambda r: True)
|
|
124
|
-
response_future = loop.create_future()
|
|
125
|
-
transport, _ = await loop.create_datagram_endpoint(
|
|
126
|
-
lambda: UdpInverterProtocol(response_future, command, 1, 3),
|
|
127
|
-
remote_addr=("255.255.255.255", 48899),
|
|
128
|
-
allow_broadcast=True,
|
|
129
|
-
)
|
|
130
128
|
try:
|
|
131
|
-
await
|
|
132
|
-
result = response_future.result()
|
|
129
|
+
result = await command.execute(UdpInverterProtocol("255.255.255.255", 48899, 1, 0))
|
|
133
130
|
if result is not None:
|
|
134
|
-
return result
|
|
131
|
+
return result.response_data()
|
|
135
132
|
else:
|
|
136
133
|
raise InverterError("No response received to broadcast request.")
|
|
137
134
|
except asyncio.CancelledError:
|
|
138
135
|
raise InverterError("No valid response received to broadcast request.") from None
|
|
139
|
-
finally:
|
|
140
|
-
transport.close()
|
|
@@ -7,7 +7,7 @@ from .inverter import Inverter
|
|
|
7
7
|
from .inverter import OperationMode
|
|
8
8
|
from .inverter import SensorKind as Kind
|
|
9
9
|
from .model import is_3_mppt, is_single_phase
|
|
10
|
-
from .protocol import ProtocolCommand
|
|
10
|
+
from .protocol import ProtocolCommand
|
|
11
11
|
from .sensor import *
|
|
12
12
|
|
|
13
13
|
|
|
@@ -110,10 +110,6 @@ class DT(Inverter):
|
|
|
110
110
|
Integer("shadow_scan", 40326, "Shadow Scan", "", Kind.PV),
|
|
111
111
|
Integer("grid_export", 40327, "Grid Export Enabled", "", Kind.GRID),
|
|
112
112
|
Integer("grid_export_limit", 40328, "Grid Export Limit", "%", Kind.GRID),
|
|
113
|
-
Integer("start", 40330, "Start / Power On", "", Kind.GRID),
|
|
114
|
-
Integer("stop", 40331, "Stop / Power Off", "", Kind.GRID),
|
|
115
|
-
Integer("restart", 40332, "Restart", "", Kind.GRID),
|
|
116
|
-
Integer("grid_export_hw", 40345, "Grid Export Enabled (HW)", "", Kind.GRID),
|
|
117
113
|
)
|
|
118
114
|
|
|
119
115
|
# Settings for single phase inverters
|
|
@@ -126,13 +122,13 @@ class DT(Inverter):
|
|
|
126
122
|
Integer("grid_export_limit", 40336, "Grid Export Limit", "%", Kind.GRID),
|
|
127
123
|
)
|
|
128
124
|
|
|
129
|
-
def __init__(self, host: str, comm_addr: int = 0, timeout: int = 1, retries: int = 3):
|
|
130
|
-
super().__init__(host, comm_addr, timeout, retries)
|
|
125
|
+
def __init__(self, host: str, port: int, comm_addr: int = 0, timeout: int = 1, retries: int = 3):
|
|
126
|
+
super().__init__(host, port, comm_addr, timeout, retries)
|
|
131
127
|
if not self.comm_addr:
|
|
132
128
|
# Set the default inverter address
|
|
133
129
|
self.comm_addr = 0x7f
|
|
134
|
-
self._READ_DEVICE_VERSION_INFO: ProtocolCommand =
|
|
135
|
-
self._READ_DEVICE_RUNNING_DATA: ProtocolCommand =
|
|
130
|
+
self._READ_DEVICE_VERSION_INFO: ProtocolCommand = self._read_command(0x7531, 0x0028)
|
|
131
|
+
self._READ_DEVICE_RUNNING_DATA: ProtocolCommand = self._read_command(0x7594, 0x0049)
|
|
136
132
|
self._sensors = self.__all_sensors
|
|
137
133
|
self._settings: dict[str, Sensor] = {s.id_: s for s in self.__all_settings}
|
|
138
134
|
|
|
@@ -184,7 +180,7 @@ class DT(Inverter):
|
|
|
184
180
|
if not setting:
|
|
185
181
|
raise ValueError(f'Unknown setting "{setting_id}"')
|
|
186
182
|
count = (setting.size_ + (setting.size_ % 2)) // 2
|
|
187
|
-
response = await self._read_from_socket(
|
|
183
|
+
response = await self._read_from_socket(self._read_command(setting.offset, count))
|
|
188
184
|
return setting.read_value(response)
|
|
189
185
|
|
|
190
186
|
async def write_setting(self, setting_id: str, value: Any):
|
|
@@ -194,9 +190,9 @@ class DT(Inverter):
|
|
|
194
190
|
raw_value = setting.encode_value(value)
|
|
195
191
|
if len(raw_value) <= 2:
|
|
196
192
|
value = int.from_bytes(raw_value, byteorder="big", signed=True)
|
|
197
|
-
await self._read_from_socket(
|
|
193
|
+
await self._read_from_socket(self._write_command(setting.offset, value))
|
|
198
194
|
else:
|
|
199
|
-
await self._read_from_socket(
|
|
195
|
+
await self._read_from_socket(self._write_multi_command(setting.offset, raw_value))
|
|
200
196
|
|
|
201
197
|
async def read_settings_data(self) -> Dict[str, Any]:
|
|
202
198
|
data = {}
|
|
@@ -7,8 +7,7 @@ from .exceptions import InverterError
|
|
|
7
7
|
from .inverter import Inverter
|
|
8
8
|
from .inverter import OperationMode
|
|
9
9
|
from .inverter import SensorKind as Kind
|
|
10
|
-
from .protocol import ProtocolCommand, Aa55ProtocolCommand, Aa55ReadCommand, Aa55WriteCommand, Aa55WriteMultiCommand
|
|
11
|
-
ModbusReadCommand, ModbusWriteCommand, ModbusWriteMultiCommand
|
|
10
|
+
from .protocol import ProtocolCommand, Aa55ProtocolCommand, Aa55ReadCommand, Aa55WriteCommand, Aa55WriteMultiCommand
|
|
12
11
|
from .sensor import *
|
|
13
12
|
|
|
14
13
|
logger = logging.getLogger(__name__)
|
|
@@ -168,8 +167,8 @@ class ES(Inverter):
|
|
|
168
167
|
ByteH("eco_mode_4_switch", 47567, "Eco Mode Group 4 Switch"),
|
|
169
168
|
)
|
|
170
169
|
|
|
171
|
-
def __init__(self, host: str, comm_addr: int = 0, timeout: int = 1, retries: int = 3):
|
|
172
|
-
super().__init__(host, comm_addr, timeout, retries)
|
|
170
|
+
def __init__(self, host: str, port: int, comm_addr: int = 0, timeout: int = 1, retries: int = 3):
|
|
171
|
+
super().__init__(host, port, comm_addr, timeout, retries)
|
|
173
172
|
if not self.comm_addr:
|
|
174
173
|
# Set the default inverter address
|
|
175
174
|
self.comm_addr = 0xf7
|
|
@@ -178,11 +177,11 @@ class ES(Inverter):
|
|
|
178
177
|
def _supports_eco_mode_v2(self) -> bool:
|
|
179
178
|
if self.arm_version < 14:
|
|
180
179
|
return False
|
|
181
|
-
if "EMU" in self.serial_number
|
|
180
|
+
if "EMU" in self.serial_number:
|
|
182
181
|
return self.dsp1_version >= 11
|
|
183
|
-
if "ESU" in self.serial_number
|
|
182
|
+
if "ESU" in self.serial_number:
|
|
184
183
|
return self.dsp1_version >= 22
|
|
185
|
-
if "BPS" in self.serial_number
|
|
184
|
+
if "BPS" in self.serial_number:
|
|
186
185
|
return self.dsp1_version >= 10
|
|
187
186
|
return False
|
|
188
187
|
|
|
@@ -192,7 +191,7 @@ class ES(Inverter):
|
|
|
192
191
|
self.firmware = self._decode(response[0:5]).rstrip()
|
|
193
192
|
self.model_name = self._decode(response[5:15]).rstrip()
|
|
194
193
|
self.serial_number = self._decode(response[31:47])
|
|
195
|
-
self.
|
|
194
|
+
self.software_version = self._decode(response[51:63])
|
|
196
195
|
try:
|
|
197
196
|
if len(self.firmware) >= 2:
|
|
198
197
|
self.dsp1_version = int(self.firmware[0:2])
|
|
@@ -228,7 +227,7 @@ class ES(Inverter):
|
|
|
228
227
|
async def _read_setting(self, setting: Sensor) -> Any:
|
|
229
228
|
count = (setting.size_ + (setting.size_ % 2)) // 2
|
|
230
229
|
if self._is_modbus_setting(setting):
|
|
231
|
-
response = await self._read_from_socket(
|
|
230
|
+
response = await self._read_from_socket(self._read_command(setting.offset, count))
|
|
232
231
|
return setting.read_value(response)
|
|
233
232
|
else:
|
|
234
233
|
response = await self._read_from_socket(Aa55ReadCommand(setting.offset, count))
|
|
@@ -249,21 +248,22 @@ class ES(Inverter):
|
|
|
249
248
|
if setting.size_ == 1:
|
|
250
249
|
# modbus can address/store only 16 bit values, read the other 8 bytes
|
|
251
250
|
if self._is_modbus_setting(setting):
|
|
252
|
-
response = await self._read_from_socket(
|
|
251
|
+
response = await self._read_from_socket(self._read_command(setting.offset, 1))
|
|
252
|
+
raw_value = setting.encode_value(value, response.response_data()[0:2])
|
|
253
253
|
else:
|
|
254
254
|
response = await self._read_from_socket(Aa55ReadCommand(setting.offset, 1))
|
|
255
|
-
|
|
255
|
+
raw_value = setting.encode_value(value, response.response_data()[2:4])
|
|
256
256
|
else:
|
|
257
257
|
raw_value = setting.encode_value(value)
|
|
258
258
|
if len(raw_value) <= 2:
|
|
259
259
|
value = int.from_bytes(raw_value, byteorder="big", signed=True)
|
|
260
260
|
if self._is_modbus_setting(setting):
|
|
261
|
-
await self._read_from_socket(
|
|
261
|
+
await self._read_from_socket(self._write_command(setting.offset, value))
|
|
262
262
|
else:
|
|
263
263
|
await self._read_from_socket(Aa55WriteCommand(setting.offset, value))
|
|
264
264
|
else:
|
|
265
265
|
if self._is_modbus_setting(setting):
|
|
266
|
-
await self._read_from_socket(
|
|
266
|
+
await self._read_from_socket(self._write_multi_command(setting.offset, raw_value))
|
|
267
267
|
else:
|
|
268
268
|
await self._read_from_socket(Aa55WriteMultiCommand(setting.offset, raw_value))
|
|
269
269
|
|
|
@@ -290,7 +290,7 @@ class ES(Inverter):
|
|
|
290
290
|
result.remove(OperationMode.ECO_DISCHARGE)
|
|
291
291
|
return tuple(result)
|
|
292
292
|
|
|
293
|
-
async def get_operation_mode(self) -> OperationMode:
|
|
293
|
+
async def get_operation_mode(self) -> OperationMode | None:
|
|
294
294
|
mode_id = await self.read_setting('work_mode')
|
|
295
295
|
try:
|
|
296
296
|
mode = OperationMode(mode_id)
|