Skip to content

Commit

Permalink
Add sequence number management for packet validation in SolarmanSunsynk
Browse files Browse the repository at this point in the history
- Introduced `current_sequence_number` attribute to track the sequence number.
- Added `advance_sequence_number` method to generate and increment the sequence number.
- Updated `write_register` and `read_holding_registers` methods to utilize the new sequence number for packet validation.
  • Loading branch information
maslyankov committed Jan 22, 2025
1 parent 63dfd4f commit 1dbb1b6
Showing 1 changed file with 16 additions and 2 deletions.
18 changes: 16 additions & 2 deletions src/sunsynk/solarmansunsynk.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import asyncio
import logging
from random import randrange
from typing import Sequence
from urllib.parse import urlparse

Expand All @@ -22,6 +23,7 @@ class SolarmanSunsynk(Sunsynk):

client: PySolarmanV5Async = None
dongle_serial_number: int = attrs.field(kw_only=True)
current_sequence_number: int | None = attrs.field(default=None, init=False)

@dongle_serial_number.validator
def check_serial(self, _: attrs.Attribute, value: str) -> None:
Expand All @@ -35,6 +37,14 @@ def check_serial(self, _: attrs.Attribute, value: str) -> None:
f"DONGLE_SERIAL_NUMBER must be an integer, got '{value}'"
) from err

def advance_sequence_number(self) -> None:
"""Generate and advance the sequence number for packet validation."""
# Generate initial value randomly and increment from then forward
if self.current_sequence_number is None:
self.current_sequence_number = randrange(0x01, 0xFF)
else:
self.current_sequence_number = (self.current_sequence_number + 1) & 0xFF # prevent overflow

async def connect(self) -> None:
"""Connect."""
if self.client:
Expand Down Expand Up @@ -70,8 +80,9 @@ async def write_register(self, *, address: int, value: int) -> bool:
try:
_LOGGER.debug("DBG: write_register: %s ==> ...", [value])
await self.connect()
self.advance_sequence_number() # Set sequence number for this request
res = await self.client.write_multiple_holding_registers(
register_addr=address, values=[value]
register_addr=address, values=[value], sequence_number=self.current_sequence_number
)
_LOGGER.debug("DBG: write_register: %s ==> %s", [value], res)
return True
Expand All @@ -91,7 +102,10 @@ async def read_holding_registers(self, start: int, length: int) -> Sequence[int]
while True:
try:
await self.connect()
return await self.client.read_holding_registers(start, length)
self.advance_sequence_number() # Set sequence number for this request
return await self.client.read_holding_registers(
start, length, sequence_number=self.current_sequence_number
)
except Exception as err: # pylint: disable=broad-except
attempt += 1
_LOGGER.error("Error reading: %s (retry %s)", err, attempt)
Expand Down

0 comments on commit 1dbb1b6

Please sign in to comment.