Alles über die Mesh-Teilnehmer: Listen, Suche, Health, Pfade, Analytics, Batterie, Nachbarn
und Uhren-Drift. Per-Node-Endpoints antworten für blacklisted oder versteckte Nodes mit 404 –
Anfragende erfahren nicht, ob die Row existiert.
Die paginierte Node-Liste. Repeater- und Room-Rows tragen zusätzlich die
Usefulness-Metriken (Issue #672): die vier Achsen traffic_share_score,
bridge_score, coverage_score, redundancy_score (je 0–1),
den Komposit-Score usefulness_score mit Note usefulness_grade (A–F)
sowie Relay-Aktivität: relay_active, relay_count_1h,
relay_count_24h, unscoped_relay_count_24h und last_relayed.
Ein hoher unscoped_relay_count_24h deutet auf ein Basis-Konfigurationsproblem des
Repeaters hin (flood.max.unscoped nicht 0).
| Param | Default | Beschreibung |
limit / offset | 50 / 0 | Pagination |
role | – | repeater, room, companion, sensor |
region / area | – | Geo-Filter |
lastHeard | – | Recency: 1h, 6h, 24h, 7d, 30d |
sortBy | lastSeen | name, lastSeen, packetCount |
search | – | Substring-Match auf den Namen |
before | – | nur Nodes mit first_seen ≤ before |
Antwort: {nodes[], total, counts{repeaters, rooms, companions, sensors}}
– counts ist global, nicht vom Filter beeinflusst. Node-Rows enthalten außerdem
hash_size/hash_size_inconsistent/hash_sizes_seen und
default_scope.
Schnelle Suche für Autocomplete: Name-Substring oder Pubkey-Prefix.
| Param | Beschreibung |
q | Suchbegriff, Pflicht; leer → {nodes:[]} |
Antwort: {nodes:[{public_key, name, role, lat, lon, last_seen, first_seen, advert_count}]}.
Löst einen gehörten Pfad-Prefix (oder ganzen Pubkey) zu Name und Pubkey auf, ohne die
ganze Node-Liste laden zu müssen.
| Param | Beschreibung |
prefix | Pflicht; Hex, mindestens 4 Zeichen (2-Zeichen-Prefixe sind bewusst gesperrt, um Enumeration zu erschweren) |
Antwort: {prefix, pubkey?, name?, ambiguous} – genau ein Treffer
füllt pubkey/name; mehrere Treffer → ambiguous:true;
blacklisted/hidden wird wie „nicht gefunden“ behandelt.
Fehler: 400 bei Nicht-Hex oder zu kurzem Prefix; 503 ohne DB.
Health-Zusammenfassung für viele Nodes in einem Call – fürs Analytics-Dashboard.
| Param | Default | Beschreibung |
limit | 50 | max. 200 |
region | – | IATA-Codes, kommasepariert |
Antwort: nacktes Array (nicht in {nodes:…} gewrappt) mit
{public_key, name, role, lat, lon, stats{…}, observers[]}.
Aggregierter Netz-Zustand: Wie viele Nodes sind frisch, angeschlagen oder still?
Die Grenzen kommen aus den konfigurierten Health-Schwellen (degraded/silent).
Antwort: {total, active, degraded, silent, roleCounts{}};
Filter region wird unterstützt.
Detailseite eines Nodes: die volle Node-Row (inkl. Usefulness-Achsen und
relay_window_hours bei Repeatern/Rooms) plus die letzten 20 Transmissions als
recentAdverts.
Antwort: {node, recentAdverts[]}.
Fehler: 404 bei unbekanntem, blacklisted oder verstecktem Node.
Health-Detail eines Nodes: Welche Observer hören ihn (mit SNR/RSSI und Paketzahl je
Observer), Gesamt-Stats und die letzten 20 Pakete.
Antwort: {node, observers[], stats{totalTransmissions, totalObservations,
packetsToday, avgSnr, avgHops, lastHeard}, recentPackets[]}.
Alle beobachteten Pfade, in denen der Prefix dieses Nodes vorkommt – mit aufgelösten
Hops, Häufigkeit und Beispiel-Hash je Pfad-Signatur.
Antwort: {node, paths:[{hops[], count, lastSeen, sampleHash}],
totalPaths, totalTransmissions}.
Die Analytics-Seite eines Nodes über ein wählbares Fenster: Aktivitäts-Timeline
(Stunden-Buckets), SNR-Trend, Payload-Typ-Verteilung, Observer-Coverage, Hop-Verteilung,
Peer-Interaktionen, Uptime-Heatmap – plus berechnete Kennzahlen wie
availabilityPct, signalGrade (A–D) und relayPct.
| Param | Default | Beschreibung |
days | 7 | Lookback 1–365 |
Antwort: {node, timeRange, activityTimeline[], snrTrend[],
packetTypeBreakdown[], observerCoverage[], hopDistribution[], peerInteractions[],
uptimeHeatmap[], computedStats{}}.
Batteriespannungs-Zeitreihe eines Nodes plus Status-Ampel aus dem jüngsten Messwert
gegen die konfigurierten mV-Schwellen.
| Param | Default | Beschreibung |
days | 7 | gültig 1–365, sonst stiller Fallback auf 7 |
Antwort: {public_key, days, samples:[{timestamp, battery_mv}],
latest_mv, latest_ts, status, thresholds{low_mv, critical_mv}} –
status ist ok, low (< 3300 mV Default),
critical (< 3000 mV) oder unknown ohne Samples.
Fehler: 400 ohne Pubkey, 404 bei unbekanntem Node.
Die First-Hop-Nachbarn aus dem Affinity-Graph: je Nachbar Score (Sättigung × Recency ×
Observer-Diversität), Beobachtungszahlen nach Hash-Prefix-Modus, SNR, Distanz und die
beteiligten Observer. Mehrdeutige Kanten tragen Kandidaten-Listen.
| Param | Default | Beschreibung |
min_count | 1 | Mindest-Beobachtungen je Kante |
min_score | 0.0 | Mindest-Affinity-Score |
include_ambiguous | true | false blendet mehrdeutige Kanten aus |
Antwort: {node, neighbors:[{pubkey, prefix, name, role, count,
counts_by_mode, score, avg_snr, distance_km, observers[], ambiguous, unresolved, candidates[]}],
total_observations}, sortiert nach Score absteigend.
Fehler: 404 bei blacklisted/hidden Node. Der Graph wird lazy gebaut und mit TTL gecacht.
Der Zwei-Wege-Reichweiten-Report: Aus der Pfad-Adjazenz werden richtungsbehaftete
Link-Zähler berechnet (we_hear/they_hear); ein Link ist
bidirektional, wenn beide Richtungen belegt sind, und der bottleneck (die
schwächere Richtung) bewertet die Stabilität. Nodes werden nur über eindeutige
2–3-Byte-Prefixe identifiziert – reliable_tokens: [] heißt: Node ist in Pfaden
nicht zuverlässig identifizierbar, links bleibt leer.
| Param | Default | Beschreibung |
days | 7 | Lookback, geklemmt auf 1–30 |
Antwort: {node, window, reliable_tokens[], importance{neighbor_degree,
degree_rank, relay_observations, bidirectional_links, direct_observers},
direct_observers[], links[]}.
Cache/Limits: Antwort 5 min pro pubkey|days gecacht;
Pfad-Scan hart bei 200 000 Zeilen gekappt (dann repräsentative Stichprobe).
Fehler: 400 wenn pubkey keine 64 Hex-Zeichen ist, 404 bei unbekannt/blacklisted.
Uhren-Drift der ganzen Flotte, berechnet aus ADVERT-Zeitstempel-Paaren: je Node der
geschätzte Offset, die Drift-Rate und eine Severity-Einstufung.
| Param | Beschreibung |
area | optional; ohne area kommt die Antwort aus dem 30-s-Hintergrund-Snapshot, mit area wird live gerechnet |
Antwort: nacktes Array
[{pubkey, nodeName, nodeRole, skewMs, driftPerDaySec, severity, samples:null}] –
die Detail-Felder (samples, Evidence) sind in der Fleet-Ansicht bewusst weggelassen.
Volle Clock-Skew-Details eines einzelnen Nodes – inklusive der Sample-Serie für
Sparklines, Kalibrier-Zusammenfassung und Hash-Evidenz der letzten Auffälligkeiten.
Antwort: {pubkey, meanSkewSec, medianSkewSec, recentMedianSkewSec,
driftPerDaySec, severity, sampleCount, calibrated, samples[], goodFraction,
recentBadSamples[], recentHashEvidence, calibrationSummary}.
Fehler: 404, wenn (noch) keine Skew-Daten für den Node existieren.