Added 3 new batteries

This commit is contained in:
2026-05-11 18:36:58 -04:00
parent df3fb3466a
commit 38ac9ca8e8

View File

@@ -433,6 +433,12 @@ class ModbusActivePoller:
bytesize=8, parity="N", stopbits=1,
)
# Some pack/FTDI combos (observed on 2026-05-11 batch) emit one or two
# line-idle bytes before the real Modbus frame, e.g. "00 f0 40 03 4e …".
# Tolerate up to this many leading non-frame bytes by sliding the
# window and CRC-checking each candidate offset.
_MAX_LEADING_IDLE = 4
def _read_block(self, start: int, count: int) -> list[int]:
body = bytes([self._address, 0x03,
start >> 8, start & 0xFF, count >> 8, count & 0xFF])
@@ -443,7 +449,8 @@ class ModbusActivePoller:
self._ser.reset_input_buffer()
self._ser.write(frame)
expected = 3 + count * 2 + 2
# Read enough bytes to also cover any leading idle bytes.
expected = 3 + count * 2 + 2 + self._MAX_LEADING_IDLE
buf = bytearray()
deadline = time.monotonic() + self._timeout_s
while time.monotonic() < deadline and len(buf) < expected:
@@ -454,16 +461,22 @@ class ModbusActivePoller:
log.debug("pack 0x%02x [%d@%d] tx=%s rx=%s",
self._address, count, start, frame.hex(" "), raw.hex(" "))
if len(raw) < 5 or raw[0] != self._address or raw[1] != 0x03:
raise RuntimeError(f"no/bad response ({len(raw)} B) for read({count}@{start})")
bc = raw[2]
if len(raw) < 3 + bc + 2:
raise RuntimeError(f"truncated response for read({count}@{start})")
if not _crc_ok(raw, 0, 3 + bc + 2):
raise RuntimeError(f"CRC mismatch for read({count}@{start})")
data = raw[3:3 + bc]
# Locate the real frame: address byte + fn=0x03 + valid CRC, at
# offset 0..MAX_LEADING_IDLE. Reject any candidate whose CRC fails.
for off in range(min(self._MAX_LEADING_IDLE + 1, max(len(raw) - 4, 0))):
if raw[off] != self._address or raw[off + 1] != 0x03:
continue
bc = raw[off + 2]
frame_end = off + 3 + bc + 2
if frame_end > len(raw):
continue
if not _crc_ok(raw, off, 3 + bc + 2):
continue
data = raw[off + 3:off + 3 + bc]
return [(data[i] << 8) | data[i + 1] for i in range(0, len(data), 2)]
raise RuntimeError(f"no valid frame in {len(raw)} bytes for read({count}@{start})")
def poll(self) -> list[int]:
self._open()
# Build a sparse 136-element register array.