Skip to content

Fix struct.error crashes on Conext SW 4024 / MPPT 60 150 (shorter fast-packet payloads) - #4

Open
kaanow wants to merge 1 commit into
extrafu:mainfrom
kaanow:fix/tolerate-shorter-payloads
Open

Fix struct.error crashes on Conext SW 4024 / MPPT 60 150 (shorter fast-packet payloads)#4
kaanow wants to merge 1 commit into
extrafu:mainfrom
kaanow:fix/tolerate-shorter-payloads

Conversation

@kaanow

@kaanow kaanow commented Jul 29, 2026

Copy link
Copy Markdown

The problem

Running berrybms against a Conext SW 4024 + MPPT 60 150 site crashes in every fast-packet processor: this device generation sends shorter payloads than the XW+ / MPPT 80 600 the code was developed on, and the fixed-size struct.unpack calls raise struct.error.

Observed payload lengths (from a live capture corpus, ~59k reassembled messages):

PGN XW+ / MPPT 80 600 (this repo) SW 4024 / MPPT 60 150
BattSts2 (0x1F0C4) 41 36
DcSrcSts2 (0x1F0C5) 27 21
ChgSts (0x1F00E) 20 17
AcStsRms (0x1F016) 55 / 83 78

The fix

The field layouts are prefix-stable — the older devices just send fewer trailing bytes. (Verified: battery voltage decodes at your documented offsets on the SW 4024 and matches the same site's InsightHome Modbus registers at r = +0.98.) So:

  • switch each processor to struct.unpack_from + a minimum-length guard;
  • branch processAcStsRms on the association id (0x13 gen / 0x33 loads / 0x43 grid — per your own comments) instead of the exact payload length, and only read the extra grid block past byte 55 when it's present.

Testing

  • 59k real reassembled payloads from the SW 4024 / MPPT 60 150 bus through all four processors: no exceptions, values sensible (battery/PV V/I/W, charge stage all cross-checked against Modbus).
  • Regression: the full-length sample payloads from this file's own comments (27 B DcSrcSts2 → 266.56 V / 1356 W, 41 B BattSts2) decode unchanged.

Two related findings from the same site that may interest you, documented in our fork's findings notes:

  1. The MPPT 60 150 never populates PV-side current/power in DcSrcSts2 assoc 0x15 (hard zeros even at full production, and the InsightHome's Modbus PV-current registers are zero too) — production on that model is only available via the assoc 0x03 output channel.
  2. The assoc values you identified empirically match the official Xantrex XB_eAC_SRC_ID/XB_eDC_SRC_ID enums leaked in the Freedom SW-RVC DGN Reference Guide (976-0452-01-01): 0x03=HOUSE_BAT_BANK1, 0x13=GEN1, 0x15=SOLAR_ARRAY1, 0x33=AC_LOAD1, 0x43=GRID1.

(Independent of #3, which fixes >16-frame reassembly; the two can merge in either order.)

…processors

A Conext SW 4024 + MPPT 60 150 site sends shorter fast-packet payloads than
the XW+ / MPPT 80 600 generation this code was developed against:

  PGN        XW+/80600   SW4024/60150
  BattSts2       41           36
  DcSrcSts2      27           21
  ChgSts         20           17
  AcStsRms     55/83          78

Every processor used fixed-size struct.unpack, so ALL of them raise
struct.error on such a site. The field layouts are prefix-stable (verified:
battery V decodes at the same offsets and matches the site's InsightHome
Modbus registers at r=+0.98), so switch to struct.unpack_from with minimum-
length guards, and branch AcStsRms on the association id (0x13 gen / 0x33
loads / 0x43 grid, per the existing comments) instead of the exact payload
length. The extra grid block past byte 55 is only read when present.

Tested on 59k reassembled payloads from a live SW 4024 + MPPT 60 150 bus
(no exceptions, sensible values) and against the full-length sample payloads
in this file's comments (unchanged results).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant