Skip to content

Commit

Permalink
Add support for writing generic modbus register
Browse files Browse the repository at this point in the history
  • Loading branch information
mletenay committed May 11, 2024
1 parent 72e65ed commit 5f1811d
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 27 deletions.
51 changes: 39 additions & 12 deletions goodwe/dt.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
from __future__ import annotations

import logging
from typing import Tuple

from .exceptions import InverterError
from .exceptions import InverterError, RequestRejectedException
from .inverter import Inverter
from .inverter import OperationMode
from .inverter import SensorKind as Kind
from .modbus import ILLEGAL_DATA_ADDRESS
from .model import is_3_mppt, is_single_phase
from .protocol import ProtocolCommand
from .sensor import *

logger = logging.getLogger(__name__)


class DT(Inverter):
"""Class representing inverter of DT/MS/D-NS/XS or GE's GEP(PSB/PSC) families"""
Expand Down Expand Up @@ -176,21 +180,44 @@ async def read_runtime_data(self) -> Dict[str, Any]:
return data

async def read_setting(self, setting_id: str) -> Any:
if setting_id.startswith("modbus"):
response = await self._read_from_socket(self._read_command(int(setting_id[7:]), 1))
return int.from_bytes(response.read(2), byteorder="big", signed=True)
setting = self._settings.get(setting_id)
if not setting:
raise ValueError(f'Unknown setting "{setting_id}"')
count = (setting.size_ + (setting.size_ % 2)) // 2
response = await self._read_from_socket(self._read_command(setting.offset, count))
return setting.read_value(response)
if setting:
return await self._read_setting(setting)
else:
if setting_id.startswith("modbus"):
response = await self._read_from_socket(self._read_command(int(setting_id[7:]), 1))
return int.from_bytes(response.read(2), byteorder="big", signed=True)
else:
raise ValueError(f'Unknown setting "{setting_id}"')

async def _read_setting(self, setting: Sensor) -> Any:
try:
count = (setting.size_ + (setting.size_ % 2)) // 2
response = await self._read_from_socket(self._read_command(setting.offset, count))
return setting.read_value(response)
except RequestRejectedException as ex:
if ex.message == ILLEGAL_DATA_ADDRESS:
logger.debug("Unsupported setting %s", setting.id_)
self._settings.pop(setting.id_, None)
return None

async def write_setting(self, setting_id: str, value: Any):
setting = self._settings.get(setting_id)
if not setting:
raise ValueError(f'Unknown setting "{setting_id}"')
raw_value = setting.encode_value(value)
if setting:
await self._write_setting(setting, value)
else:
if setting_id.startswith("modbus"):
await self._read_from_socket(self._write_command(int(setting_id[7:]), int(value)))
else:
raise ValueError(f'Unknown setting "{setting_id}"')

async def _write_setting(self, setting: Sensor, value: Any):
if setting.size_ == 1:
# modbus can address/store only 16 bit values, read the other 8 bytes
response = await self._read_from_socket(self._read_command(setting.offset, 1))
raw_value = setting.encode_value(value, response.response_data()[0:2])
else:
raw_value = setting.encode_value(value)
if len(raw_value) <= 2:
value = int.from_bytes(raw_value, byteorder="big", signed=True)
await self._read_from_socket(self._write_command(setting.offset, value))
Expand Down
2 changes: 2 additions & 0 deletions goodwe/es.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ async def write_setting(self, setting_id: str, value: Any):
await self._read_from_socket(
Aa55ProtocolCommand("030206" + Timestamp("time", 0, "").encode_value(value).hex(), "0382")
)
elif setting_id.startswith("modbus"):
await self._read_from_socket(self._write_command(int(setting_id[7:]), int(value)))
else:
setting: Sensor | None = self._settings.get(setting_id)
if not setting:
Expand Down
36 changes: 21 additions & 15 deletions goodwe/et.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,30 +610,36 @@ async def read_runtime_data(self) -> Dict[str, Any]:
return data

async def read_setting(self, setting_id: str) -> Any:
if setting_id.startswith("modbus"):
response = await self._read_from_socket(self._read_command(int(setting_id[7:]), 1))
return int.from_bytes(response.read(2), byteorder="big", signed=True)
setting = self._settings.get(setting_id)
if not setting:
raise ValueError(f'Unknown setting "{setting_id}"')
try:
if setting:
return await self._read_setting(setting)
else:
if setting_id.startswith("modbus"):
response = await self._read_from_socket(self._read_command(int(setting_id[7:]), 1))
return int.from_bytes(response.read(2), byteorder="big", signed=True)
else:
raise ValueError(f'Unknown setting "{setting_id}"')

async def _read_setting(self, setting: Sensor) -> Any:
try:
count = (setting.size_ + (setting.size_ % 2)) // 2
response = await self._read_from_socket(self._read_command(setting.offset, count))
return setting.read_value(response)
except RequestRejectedException as ex:
if ex.message == ILLEGAL_DATA_ADDRESS:
logger.debug("Unsupported setting %s", setting.id_)
self._settings.pop(setting_id, None)
self._settings.pop(setting.id_, None)
return None

async def _read_setting(self, setting: Sensor) -> Any:
count = (setting.size_ + (setting.size_ % 2)) // 2
response = await self._read_from_socket(self._read_command(setting.offset, count))
return setting.read_value(response)

async def write_setting(self, setting_id: str, value: Any):
setting = self._settings.get(setting_id)
if not setting:
raise ValueError(f'Unknown setting "{setting_id}"')
await self._write_setting(setting, value)
if setting:
await self._write_setting(setting, value)
else:
if setting_id.startswith("modbus"):
await self._read_from_socket(self._write_command(int(setting_id[7:]), int(value)))
else:
raise ValueError(f'Unknown setting "{setting_id}"')

async def _write_setting(self, setting: Sensor, value: Any):
if setting.size_ == 1:
Expand Down
3 changes: 3 additions & 0 deletions tests/test_et.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ def test_GW10K_ET_write_setting(self):
self.loop.run_until_complete(self.write_setting('grid_export_limit', 100))
self.assertEqual('f706b996006459c7', self.request.hex())

self.loop.run_until_complete(self.write_setting('modbus_47510', 100))
self.assertEqual('f706b996006459c7', self.request.hex())

self.loop.run_until_complete(self.write_setting('time', datetime(2022, 1, 4, 18, 30, 25)))
self.assertEqual('f710b090000306160104121e19a961', self.request.hex())

Expand Down

0 comments on commit 5f1811d

Please sign in to comment.