mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-04-26 15:27:20 +00:00
## Problem The "Top 20 Longest Hops" RF analytics card shows the same repeater pair filling most slots because the query sorts raw hop records by distance with no pair deduplication. A single long link observed 12+ times dominates the leaderboard. ## Fix Dedupe by unordered `(pk1, pk2)` pair. Per pair, keep the max-distance record and compute reliability metrics: | Column | Description | |--------|-------------| | **Obs** | Total observations of this link | | **Best SNR** | Maximum SNR seen (dB) | | **Median SNR** | Median SNR across all observations (dB) | Tooltip on each row shows the timestamp of the best observation. ### Before | # | From | To | Distance | Type | SNR | Packet | |---|------|----|----------|------|-----|--------| | 1 | NodeX | NodeY | 200 mi | R↔R | 5 dB | abc… | | 2 | NodeX | NodeY | 199 mi | R↔R | 6 dB | def… | | 3 | NodeX | NodeY | 198 mi | R↔R | 4 dB | ghi… | ### After | # | From | To | Distance | Type | Obs | Best SNR | Median SNR | Packet | |---|------|----|----------|------|-----|----------|------------|--------| | 1 | NodeX | NodeY | 200 mi | R↔R | 12 | 8.0 dB | 5.2 dB | abc… | | 2 | NodeA | NodeB | 150 mi | C↔R | 3 | 6.5 dB | 6.5 dB | jkl… | ## Changes - **`cmd/server/store.go`**: Group `filteredHops` by unordered pair key, accumulate obs count / best SNR / median SNR per group, sort by max distance, take top 20 - **`cmd/server/types.go`**: Update `DistanceHop` struct — replace `SNR` with `BestSnr`, `MedianSnr`, add `ObsCount` - **`public/analytics.js`**: Replace single SNR column with Obs, Best SNR, Median SNR; add row tooltip with best observation timestamp - **`cmd/server/store_tophops_test.go`**: 3 unit tests — basic dedupe, reverse-pair merge, nil SNR edge case ## Test Coverage - `TestDedupeTopHopsByPair`: 5 records on pair (A,B) + 1 on (C,D) → 2 results, correct obsCount/dist/bestSnr/medianSnr - `TestDedupeTopHopsReversePairMerges`: (B,A) and (A,B) merge into one entry - `TestDedupeTopHopsNilSNR`: all-nil SNR records → bestSnr and medianSnr both nil - Existing `TestAnalyticsRFEndpoint` and `TestAnalyticsRFWithRegion` still pass Closes #847 --------- Co-authored-by: you <you@example.com>
1590 lines
33 KiB
JSON
1590 lines
33 KiB
JSON
{
|
|
"analytics_distance": {
|
|
"type": "object",
|
|
"keys": {
|
|
"summary": {
|
|
"type": "object",
|
|
"keys": {
|
|
"totalHops": {
|
|
"type": "number"
|
|
},
|
|
"totalPaths": {
|
|
"type": "number"
|
|
},
|
|
"avgDist": {
|
|
"type": "number"
|
|
},
|
|
"maxDist": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"topHops": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"fromName": {
|
|
"type": "string"
|
|
},
|
|
"fromPk": {
|
|
"type": "string"
|
|
},
|
|
"toName": {
|
|
"type": "string"
|
|
},
|
|
"toPk": {
|
|
"type": "string"
|
|
},
|
|
"dist": {
|
|
"type": "number"
|
|
},
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"hash": {
|
|
"type": "string"
|
|
},
|
|
"timestamp": {
|
|
"type": "string"
|
|
},
|
|
"bestSnr": {
|
|
"type": "number"
|
|
},
|
|
"medianSnr": {
|
|
"type": "number"
|
|
},
|
|
"obsCount": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"topPaths": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hash": {
|
|
"type": "string"
|
|
},
|
|
"totalDist": {
|
|
"type": "number"
|
|
},
|
|
"hopCount": {
|
|
"type": "number"
|
|
},
|
|
"timestamp": {
|
|
"type": "string"
|
|
},
|
|
"hops": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"catStats": {
|
|
"type": "object",
|
|
"dynamicKeys": true,
|
|
"valueShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"count": {
|
|
"type": "number"
|
|
},
|
|
"avg": {
|
|
"type": "number"
|
|
},
|
|
"median": {
|
|
"type": "number"
|
|
},
|
|
"min": {
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"distHistogram": {
|
|
"type": "object",
|
|
"keys": {
|
|
"bins": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"x": {
|
|
"type": "number"
|
|
},
|
|
"w": {
|
|
"type": "number"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"min": {
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"distOverTime": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hour": {
|
|
"type": "string"
|
|
},
|
|
"avg": {
|
|
"type": "number"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"analytics_hash_sizes": {
|
|
"type": "object",
|
|
"keys": {
|
|
"total": {
|
|
"type": "number"
|
|
},
|
|
"distribution": {
|
|
"type": "object",
|
|
"dynamicKeys": true,
|
|
"valueShape": {
|
|
"type": "number"
|
|
}
|
|
},
|
|
"hourly": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hour": {
|
|
"type": "string"
|
|
},
|
|
"1": {
|
|
"type": "number"
|
|
},
|
|
"2": {
|
|
"type": "number"
|
|
},
|
|
"3": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"topHops": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hex": {
|
|
"type": "string"
|
|
},
|
|
"size": {
|
|
"type": "number"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
},
|
|
"name": {
|
|
"type": "nullable"
|
|
},
|
|
"pubkey": {
|
|
"type": "nullable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"multiByteNodes": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"hashSize": {
|
|
"type": "number"
|
|
},
|
|
"packets": {
|
|
"type": "number"
|
|
},
|
|
"lastSeen": {
|
|
"type": "string"
|
|
},
|
|
"pubkey": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"analytics_rf": {
|
|
"type": "object",
|
|
"keys": {
|
|
"totalPackets": {
|
|
"type": "number"
|
|
},
|
|
"totalAllPackets": {
|
|
"type": "number"
|
|
},
|
|
"totalTransmissions": {
|
|
"type": "number"
|
|
},
|
|
"snr": {
|
|
"type": "object",
|
|
"keys": {
|
|
"min": {
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"type": "number"
|
|
},
|
|
"avg": {
|
|
"type": "number"
|
|
},
|
|
"median": {
|
|
"type": "number"
|
|
},
|
|
"stddev": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"rssi": {
|
|
"type": "object",
|
|
"keys": {
|
|
"min": {
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"type": "number"
|
|
},
|
|
"avg": {
|
|
"type": "number"
|
|
},
|
|
"median": {
|
|
"type": "number"
|
|
},
|
|
"stddev": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"snrValues": {
|
|
"type": "object",
|
|
"keys": {
|
|
"bins": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"x": {
|
|
"type": "number"
|
|
},
|
|
"w": {
|
|
"type": "number"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"min": {
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"rssiValues": {
|
|
"type": "object",
|
|
"keys": {
|
|
"bins": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"x": {
|
|
"type": "number"
|
|
},
|
|
"w": {
|
|
"type": "number"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"min": {
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"packetSizes": {
|
|
"type": "object",
|
|
"keys": {
|
|
"bins": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"x": {
|
|
"type": "number"
|
|
},
|
|
"w": {
|
|
"type": "number"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"min": {
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"minPacketSize": {
|
|
"type": "number"
|
|
},
|
|
"maxPacketSize": {
|
|
"type": "number"
|
|
},
|
|
"avgPacketSize": {
|
|
"type": "number"
|
|
},
|
|
"packetsPerHour": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hour": {
|
|
"type": "string"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"payloadTypes": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"type": {
|
|
"type": "nullable_number"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"snrByType": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
},
|
|
"avg": {
|
|
"type": "number"
|
|
},
|
|
"min": {
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"signalOverTime": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hour": {
|
|
"type": "string"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
},
|
|
"avgSnr": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"scatterData": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"snr": {
|
|
"type": "number"
|
|
},
|
|
"rssi": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"timeSpanHours": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"analytics_subpaths": {
|
|
"type": "object",
|
|
"keys": {
|
|
"subpaths": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"path": {
|
|
"type": "string"
|
|
},
|
|
"rawHops": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
},
|
|
"hops": {
|
|
"type": "number"
|
|
},
|
|
"pct": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"totalPaths": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"analytics_topology": {
|
|
"type": "object",
|
|
"keys": {
|
|
"uniqueNodes": {
|
|
"type": "number"
|
|
},
|
|
"avgHops": {
|
|
"type": "number"
|
|
},
|
|
"medianHops": {
|
|
"type": "number"
|
|
},
|
|
"maxHops": {
|
|
"type": "number"
|
|
},
|
|
"hopDistribution": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hops": {
|
|
"type": "number"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"topRepeaters": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hop": {
|
|
"type": "string"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
},
|
|
"name": {
|
|
"type": "nullable"
|
|
},
|
|
"pubkey": {
|
|
"type": "nullable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"topPairs": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hopA": {
|
|
"type": "string"
|
|
},
|
|
"hopB": {
|
|
"type": "string"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
},
|
|
"nameA": {
|
|
"type": "nullable"
|
|
},
|
|
"nameB": {
|
|
"type": "nullable"
|
|
},
|
|
"pubkeyA": {
|
|
"type": "nullable"
|
|
},
|
|
"pubkeyB": {
|
|
"type": "nullable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"hopsVsSnr": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hops": {
|
|
"type": "number"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
},
|
|
"avgSnr": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"observers": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"id": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"perObserverReach": {
|
|
"type": "object",
|
|
"dynamicKeys": true,
|
|
"valueShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"observer_name": {
|
|
"type": "string"
|
|
},
|
|
"rings": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"multiObsNodes": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hop": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "nullable"
|
|
},
|
|
"pubkey": {
|
|
"type": "nullable"
|
|
},
|
|
"observers": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"bestPathList": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hop": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "nullable"
|
|
},
|
|
"pubkey": {
|
|
"type": "nullable"
|
|
},
|
|
"minDist": {
|
|
"type": "number"
|
|
},
|
|
"observer_id": {
|
|
"type": "string"
|
|
},
|
|
"observer_name": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"bulk_health": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"public_key": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"role": {
|
|
"type": "string"
|
|
},
|
|
"lat": {
|
|
"type": "number"
|
|
},
|
|
"lon": {
|
|
"type": "number"
|
|
},
|
|
"stats": {
|
|
"type": "object",
|
|
"keys": {
|
|
"totalTransmissions": {
|
|
"type": "number"
|
|
},
|
|
"totalObservations": {
|
|
"type": "number"
|
|
},
|
|
"totalPackets": {
|
|
"type": "number"
|
|
},
|
|
"packetsToday": {
|
|
"type": "number"
|
|
},
|
|
"avgSnr": {
|
|
"type": "nullable"
|
|
},
|
|
"lastHeard": {
|
|
"type": "nullable"
|
|
}
|
|
}
|
|
},
|
|
"observers": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"observer_id": {
|
|
"type": "string"
|
|
},
|
|
"observer_name": {
|
|
"type": "string"
|
|
},
|
|
"avgSnr": {
|
|
"type": "nullable"
|
|
},
|
|
"avgRssi": {
|
|
"type": "nullable"
|
|
},
|
|
"packetCount": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"channel_messages": {
|
|
"type": "object",
|
|
"keys": {
|
|
"messages": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"sender": {
|
|
"type": "string"
|
|
},
|
|
"text": {
|
|
"type": "string"
|
|
},
|
|
"timestamp": {
|
|
"type": "string"
|
|
},
|
|
"sender_timestamp": {
|
|
"type": "number"
|
|
},
|
|
"packetId": {
|
|
"type": "number"
|
|
},
|
|
"packetHash": {
|
|
"type": "string"
|
|
},
|
|
"repeats": {
|
|
"type": "number"
|
|
},
|
|
"observers": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"hops": {
|
|
"type": "number"
|
|
},
|
|
"snr": {
|
|
"type": "nullable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"total": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"channels": {
|
|
"type": "object",
|
|
"keys": {
|
|
"channels": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hash": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"lastMessage": {
|
|
"type": "string"
|
|
},
|
|
"lastSender": {
|
|
"type": "string"
|
|
},
|
|
"messageCount": {
|
|
"type": "number"
|
|
},
|
|
"lastActivity": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"health": {
|
|
"type": "object",
|
|
"keys": {
|
|
"status": {
|
|
"type": "string"
|
|
},
|
|
"uptime": {
|
|
"type": "number"
|
|
},
|
|
"uptimeHuman": {
|
|
"type": "string"
|
|
},
|
|
"memory": {
|
|
"type": "object",
|
|
"keys": {
|
|
"rss": {
|
|
"type": "number"
|
|
},
|
|
"heapUsed": {
|
|
"type": "number"
|
|
},
|
|
"heapTotal": {
|
|
"type": "number"
|
|
},
|
|
"external": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"eventLoop": {
|
|
"type": "object",
|
|
"keys": {
|
|
"currentLagMs": {
|
|
"type": "number"
|
|
},
|
|
"maxLagMs": {
|
|
"type": "number"
|
|
},
|
|
"p50Ms": {
|
|
"type": "number"
|
|
},
|
|
"p95Ms": {
|
|
"type": "number"
|
|
},
|
|
"p99Ms": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"cache": {
|
|
"type": "object",
|
|
"keys": {
|
|
"entries": {
|
|
"type": "number"
|
|
},
|
|
"hits": {
|
|
"type": "number"
|
|
},
|
|
"misses": {
|
|
"type": "number"
|
|
},
|
|
"staleHits": {
|
|
"type": "number"
|
|
},
|
|
"recomputes": {
|
|
"type": "number"
|
|
},
|
|
"hitRate": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"websocket": {
|
|
"type": "object",
|
|
"keys": {
|
|
"clients": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"packetStore": {
|
|
"type": "object",
|
|
"keys": {
|
|
"packets": {
|
|
"type": "number"
|
|
},
|
|
"estimatedMB": {
|
|
"type": "number"
|
|
},
|
|
"trackedMB": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"perf": {
|
|
"type": "object",
|
|
"keys": {
|
|
"totalRequests": {
|
|
"type": "number"
|
|
},
|
|
"avgMs": {
|
|
"type": "number"
|
|
},
|
|
"slowQueries": {
|
|
"type": "number"
|
|
},
|
|
"recentSlow": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"path": {
|
|
"type": "string"
|
|
},
|
|
"ms": {
|
|
"type": "number"
|
|
},
|
|
"time": {
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"node_detail": {
|
|
"type": "object",
|
|
"keys": {
|
|
"node": {
|
|
"type": "object",
|
|
"keys": {
|
|
"public_key": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"role": {
|
|
"type": "string"
|
|
},
|
|
"lat": {
|
|
"type": "number"
|
|
},
|
|
"lon": {
|
|
"type": "number"
|
|
},
|
|
"last_seen": {
|
|
"type": "string"
|
|
},
|
|
"first_seen": {
|
|
"type": "string"
|
|
},
|
|
"advert_count": {
|
|
"type": "number"
|
|
},
|
|
"hash_size": {
|
|
"type": "number"
|
|
},
|
|
"hash_size_inconsistent": {
|
|
"type": "boolean"
|
|
},
|
|
"hash_sizes_seen": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "number"
|
|
}
|
|
},
|
|
"battery_mv": {
|
|
"type": "nullable_number"
|
|
},
|
|
"temperature_c": {
|
|
"type": "nullable_number"
|
|
}
|
|
}
|
|
},
|
|
"recentAdverts": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"id": {
|
|
"type": "number"
|
|
},
|
|
"raw_hex": {
|
|
"type": "string"
|
|
},
|
|
"hash": {
|
|
"type": "string"
|
|
},
|
|
"first_seen": {
|
|
"type": "string"
|
|
},
|
|
"timestamp": {
|
|
"type": "string"
|
|
},
|
|
"route_type": {
|
|
"type": "number"
|
|
},
|
|
"payload_type": {
|
|
"type": "number"
|
|
},
|
|
"decoded_json": {
|
|
"type": "string"
|
|
},
|
|
"observations": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object"
|
|
}
|
|
},
|
|
"observation_count": {
|
|
"type": "number"
|
|
},
|
|
"observer_id": {
|
|
"type": "string"
|
|
},
|
|
"observer_name": {
|
|
"type": "string"
|
|
},
|
|
"snr": {
|
|
"type": "nullable"
|
|
},
|
|
"rssi": {
|
|
"type": "nullable"
|
|
},
|
|
"path_json": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"nodes": {
|
|
"type": "object",
|
|
"keys": {
|
|
"nodes": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"public_key": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"role": {
|
|
"type": "string"
|
|
},
|
|
"lat": {
|
|
"type": "number"
|
|
},
|
|
"lon": {
|
|
"type": "number"
|
|
},
|
|
"last_seen": {
|
|
"type": "string"
|
|
},
|
|
"first_seen": {
|
|
"type": "string"
|
|
},
|
|
"advert_count": {
|
|
"type": "number"
|
|
},
|
|
"hash_size": {
|
|
"type": "number"
|
|
},
|
|
"hash_size_inconsistent": {
|
|
"type": "boolean"
|
|
},
|
|
"last_heard": {
|
|
"type": "string"
|
|
},
|
|
"battery_mv": {
|
|
"type": "nullable_number"
|
|
},
|
|
"temperature_c": {
|
|
"type": "nullable_number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"total": {
|
|
"type": "number"
|
|
},
|
|
"counts": {
|
|
"type": "object",
|
|
"keys": {
|
|
"repeaters": {
|
|
"type": "number"
|
|
},
|
|
"rooms": {
|
|
"type": "number"
|
|
},
|
|
"companions": {
|
|
"type": "number"
|
|
},
|
|
"sensors": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"observers": {
|
|
"type": "object",
|
|
"keys": {
|
|
"observers": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"id": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"iata": {
|
|
"type": "string"
|
|
},
|
|
"last_seen": {
|
|
"type": "string"
|
|
},
|
|
"first_seen": {
|
|
"type": "string"
|
|
},
|
|
"packet_count": {
|
|
"type": "number"
|
|
},
|
|
"model": {
|
|
"type": "nullable"
|
|
},
|
|
"firmware": {
|
|
"type": "nullable"
|
|
},
|
|
"client_version": {
|
|
"type": "nullable"
|
|
},
|
|
"radio": {
|
|
"type": "nullable"
|
|
},
|
|
"battery_mv": {
|
|
"type": "nullable"
|
|
},
|
|
"uptime_secs": {
|
|
"type": "nullable"
|
|
},
|
|
"noise_floor": {
|
|
"type": "nullable"
|
|
},
|
|
"packetsLastHour": {
|
|
"type": "number"
|
|
},
|
|
"lat": {
|
|
"type": "nullable"
|
|
},
|
|
"lon": {
|
|
"type": "nullable"
|
|
},
|
|
"nodeRole": {
|
|
"type": "nullable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"server_time": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"packets": {
|
|
"type": "object",
|
|
"keys": {
|
|
"packets": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"id": {
|
|
"type": "number"
|
|
},
|
|
"raw_hex": {
|
|
"type": "string"
|
|
},
|
|
"hash": {
|
|
"type": "string"
|
|
},
|
|
"first_seen": {
|
|
"type": "string"
|
|
},
|
|
"timestamp": {
|
|
"type": "string"
|
|
},
|
|
"route_type": {
|
|
"type": "number"
|
|
},
|
|
"payload_type": {
|
|
"type": "number"
|
|
},
|
|
"decoded_json": {
|
|
"type": "string"
|
|
},
|
|
"observation_count": {
|
|
"type": "number"
|
|
},
|
|
"observer_id": {
|
|
"type": "string"
|
|
},
|
|
"observer_name": {
|
|
"type": "string"
|
|
},
|
|
"snr": {
|
|
"type": "nullable"
|
|
},
|
|
"rssi": {
|
|
"type": "nullable"
|
|
},
|
|
"path_json": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"total": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"packets_grouped": {
|
|
"type": "object",
|
|
"keys": {
|
|
"packets": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"hash": {
|
|
"type": "string"
|
|
},
|
|
"first_seen": {
|
|
"type": "string"
|
|
},
|
|
"count": {
|
|
"type": "number"
|
|
},
|
|
"observer_count": {
|
|
"type": "number"
|
|
},
|
|
"latest": {
|
|
"type": "string"
|
|
},
|
|
"observer_id": {
|
|
"type": "string"
|
|
},
|
|
"observer_name": {
|
|
"type": "string"
|
|
},
|
|
"path_json": {
|
|
"type": "string"
|
|
},
|
|
"payload_type": {
|
|
"type": "number"
|
|
},
|
|
"route_type": {
|
|
"type": "number"
|
|
},
|
|
"raw_hex": {
|
|
"type": "string"
|
|
},
|
|
"decoded_json": {
|
|
"type": "string"
|
|
},
|
|
"observation_count": {
|
|
"type": "number"
|
|
},
|
|
"snr": {
|
|
"type": "nullable"
|
|
},
|
|
"rssi": {
|
|
"type": "nullable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"total": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"perf": {
|
|
"type": "object",
|
|
"keys": {
|
|
"uptime": {
|
|
"type": "number"
|
|
},
|
|
"totalRequests": {
|
|
"type": "number"
|
|
},
|
|
"avgMs": {
|
|
"type": "number"
|
|
},
|
|
"endpoints": {
|
|
"type": "object",
|
|
"dynamicKeys": true,
|
|
"valueShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"count": {
|
|
"type": "number"
|
|
},
|
|
"avgMs": {
|
|
"type": "number"
|
|
},
|
|
"p50Ms": {
|
|
"type": "number"
|
|
},
|
|
"p95Ms": {
|
|
"type": "number"
|
|
},
|
|
"maxMs": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"slowQueries": {
|
|
"type": "array",
|
|
"elementShape": {
|
|
"type": "object",
|
|
"keys": {
|
|
"path": {
|
|
"type": "string"
|
|
},
|
|
"ms": {
|
|
"type": "number"
|
|
},
|
|
"time": {
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"cache": {
|
|
"type": "object",
|
|
"keys": {
|
|
"size": {
|
|
"type": "number"
|
|
},
|
|
"hits": {
|
|
"type": "number"
|
|
},
|
|
"misses": {
|
|
"type": "number"
|
|
},
|
|
"staleHits": {
|
|
"type": "number"
|
|
},
|
|
"recomputes": {
|
|
"type": "number"
|
|
},
|
|
"hitRate": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"packetStore": {
|
|
"type": "object",
|
|
"keys": {
|
|
"totalLoaded": {
|
|
"type": "number"
|
|
},
|
|
"totalObservations": {
|
|
"type": "number"
|
|
},
|
|
"evicted": {
|
|
"type": "number"
|
|
},
|
|
"inserts": {
|
|
"type": "number"
|
|
},
|
|
"queries": {
|
|
"type": "number"
|
|
},
|
|
"inMemory": {
|
|
"type": "number"
|
|
},
|
|
"sqliteOnly": {
|
|
"type": "boolean"
|
|
},
|
|
"maxPackets": {
|
|
"type": "number"
|
|
},
|
|
"estimatedMB": {
|
|
"type": "number"
|
|
},
|
|
"maxMB": {
|
|
"type": "number"
|
|
},
|
|
"indexes": {
|
|
"type": "object",
|
|
"keys": {
|
|
"byHash": {
|
|
"type": "number"
|
|
},
|
|
"byObserver": {
|
|
"type": "number"
|
|
},
|
|
"byNode": {
|
|
"type": "number"
|
|
},
|
|
"advertByObserver": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"sqlite": {
|
|
"type": "object",
|
|
"keys": {
|
|
"dbSizeMB": {
|
|
"type": "number"
|
|
},
|
|
"walSizeMB": {
|
|
"type": "number"
|
|
},
|
|
"freelistMB": {
|
|
"type": "number"
|
|
},
|
|
"walPages": {
|
|
"type": "object",
|
|
"keys": {
|
|
"total": {
|
|
"type": "number"
|
|
},
|
|
"checkpointed": {
|
|
"type": "number"
|
|
},
|
|
"busy": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"rows": {
|
|
"type": "object",
|
|
"keys": {
|
|
"transmissions": {
|
|
"type": "number"
|
|
},
|
|
"observations": {
|
|
"type": "number"
|
|
},
|
|
"nodes": {
|
|
"type": "number"
|
|
},
|
|
"observers": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"goRuntime": {
|
|
"type": "object",
|
|
"keys": {
|
|
"goroutines": {
|
|
"type": "number"
|
|
},
|
|
"numGC": {
|
|
"type": "number"
|
|
},
|
|
"pauseTotalMs": {
|
|
"type": "number"
|
|
},
|
|
"lastPauseMs": {
|
|
"type": "number"
|
|
},
|
|
"heapAllocMB": {
|
|
"type": "number"
|
|
},
|
|
"heapSysMB": {
|
|
"type": "number"
|
|
},
|
|
"heapInuseMB": {
|
|
"type": "number"
|
|
},
|
|
"heapIdleMB": {
|
|
"type": "number"
|
|
},
|
|
"numCPU": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"stats": {
|
|
"type": "object",
|
|
"keys": {
|
|
"totalPackets": {
|
|
"type": "number"
|
|
},
|
|
"totalTransmissions": {
|
|
"type": "number"
|
|
},
|
|
"totalObservations": {
|
|
"type": "number"
|
|
},
|
|
"totalNodes": {
|
|
"type": "number"
|
|
},
|
|
"totalNodesAllTime": {
|
|
"type": "number"
|
|
},
|
|
"totalObservers": {
|
|
"type": "number"
|
|
},
|
|
"packetsLastHour": {
|
|
"type": "number"
|
|
},
|
|
"packetsLast24h": {
|
|
"type": "number"
|
|
},
|
|
"counts": {
|
|
"type": "object",
|
|
"keys": {
|
|
"repeaters": {
|
|
"type": "number"
|
|
},
|
|
"rooms": {
|
|
"type": "number"
|
|
},
|
|
"companions": {
|
|
"type": "number"
|
|
},
|
|
"sensors": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|