Commit graph

16 commits

Author SHA1 Message Date
99c952b432 feat: Show hop count and GPS distance in node detail and single-gw listings
- Added hops_away to Connectivity section in node detail
- Added nearest infra distance after Position in node detail
- Added distance from reference infra to single-gw client listings
- Added _haversine_km and _format_distance helper functions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 21:16:55 +00:00
29a57b459a fix: 6 reporter bugs — missing methods, undefined var, indentation, key types
1. Added _find_node() — delegates to health_engine.get_node()
2. Added _find_region() — fuzzy match with config aliases
3. Fixed undefined unified var in _node_recommendations
4. Fixed env recommendation indentation (was inside MQTT uplink check)
5. Fixed 6 string-vs-int key mismatches on health.nodes lookups
6. Fixed estimated_position_interval — compute inline from packets_by_type

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 20:58:41 +00:00
cc474e3bb3 feat: Show source name for single-gateway nodes
Single-gateway nodes now display "via {source_name}" to indicate
which data source they depend on. This helps identify coverage gaps
and understand node visibility.

Adds source info to:
- Tier 1 region summary (infra and client nodes)
- Node distribution section (infrastructure nodes)
- Region detail view (single gateway list)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 20:23:18 +00:00
1d9c90911b feat: Feeder-level gateway awareness from /api/packets_seen
Samples recent packets and calls /api/packets_seen to discover which
physical MQTT gateways hear each node. Per-gateway RSSI and SNR.

UnifiedNode:
- feeder_gateways list with gateway_id, gateway_name, avg_rssi, avg_snr
- feeder_count, feeder_best (strongest signal), feeder_worst

MeshviewSource:
- Added feeders to ENDPOINT_SCHEDULE (every 20 ticks / 10 min)
- _fetch_feeders() samples 20 packets and queries packets_seen
- Auto-disables if endpoint returns 404

MeshDataStore:
- _enrich_feeder_data() aggregates gateway data across all sources
- _normalize_node_id() helper for hex/decimal conversion
- get_feeder_map() shows per-gateway coverage statistics
- get_node_feeders() returns sorted gateway list for a node

MeshReporter:
- Node detail shows feeder gateways with signal strength
- Tier 1 shows total unique gateways and avg per node

Discovered gateways: AIDA, BKBS, STLR, N7MH, stor, JTS

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 19:55:23 +00:00
b3c79f12da feat: Tick-based staggered polling for all sources
Both MeshviewSource and MeshMonitorDataSource now use tick-based
staggered polling instead of batch-every-5-minutes:

MeshviewSource (30s ticks):
- Packets: every tick (30s)
- Nodes: every 4 ticks (2 min)
- Stats/Edges: every 6 ticks (3 min)
- Traceroutes: every 10 ticks (5 min)

MeshMonitorDataSource (30s ticks):
- Packets: every 2 ticks (60s)
- Nodes/Telemetry: every 4 ticks (2 min)
- Traceroutes/Channels/Network/Topology: every 10 ticks (5 min)
- Solar: every 20 ticks (10 min)

Features:
- Source health status (avg_response_ms, tick_count, backed_off)
- Source coverage analysis (unique vs shared nodes)
- Tier 1 DATA SOURCES section shows all source health
- Node detail shows source visibility
- Incremental packets and telemetry with dedup
- Rate limit detection (429) with backoff
- Consecutive error exponential backoff
- polite_mode config option for shared instances

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 19:16:00 +00:00
bc644b3ac2 fix: Name single-gateway client nodes in Tier 1 (top 10 per region)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 17:04:49 +00:00
aef78996a9 feat: Named single-gw nodes, infra-only monitoring, commands overhaul
Coverage:
- Single-gateway infra nodes named as critical risks per region
- Client single-gw nodes counted but not individually named
- Mesh-wide single-gw infra summary

Monitoring rules by node type:
- Infrastructure: full detail - battery, offline, coverage, neighbors, hardware
- Clients causing problems: named - high util, top senders
- Clients otherwise: counted per region, not individually tracked
- POWER breakdown now infra-only

Commands:
- Removed hardcoded command list from config.py system_prompt
- Dynamic command list in router.py from dispatcher (only enabled commands)
- MeshMonitor commands no longer listed as MeshAI commands
- !help overhaul: grouped by category, per-command detailed help
- LLM explicitly told to only mention listed commands

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 15:33:14 +00:00
56536f55c8 feat: Rich Tier 1 data - named infra per region, problem nodes, expanded recommendations
Tier 1 now includes:
- Every infrastructure node BY NAME per region with status/battery/util/gateways
- Problem nodes section: offline infra, critical battery, high util, coverage risks
- Per-region coverage with gateway counts and single-gw counts
- Environmental data per region
- All 5 pillars with weights
- Expanded recommendations with specifics (10 max, up from 5)
- LLM prompt simplified: data speaks for itself

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 14:32:43 +00:00
51969050da fix: Replace deleted REGION_CONTEXT with config method, replace hardcoded city map with config aliases
- Line 763: REGION_CONTEXT.get() → self._region_context() (same method used elsewhere)
- Deleted _CITY_TO_REGION hardcoded dict
- Scope detection now uses config aliases/cities from RegionAnchor
- Fixed Sun Valley/Ketchum geography (was Central ID, should be South Central ID)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 07:11:08 +00:00
de400068dd feat(mesh): config-driven regions with stale purge and coverage fix
- Extended RegionAnchor with local_name, description, aliases, cities
- Moved region geographic context from hardcoded Python to config.yaml
- Added 7-day stale node purge in _do_refresh (556 → 267 nodes)
- Fixed coverage lookup: str(node_num) → node_num (int key)
- Added bidirectional neighbor lookup for better region assignment
- Dynamic geography building in router from config
- Reporter reads region context from config instead of hardcoded dict

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 06:33:38 +00:00
abcf2d88e2 feat: Geographic context — local names, accurate Idaho/Utah geography, no Unknown gaps
- Magic Valley, Treasure Valley, Panhandle, Dixie — local names in all output
- Southern Idaho correctly maps to Magic Valley, not lumped with Boise/IF
- Unlocated nodes excluded from coverage gap recommendations
- LLM response rules override brevity for mesh questions
- Node detail shows region with local context

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 06:08:58 +00:00
69f3d5d284 fix: Replace 5 remaining node_id refs with node_id_hex after NodeHealth removal
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 05:24:26 +00:00
4183abe755 refactor: DELETE NodeHealth — reporter uses UnifiedNode directly
NodeHealth is gone. MeshHealth.nodes is now dict[int, UnifiedNode].
Reporter reads all fields from UnifiedNode: coverage, environment,
neighbors, hw_model — everything available without cross-referencing.
This eliminates the entire category of field missing on NodeHealth bugs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 05:12:45 +00:00
ac2bb87473 fix: Coverage breakdown now uses str(node_num) for health node lookup
Health engine stores node IDs as decimal strings, but UnifiedNode.node_num
is an integer. The lookup health.nodes.get(n.node_num) was failing, causing
all nodes to show as Unlocated. Fixed by converting to string first.
2026-05-05 04:40:12 +00:00
cb61c4199c feat: Geographic coverage breakdown in mesh reporter
- Show per-region coverage stats in tier1 summary
- List single-gateway nodes in region detail
- Add coverage status to node detail view
- Add coverage gap recommendations
2026-05-05 04:07:19 +00:00
Ubuntu
b20dea60e2 feat(subscriptions): Add Phase 4 subscription system for scheduled reports
- Create subscriptions.py with SubscriptionManager class for SQLite storage
- Add subscribe.py commands: !sub, !unsub, !mysubs with aliases
- Update dispatcher.py to register subscription commands
- Modify main.py with scheduler tick (60s) and _check_scheduled_subs()
- Add build_node_compact() and build_region_compact() to mesh_reporter.py
- Support daily, weekly, and alerts subscription types
- Support mesh, region, and node scope filtering
- 5-minute matching window for schedule tolerance
- Dedup via last_sent tracking

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 02:26:12 +00:00