Skip to content

Releases

diaggrok 2026.11.8.post1

Choose a tag to compare

@lukejenkins lukejenkins released this 08 Nov 23:50

diaggrok 2026.11.8.post1: a README-only post-release of v2026.11.8.

README only: the Installation section now says pip install diaggrok. The
v2026.11.8 README still said diaggrok was not on PyPI, and PyPI never lets a
published version's description change, so this post-release carries the fix.
The code is identical to v2026.11.8.

On PyPI: pip install diaggrok==2026.11.8.post1, the same code as this tag.

diaggrok 2026.11.8

Choose a tag to compare

@lukejenkins lukejenkins released this 08 Nov 23:50

diaggrok 2026.11.8, the first release on PyPI. The same notes are the v2026.11.8 section of CHANGELOG.md.

On PyPI: diaggrok 2026.11.8 is the same code as this tag. Its PyPI page shows the README this tag shipped, which still said diaggrok was not on PyPI; v2026.11.8.post1 fixes that.

First release published to PyPI (pip install diaggrok). 197 log codes: the
196 of v2026.10.31 plus one new parser, 0xB9A6. No parser was removed.
Three record shapes change in ways that can break code reading them (below);
every other shape change adds fields.

New log code

code name record type
0xB9A6 NR cell acquisition timeline (per-stage frame and USTMR stamps, RF config id, target cell's SSB and UL-centre NR-ARFCN) Diag0xB9A6

It is grounded on the firmware's own F3 text for both versions it decodes
(v0x01, v0x02). Its shared time-word decode ships as
parsers/_nr_acq_b9be_b9bf.py, which registers no parser of its own.

Breaking: removed, renamed or re-typed fields

record change
DplRecord (0x11EB and the other DPL codes) counter is removed. The old 24-bit "counter" is two fields: packet_seq and segment, plus last_segment (bool).
Diag0xB8DD slot is removed: it was mis-modelled. The bits it read are sfn_word_hi6.
Diag0x1476 num_gps_svs, num_glo_svs, num_bds_svs, total_gps_svs, total_glo_svs and total_bds_svs are int | None: None on the v21 form, which does not carry them, instead of a misread number.
Diag0xB825 cells is always a list (list[dict[str, Any]]), never None; each cell also carries its raw wire words.
Diag0x1886 svs items may also be the new Sdx55GalSv.

Decode changes in existing parsers

  • 0x1886 (GNSS Galileo measurement) decodes the SDX55 variable-length
    variant (Sdx55GalSv).
  • 0x197F decodes its 9,244 B capture form (Diag0x197FCapture).
  • 0xB180 decodes the v0x04 8 + N×32 form, picking the stride from the
    record size.
  • 0xB063 frames records whose RLC extension the strict layout rejected, and
    marks them framing_relaxed.
  • 0xB064 decodes subpacket 8 versions 5, 7 and 8.
  • 0x18AE and 0x4177 fix lossy reads: values that were truncated or skipped
    are now exposed (see Fields added).
  • 0x1476: the v24 / v26 SV-block tails and the v21 tail are kept raw.
    A cut MDM9600 record is rejected instead of half-decoded.
  • 0x506A: to_dict()'s tail_raw is JSON-safe.
  • Every record these parsers now drop logs a warning saying why.
  • codes: 0x4801 is LOG_WCDMA_RRC_ACQ_SUMMARY_INFORMATION (it is a WCDMA
    code). LOG_LTE_CELL_SEARCH_RESULTS remains as a deprecated alias.

Fields added

record added fields
Diag0x1476 sv_block_568_raw, sv_block_602_raw, sv_block_612_raw, sv_pad_566, sv_pad_600, v21_tail_raw
Diag0x18AE full_hdr_raw, full_trailer_raw, gts_raw_25, gts_raw_2_6, gts_raw_34, gts_raw_43, gts_raw_52_75, gts_raw_u32_48, timer_19m2
Diag0x4177 hdr_count, hdr_s16, hdr_u16_at23, hdr_u16_at34, hdr_u16_at8, hdr_var_raw, hdr_word
Diag0xB063 framing_relaxed
Diag0xB0CD tail_bytes
Diag0xB0EE guti_plmn_raw
Diag0xB823 tac, nr_band, rel_major, word_22
Diag0xB825 bands, blocks
Diag0xB8DD sfn_word_hi6
HdlcStats qsh_trace_sub_stream_frames

diaggrok 2026.10.31

Choose a tag to compare

@lukejenkins lukejenkins released this 01 Nov 16:08

diaggrok 2026.10.31. The same notes are the v2026.10.31 section of CHANGELOG.md.

196 log codes: the 191 of v2026.10.26 plus five new parsers, 0x1377,
0x1383, 0x13C4, 0x1756 and 0xB181. No parser was removed, and no
record field was removed, renamed or re-typed: every shape change below adds
fields. One module is new outside the parsers: ts64_cal.py (see below).

New log codes

code name record type
0x1377 CGPS report event log packet (GNSS session events) Diag0x1377
0x1383 CGPS PDSM extended-status position report (each final, intermediate or seed fix) Diag0x1383
0x13C4 CGPS measurement-engine time-estimate put (GPS week / ms clock, bias, uncertainty) Diag0x13C4
0x1756 GNSS BeiDou B1I measurement report (per-SV) Diag0x1756
0xB181 LTE ML1 intra-frequency cell reselection (serving EARFCN / PCI, per-frequency reselection lists) Diag0xB181

All five are grounded on the firmware's own F3 text for every version they
decode. 0xB181's subpackets must tile the record exactly; a record that does
not is rejected (None, with a warning), which no corpus record does.

ts64_cal — capture-clock calibration

diaggrok.ts64_cal now ships whenever 0x1476 does. It maps the DIAG ts64
counter to UTC from the capture's own 0x1476 GNSS fixes, fitting the tick rate
rather than assuming it, and applies the GPS-UTC leap-second offset. It is what
diagmunge-dlf-to-pcap uses for calibrated pcap timestamps; without it that
tool falls back to a synthetic clock.

Decode changes in existing parsers

  • 0xB18F (LTE ML1 AdvRx IC cell list) decodes v0x18 (512 B, MDM9240), which
    was previously rejected: the 34 B head of v0x20 with 28 B cell slots that
    carry no dl_bw_rb / num_rx_ant_candidate (both None on v0x18).
  • 0xB18B (LTE ML1 sleep) decodes the 64 B v0x01 form (MDM9625) as the 60 B
    form's 16-bit EARFCN + PCI; it previously fell back to an out-of-range 32-bit
    EARFCN. A record one byte short of 64 B is now rejected.
  • 0xB0C0 v0x1e: connected-mode channels 8..11 decode (the v26 / v27 layout).
  • 0xB193: the v48 / v59 family uses constant strides.
  • 0x1476: the GLONASS time triplet is decoded on the v13+ and MDM9600 paths too.
  • 0x1807: every f32 site keeps its raw u32 word, so an sNaN lane survives a
    rebuild of the record.
  • 0xB823: bytes [9:17] are a 60-bit NCGI: PLMN (ncgi_mcc, ncgi_mnc) and
    36-bit ncgi_nci, plus cell_global_id.

Fields added

record added fields
Diag0x1476 clock_block_raw, ellipse_sensor_raw, failure_code, fake_align, fix_events, hdr_gap_raw, pos_count, pos_vel_flag, pos_vel_flag2, post_dop_raw, reserved1; to_dict() key struct_raw
Diag0x14FD aux1_lat_raw, aux1_lon_raw, aux2_lat_raw, aux2_lon_raw, cell_lat_raw, cell_lon_raw, raw
Diag0x1526V01 aux_b8_27_raw
Diag0x1807 fmt_b30, gps_ms_of_week, gps_week, hb_trailer_word, hdr_tail_raw, medium_b27_raw, medium_body_words, medium_fmt_b31, medium_fmt_b32, medium_word_23
Diag0x1807FineCell / Diag0x1807MeasRow meas_a_word, meas_b_word / lane_words
Diag0x1874V0c flag_6, flag_11
Diag0x1C7Cv2Sub* (8 types) entries (dataclass); tags (to_dict())
Diag0xB0C0 aux_b3_raw, bearer_word_lo
Diag0xB17F aux_b1_raw, aux_word_raw, rsrp_avg_word, rsrp_word, rsrq_word, rssi_word, squal_word, srxlev_word
Diag0xB18F cells (v0x18) raw_10 in place of raw_14 (the 28 B slot's trailing bytes)
Diag0xB192 num_subpackets, request_earfcn, request_num_cells_flag, request_sp_version; LteMl1NeighborCellEntry.timing1; LteMl1NeighborRequestCell.pci_raw
Diag0xB193 body_raw, num_subpackets, subpacket_id, subpacket_size; LteMl1ServingCellMeasEntry.cell_index, .pci_word
Diag0xB195 counter, request_cells, request_header, request_sp_version, request_trailing, response_trailing; new LteMl1ConnectedNeighborRequestCell
Diag0xB821 reserved_raw, trailing_raw
Diag0xB823 cell_global_id, ncgi_mcc, ncgi_mnc, ncgi_nci
Diag0xB97F trailing_raw

Install: pip install "diaggrok @ git+https://github.com/lukejenkins/diaggrok@v2026.10.31"