You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(nodes): estimated advert intervals (flood / zero-hop) per node, then mesh-wide settings analytics #245
Show each node's estimated advert intervals (flood and zero-hop) on the node detail page. Later, analyse the distribution across the mesh, i.e. which settings nodes run with.
Motivation: a repeater operator could see from CoreScope that a node sends flood adverts about every 47 h and no zero-hop adverts (the zero-hop interval was set to 0). After changing the setting, the effect should be visible on the node page.
Firmware sends flood adverts on one interval (hours) and zero-hop ("local") adverts on another (minutes), and either can be off. The exact setting names, units, allowed ranges and defaults must be taken from the MeshCore firmware source (src/, docs/cli_commands.md), not guessed (AGENTS.md).
A zero-hop advert is only recorded if an observer hears it directly, so "no zero-hop adverts observed" can also mean "no observer in direct range". The UI must word it that way.
M1: estimate per node, shown in node detail
Estimator (pure, unit-tested):
Work per route class (flood, zero-hop) over the node's distinct adverts (deduplicated by content hash) inside retention.
Prefer the advert's own sender timestamp. Fall back to first-seen when the sender clock is clearly wrong (in the future, or not monotonic).
Be robust:
use the median of the gaps;
treat gaps that are about an integer multiple of the interval as missed adverts;
drop gaps far shorter than the interval (manual adverts, reboots);
require a minimum number of samples.
Snap the result to the nearest value the firmware allows, if the firmware has discrete steps.
Output per class: interval_s, samples, confidence (high / medium / low / none), and last_advert.
API:
A new field advertIntervals on GET /api/nodes/{pubkey}, ideally under the existing include=advertRoutes opt-in so other callers do not pay for it.
Use a named Go struct, with no new map[string]interface{}.
Document it in openapi.go and docs/api-spec.md.
UI:
In the node detail advert section, e.g. "Estimated flood interval ≈ 47 h (14 adverts, high confidence)".
When no zero-hop adverts were observed, show "Zero-hop: none observed (off, or no observer in direct range)".
No hardcoded colours, and all text escaped.
Perf: O(adverts of this node) per request, with no store-wide scan in the request path.
M2 (later, separate PR): analytics across nodes
An analytics view showing:
the distribution of flood and zero-hop intervals by role and region;
how many nodes have zero-hop off or not observed;
outliers, i.e. very frequent adverts.
It is computed once per analytics cache cycle, not per request. It is only started after M1 has run on staging for a while.
Later (rule 8)
Expose the confidence thresholds and the minimum samples in the customizer.
Acceptance (M1)
Unit tests for the estimator:
a regular series;
missed adverts (2× and 3× gaps);
manual or extra adverts;
sender-clock jumps or a wrong clock;
too few samples;
zero-hop absent.
Snapping matches the firmware's allowed values, cited from the firmware source.
The node detail shows both classes, and an E2E checks the rendering against a seeded node with known advert gaps.
The API is documented. cmd/server stays read-only.
Goal
Show each node's estimated advert intervals (flood and zero-hop) on the node detail page. Later, analyse the distribution across the mesh, i.e. which settings nodes run with.
Motivation: a repeater operator could see from CoreScope that a node sends flood adverts about every 47 h and no zero-hop adverts (the zero-hop interval was set to 0). After changing the setting, the effect should be visible on the node page.
Background
include=advertRoutes:recentAdvertsByRoute,advertCounts, from [feat] node detail, separate flood-adv from zero-hop adv Kpa-clawbot/CoreScope#2073 /route_mask).src/,docs/cli_commands.md), not guessed (AGENTS.md).M1: estimate per node, shown in node detail
Estimator (pure, unit-tested):
interval_s,samples,confidence(high/medium/low/none), andlast_advert.API:
advertIntervalsonGET /api/nodes/{pubkey}, ideally under the existinginclude=advertRoutesopt-in so other callers do not pay for it.map[string]interface{}.openapi.goanddocs/api-spec.md.UI:
Perf: O(adverts of this node) per request, with no store-wide scan in the request path.
M2 (later, separate PR): analytics across nodes
An analytics view showing:
It is computed once per analytics cache cycle, not per request. It is only started after M1 has run on staging for a while.
Later (rule 8)
Expose the confidence thresholds and the minimum samples in the customizer.
Acceptance (M1)
cmd/serverstays read-only.