Repository navigation
Record each node's radio counters in every experiment cell - #746
Conversation
A chip that applies the firmware's IrqMask counts the events it had to raise and was not allowed to. A native node can append that count to its radio stats record as bytes 43-46; the bridge reads it when the record is at least 47 bytes long. node.stats answers it as irq_suppressed, and the Python client's NodeStat carries it. A record shorter than 47 bytes comes from a chip that does not count, and irq_suppressed is then absent (None in the Python client) rather than zero.
Each cell's result gains `chip`: the radio counters every running node reported at the end of the cell (IRQ register reads, reads that found a detection flag set, milliseconds with a detection flag set, injected spurious detections, and events the IrqMask suppressed), summed across the cell and kept per node with the node's IRQ mask, spreading factor and bandwidth. They are read before the engine closes, from the last record each node's bridge received. The suppressed total counts only nodes whose chip reports it; `suppressed_reporting` says how many did, so a total of zero is not read as a count of zero from chips that do not keep one. The experiment.export description names the field, and the generated verb reference is regenerated from it.
|
got some time, so hijacking to get things moving |
|
I've pushed two commits to the branch to get CI green, merging main and regenerating docs/verbs.json... I am going to make the following change quickly: The chip counters will be measured from the cell's baseline rather than from boot. runArm marks baseline and calls eng.ResetSensitivity() after the adverts and the 6 s settle, so the cell's delivery totals don't count the boot chatter. chipStats reads the bridge's totals from boot, so irq_reads, busy_reads, busy_ms, spurious and irq_suppressed currently include the boot and advert phase, and tx, rx and delivered don't. I'll snapshot each node's stats at baseline and report the end value minus the snapshot. irq_mask, sf and bandwidth_hz stay as end-of-cell readings, since they're state rather than counts. I'll add a test that counts from before the baseline don't reach the cell. This may change the comparison in the description. Identical delivery totals alongside a different busy_ms could have come partly from the boot phase, so it's worth rerunning the 1.16 vs 1.17 seeds once this lands. Separately, AngusOutlaw1 reporting bandwidth_hz 10420 is the SX126x's 10.4 kHz setting, a valid value rather than a decode error. It appears in one seed but in every arm with that seed, so I'll open an issue for it rather than hold this PR. |
The cell's delivery totals and margin counters start after the adverts have settled; the chip counters ran from boot, so they carried the mesh coming up while the totals beside them did not. Each node's radio record is now read at the same baseline and the counters reported as the difference. The mask and modem settings stay as the chip held them at the end, and a counter that went backwards is a node that restarted, so it is taken whole rather than wrapped.
Builds on #745: this branch contains #745's commit, and the change here is the last commit (
experiment: every cell records what each node's chip saw). It merges after #745.What this changes, and why
Each cell in an experiment gains
chip(ChipStatsininternal/app/session/experiment/chipstats.go):irq_reads,busy_reads,busy_ms,spurious, andirq_suppressedwithsuppressed_reporting(how many nodes reported a suppressed count);nodes): name, kind, the same counters, whether the suppressed count was reported,irq_mask,sfandbandwidth_hz.The counters are read in
runArmbefore the engine closes, from the last radio stats record each node's bridge received. They reachexperiment.export.experiment.resultsis unchanged.experiment.export's description names the field, anddocs/verb-reference.mdis regenerated from it.Without these, an experiment row carries delivery totals only, so two arms whose firmware read different radio state but transmitted identically produce identical rows.
Manual: MeshBench/docs#40.
Verification
gofmt -l internal/: empty.go vet ./internal/app/session/experiment/: clean.go test ./internal/app/session/experiment/ ./internal/: pass.golangci-lintv2.12.2 oninternal/app/session/experiment: no findings in changed files.tools/verbdoc/verbdoc.py --check: current after regeneration.chipstats_test.go: sums and per-node rows; a node without a suppressed count is neither added to the total nor counted as reporting; the export row carrieschip.scotland-strict, five seeds): every cell'schiplisted 159 nodes.irq_maskread0x0272for 1.16 and0x0276for 1.17;sf8 andbandwidth_hz62500 throughout, except one node in one seed (see below);spurious0. The delivery totals of the 1.16 and 1.17 arms were identical per seed, whilebusy_msandirq_suppresseddiffered between them.AngusOutlaw1reportedbandwidth_hz10420 at the end of the cell, in every arm. It is recorded here as observed.Checklist
CLAUDE.mdin this commit. (No new package.)cell.gois 490 lines; the collection is in its own file.)auditTargets; a new state is reachable by flag. (No panel.)docs/shortcomings.mdstill tells the truth after this change.security-audit/.