Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for OpenDTU Modbus PR #28

Open
ArekKubacki opened this issue Jan 7, 2025 · 2 comments
Open

Add support for OpenDTU Modbus PR #28

ArekKubacki opened this issue Jan 7, 2025 · 2 comments
Labels
enhancement New feature or request

Comments

@ArekKubacki
Copy link

Description

Czy jest możliwość dodania wsparcia dla OpenDTU Modbus PR?
tbnobody/OpenDTU#1893
We have tried to maintain as much consistency as possible with the original DTU.

What I Did

Currently I have read from OpenDTU as a workaround by adding a DTU type variable. My simple code below:

                if self._dtu_type == 1:
                    start_address = i * 20 + 0x1000
                    result = self._read_registers(client, start_address, 20, self._unit_id)
                    data_to_unpack = result.encode()[1:41]
                elif self._dtu_type == 2:
                    start_address = i * 40 + 0x1000
                    result = self._read_registers(client, start_address, 40, self._unit_id)
                    data_to_unpack = result.encode()[1:81]
                else:
                    start_address = i * 40 + 0x1000
                    result = self._read_registers(client, start_address, 20, self._unit_id)
                    data_to_unpack = result.encode()[1:41]
                if self._dtu_type == 2:
                    result = self._read_registers(client, 0x2000, 3, self._unit_id)
                    self._dtu_serial_number = _serial_number_t2.unpack(result.encode()[1::])
                else:
                    result = self._read_registers(client, 0x2000, 3, self._unit_id)
                    self._dtu_serial_number = _serial_number_t.unpack(result.encode()[1::])
_udec32p1 = DecimalX(name='udec32p1', nbytes=4, precision=1, byteorder='big', signed=False)
_sdec32p1 = DecimalX(name='sdec32p1', nbytes=4, precision=1, byteorder='big', signed=True)
_udec32p2 = DecimalX(name='udec32p2', nbytes=4, precision=2, byteorder='big', signed=False)

_serial_number_t = _SerialNumberX(name='serial_number_t', nbytes=6)
_serial_number_t2 = _SerialNumberX(name='serial_number_t', nbytes=3)
_reserved = ArrayX(name='reserved', fmt=uint8)
_reserved2 = ArrayX(name='reserved', fmt=uint16)

class _PVCurrentType(Enum):
    """PV current datatype depending on inverter type."""

    MI = _udec16p1
    """MI series."""
    HM = _udec16p2
    """HM series."""
    MIDTU = _udec32p1
    """MI series."""
    HMDTU = _udec32p2
    """HM series."""

class InverterDataOpenDTU(Structure):  # type: ignore[misc]
    """Inverter data structure."""

    data_type: int = member(fmt=uint16)
    serial_number: str = member(fmt=_serial_number_t)
    serial_number2: str = member(fmt=_serial_number_t)
    """Inverter serial number."""
    port_number: int = member(fmt=uint16)
    """Port number."""
    pv_voltage: Decimal = member(fmt=_udec32p1)
    """PV voltage [V]."""
    pv_current: Decimal = member(fmt=_pv_current_type, fmt_arg=serial_number)  # type: ignore[arg-type]
    """PV current [A]."""
    grid_voltage: Decimal = member(fmt=_udec32p1)
    """Grid voltage [V]."""
    grid_frequency: Decimal = member(fmt=_udec32p2)
    """Grid frequency [Hz]."""
    pv_power: Decimal = member(fmt=_udec32p1)
    """PV power [W]."""
    today_production: int = member(fmt=uint32)
    """Today production [Wh]."""
    total_production: int = member(fmt=uint32)
	
    total_production2: int = member(fmt=uint32)
    """Total production [Wh]."""
    temperature: Decimal = member(fmt=_sdec32p1)
    """Inverter temperature [°C]."""
    operating_status: int = member(fmt=uint32)
    """Operating status."""
    alarm_code: int = member(fmt=uint32)
    """Alarm code."""
    alarm_count: int = member(fmt=uint32)
    """Alarm count."""
    link_status: int = member(fmt=uint16)
    """Link status."""
    reserved: list[int] = member(fmt=_reserved)
@dataclass
@wasilukm
Copy link
Owner

wasilukm commented Jan 8, 2025

Yeah, why not? I see that OpenDTU doesn't fully reflect all the quirks of the original DTU, which, for some reason, ignores the Modus spec and has 8-bit registers instead of 16-bit. Therefore a separate data structure will be required for OpenDTU. That's doable but my current concern is that the referred PR is still open so the modubus support is still not delivered and may be a subject of modification. I wouldn't want to provide support for something that is still unofficial.

@ArekKubacki
Copy link
Author

I don't think it will ever become a fully official work. Although many people use it in my HA module, unfortunately I can't use your library natively. Unfortunately I have to add it to the component and edit it.

@wasilukm wasilukm added the enhancement New feature or request label Jan 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants