The iBMS PC Utility's periodic poll set is exactly 33 DIDs and our util/capture_dual_can.py / bms/solectrac-bms-diagnostics.py already match it 1:1 (audited against dual-capture-charging-120-10p-to-100p.asc). However, the History → XLSX export surfaces fields that aren't reachable from any DID we currently poll — they must come from one-shot reads at the bootstrap / connection phase, not from steady-state polling.
Fields the XLSX exposes that we don't have a DID for
From the 2026-06-13/14 XLSX historical exports (2290432064100800D090A000A0000022_*.xlsx):
UDAN tag 0x92 Device info (11 cols):
releaseName = A650_C121.074.001.01_T1.0.2 (firmware identifier)
SCID = 40-char hex (SHA-1?)
Custom info. ver., FW zone
Up time, Current mode
Charging cycles (= 0, broken/unused on this BMS — actual cycle count is elsewhere)
FWID, BurnID (manufacturer codes)
PackSN (unpopulated on this pack but the column exists)
UDAN tag 0x82 Device list (7 cols):
VIN (placeholder 1234567890ABCDEF on this tractor)
Hardware Device count, per-device HWID + FWVersion
- Device 1 HWID =
2290432064100800D090A000A0000022 (matches export filename — global BMS identifier)
System state 0x93 fields we don't surface (subset; many are from currently-polled DIDs but others aren't):
DI1 / DI2 (discrete inputs — could anchor key / seat / brake state)
SW1 / SW2 (switch inputs)
Relay 0 / Relay 1 (Close / Open vendor-labeled relay states) + Relay count
HALL Power Supply Voltage (mV) (= 0 on this pack, but useful as a sanity-check anchor)
HALL Channel 1/2 Calibration Current (A)
Reset source (= Powered On always in this export)
Slave communication interruption status
Proposed approach
- Record an iBMS bootstrap-only capture — start a CAN trace on the diagnostic bus, then connect iBMS PC Utility, let it complete the connect/identity phase, then disconnect. Should be ~10–30 s.
- Extract all UDS
22 XX YY requests the iBMS sends during bootstrap (separate from the steady-state poll set we already mirror). Diff against our ALL_POLLS.
- Map each bootstrap DID to the field it populates by looking at the iBMS UI tab that displays the value (System overview / Device info / etc.).
- Add a
--bootstrap-only mode to util/capture_dual_can.py (or extend bms/solectrac-bms-diagnostics.py:read_identity) to read those DIDs once at startup and surface the values.
Not blocking on this
The DIDs we already poll cover all the high-value live state (pack V/A/SOC, alarms, charging telemetry, peak data, balancing). The fields above are nice-to-have inventory / identity / discrete-IO additions, not critical for live monitoring. Worth picking up next time the iBMS is being connected to the tractor anyway — opportunistic capture.
See bms/README.md §"Polling patterns" for the current 33-DID inventory and bms/solectrac-bms-diagnostics.py ALL_POLLS for the code list.
The iBMS PC Utility's periodic poll set is exactly 33 DIDs and our
util/capture_dual_can.py/bms/solectrac-bms-diagnostics.pyalready match it 1:1 (audited againstdual-capture-charging-120-10p-to-100p.asc). However, the History → XLSX export surfaces fields that aren't reachable from any DID we currently poll — they must come from one-shot reads at the bootstrap / connection phase, not from steady-state polling.Fields the XLSX exposes that we don't have a DID for
From the 2026-06-13/14 XLSX historical exports (
2290432064100800D090A000A0000022_*.xlsx):UDAN tag
0x92 Device info(11 cols):releaseName=A650_C121.074.001.01_T1.0.2(firmware identifier)SCID= 40-char hex (SHA-1?)Custom info. ver.,FW zoneUp time,Current modeCharging cycles(= 0, broken/unused on this BMS — actual cycle count is elsewhere)FWID,BurnID(manufacturer codes)PackSN(unpopulated on this pack but the column exists)UDAN tag
0x82 Device list(7 cols):VIN(placeholder1234567890ABCDEFon this tractor)Hardware Device count, per-deviceHWID+FWVersion2290432064100800D090A000A0000022(matches export filename — global BMS identifier)System state 0x93fields we don't surface (subset; many are from currently-polled DIDs but others aren't):DI1/DI2(discrete inputs — could anchor key / seat / brake state)SW1/SW2(switch inputs)Relay 0/Relay 1(Close / Open vendor-labeled relay states) +Relay countHALL Power Supply Voltage (mV)(= 0 on this pack, but useful as a sanity-check anchor)HALL Channel 1/2 Calibration Current (A)Reset source(=Powered Onalways in this export)Slave communication interruption statusProposed approach
22 XX YYrequests the iBMS sends during bootstrap (separate from the steady-state poll set we already mirror). Diff against ourALL_POLLS.--bootstrap-onlymode toutil/capture_dual_can.py(or extendbms/solectrac-bms-diagnostics.py:read_identity) to read those DIDs once at startup and surface the values.Not blocking on this
The DIDs we already poll cover all the high-value live state (pack V/A/SOC, alarms, charging telemetry, peak data, balancing). The fields above are nice-to-have inventory / identity / discrete-IO additions, not critical for live monitoring. Worth picking up next time the iBMS is being connected to the tractor anyway — opportunistic capture.
See
bms/README.md§"Polling patterns" for the current 33-DID inventory andbms/solectrac-bms-diagnostics.pyALL_POLLSfor the code list.