No description
  • Python 99%
  • Shell 0.5%
  • Dockerfile 0.5%
Find a file
K7ZVX a4cb29002d fix(notifications): inject llm_backend into build_pipeline
build_pipeline previously constructed its own LLMBackend from
config.llm, which:
  - duplicated main.py's already-running backend instance
  - failed to inherit env-loaded LLM_API_KEY when called from
    short-lived scripts (eyeball checks, tests), forcing fallback
  - prevented pipeline components from sharing the live backend

build_pipeline and build_pipeline_components now require an
llm_backend parameter. main.py passes the same instance it
constructed for its primary responder. Tests pass mocks. The
digest accumulator now uses the live, authenticated backend.

Added test_build_pipeline_uses_provided_backend to lock in the
injection contract.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-15 03:08:31 +00:00
.github/workflows Add GHCR publishing workflow and update docker-compose for registry pull 2026-02-23 21:39:23 +00:00
config build: normalize all line endings to LF 2026-05-14 22:43:06 +00:00
dashboard-frontend build: normalize all line endings to LF 2026-05-14 22:43:06 +00:00
meshai fix(notifications): inject llm_backend into build_pipeline 2026-05-15 03:08:31 +00:00
tests fix(notifications): inject llm_backend into build_pipeline 2026-05-15 03:08:31 +00:00
.dockerignore Initial commit: MeshAI - LLM-powered Meshtastic assistant 2025-12-15 11:53:46 -07:00
.gitattributes build: add .gitattributes to enforce LF line endings 2026-05-14 22:42:14 +00:00
.gitignore build: normalize all line endings to LF 2026-05-14 22:43:06 +00:00
config.example.yaml build: normalize all line endings to LF 2026-05-14 22:43:06 +00:00
docker-compose.yml feat(dashboard): embedded FastAPI backend with REST API + WebSocket 2026-05-12 15:47:58 +00:00
docker-entrypoint.sh feat: Hybrid RAG knowledge base, sentence-aware chunking, MeshMonitor HTTP sync 2026-05-04 07:44:12 +00:00
Dockerfile feat(dashboard): embedded FastAPI backend with REST API + WebSocket 2026-05-12 15:47:58 +00:00
LICENSE Add MIT license file 2026-02-23 21:31:59 +00:00
pyproject.toml feat: Add MQTT source adapter 2026-05-12 21:57:11 +00:00
README.md docs: comprehensive README with full setup guide 2026-05-12 21:02:17 -06:00
requirements.txt feat: Add MQTT source adapter 2026-05-12 21:57:11 +00:00

MeshAI

LLM-powered mesh intelligence assistant for Meshtastic networks. MeshAI connects to your mesh as a physical node, monitors network health in real-time, and answers questions about your infrastructure over LoRa.

What It Does

MeshAI runs on your Meshtastic node and provides:

  • Mesh Intelligence — 5-pillar health scoring, per-region breakdowns, infrastructure monitoring, coverage gap analysis, and environmental sensing
  • Conversational Queries — ask "how's the mesh?" or "tell me about MHR" and get data-driven answers over LoRa
  • Node Distance — GPS-based distance calculations between any two nodes on the mesh
  • Multi-Source Awareness — aggregates data from multiple Meshview instances and MeshMonitor with staggered polling
  • Feeder Gateway Tracking — identifies which physical MQTT gateways hear each node and signal quality
  • Subscriptions — scheduled daily/weekly health reports and instant alerts delivered via DM
  • LLM Chat — general conversation, knowledge base lookups, and weather queries
  • Multi-Backend — supports Google Gemini, OpenAI, Anthropic Claude, and local LLMs via LiteLLM

Quick Start

# Clone
git clone https://github.com/zvx-echo6/meshai.git
cd meshai

# Install
pip install -e .

# Configure (interactive TUI)
meshai --config

# Run
meshai

Or with Docker:

mkdir -p meshai/data && cd meshai
curl -O https://raw.githubusercontent.com/zvx-echo6/meshai/main/docker-compose.yml
curl -o data/config.yaml https://raw.githubusercontent.com/zvx-echo6/meshai/main/config.example.yaml
# Edit data/config.yaml
docker compose up -d

Commands

Command Description
!health Mesh health overview with colored status dots
!region List all regions with health status
!region [name] Detailed region breakdown
!neighbors [node] Top infrastructure neighbors with signal quality
!sub daily 6pm Subscribe to daily health reports
!sub weekly 8am sun Subscribe to weekly digest
!sub alerts Subscribe to instant alerts on issues
!unsub [type] Remove a subscription
!mysubs List your active subscriptions
!clear Clear conversation history
!help Show available commands
!help [cmd] Detailed help for a command
!quakes Recent earthquakes in monitored area
!fires Active wildfires from NIFC
!hotspots NASA FIRMS satellite fire detections
!hotspots --new Only hotspots not matching known fires
!traffic Traffic incidents from TomTom
!space Space weather conditions (solar/geomagnetic)
!water USGS stream gauge readings
!air Air quality index

Commands can be disabled in config if another service (like MeshMonitor) handles them.

Mesh Intelligence

MeshAI continuously polls mesh data sources and computes a 5-pillar health score:

Pillar Weight What It Measures
Infrastructure 30% Router uptime — how many infra nodes are online
Utilization 25% Channel busyness — RF congestion across the mesh
Coverage 20% Gateway reach — how many monitoring sources see each node
Behavior 15% Traffic patterns — detecting noisy or misconfigured nodes
Power 10% Battery health — infrastructure nodes only

Health Display

!health shows a compact overview with personality:

📡 Mesh 🟢 healthy
🏗️ 15/16 routers up
❌ Down: TVM Tablerock Relay
📶 152 full coverage, 94 on thin ice
🔥 Hayden Peak Router at 21% util
🔋 All infra powered ✅
🌡️ 29-34°C across 2 sensors
Treasure Valley 🟢 | Magic Valley 🟢

Status dots: 🔵 perfect (100) · 🟢 healthy (75+) · 🟠 warning (50+) · 🔴 critical (<50)

Monitoring Rules

Infrastructure nodes (routers, repeaters) are monitored individually with full detail — battery, offline alerts, coverage, neighbors, hardware. Client nodes dying is normal and not tracked. Channel utilization and environmental sensors are monitored for all nodes.

Conversational Queries

Ask questions naturally over LoRa:

  • "how's the mesh?" → health overview with top issues
  • "tell me about MHR" → full node detail with neighbors, coverage, feeders
  • "where do we need more coverage?" → named gaps with specific nodes
  • "how far is MHR from AIDA?" → GPS distance calculation
  • "which nodes only reach one gateway?" → named nodes with their gateway
  • "which gateway has the best signal?" → feeder comparison

Geographic Regions

Regions are configurable with local names, descriptions, aliases, and cities — all manageable through the TUI. No hardcoded geography in the code.

mesh_intelligence:
  regions:
    - name: "South Central ID"
      local_name: "Magic Valley"
      description: "Twin Falls area"
      aliases: ["southern Idaho", "magic valley"]
      cities: ["Twin Falls", "Burley", "Jerome"]
      lat: 42.5
      lon: -114.5
      radius_km: 80

Environmental Feeds

MeshAI integrates real-time environmental data for situational awareness beyond mesh network health.

USGS Earthquake Monitoring

env:
  usgs:
    enabled: true
    min_magnitude: 2.5
    radius_km: 500
    center_lat: 43.6150
    center_lon: -116.2023

No API key required. Data from USGS Earthquake Hazards Program.

NWS Weather Alerts

env:
  nws:
    enabled: true
    zone: IDZ025         # NWS zone ID
    point: "43.6150,-116.2023"

No API key required. Find your zone at NWS Zone Lookup.

NOAA Space Weather

env:
  noaa_space:
    enabled: true

No API key required. Data from NOAA SWPC.

NIFC Wildfire Perimeters

env:
  nifc:
    enabled: true
    radius_km: 200
    center_lat: 43.6150
    center_lon: -116.2023

No API key required. Data from NIFC Open Data.

NASA FIRMS Satellite Fire Detection

env:
  firms:
    enabled: true
    map_key: "your-map-key"    # Required
    radius_km: 200
    center_lat: 43.6150
    center_lon: -116.2023
    source: VIIRS_SNPP         # VIIRS_SNPP, VIIRS_NOAA20, MODIS_NRT
    day_range: 1               # 1, 2, or 10 days

API Key Required: Register at NASA FIRMS. Free MAP_KEY provides access to near real-time satellite fire detections. Hotspots are cross-referenced against NIFC perimeters to identify potential new ignitions.

TomTom Traffic

env:
  tomtom:
    enabled: true
    api_key: "your-api-key"    # Required
    bbox: "-117.5,42.5,-115.0,44.5"  # lon1,lat1,lon2,lat2

API Key Required: Register at TomTom Developer Portal. Free tier includes 2,500 requests/day.

511 Road Conditions

env:
  fiveonone:
    enabled: true
    state: ID                  # State code
    api_key: "your-api-key"    # If required by state
    bbox: [-117.5, 42.5, -115.0, 44.5]

API key requirements vary by state. Check your state's 511 developer portal.

USGS Water Services

env:
  usgs_water:
    enabled: true
    sites: ["13206000", "13202000"]  # USGS site numbers

No API key required. Find sites at USGS Water Services.

AirNow Air Quality

env:
  airnow:
    enabled: true
    api_key: "your-api-key"    # Required
    zipcode: "83702"

API Key Required: Register at AirNow API.

Dashboard Configuration

dashboard:
  enabled: true
  host: 0.0.0.0
  port: 8080

The web dashboard provides real-time visualization of mesh nodes, environmental conditions, and alerts with WebSocket push notifications.


Data Sources

MeshAI aggregates from multiple sources using staggered tick-based polling (one API call per 30-second tick):

Meshview

Unauthenticated REST API. Supports multiple instances.

Endpoint Interval Data
/api/packets 30s Near real-time packet feed
/api/nodes 2 min Node list with metadata
/api/stats 3 min Traffic statistics
/api/edges 3 min Node-to-node connections
/api/traceroutes 5 min Route data
/api/packets_seen 10 min Per-gateway RSSI/SNR (sampled)

MeshMonitor

Authenticated (Bearer token). Single instance.

Endpoint Interval Data
/api/v1/packets 60s Packet feed
/api/v1/nodes 2 min Nodes with battery, utilization, hardware
/api/v1/telemetry 2 min Environmental sensors, device metrics
/api/v1/traceroutes 5 min Route data
/api/v1/channels 5 min Channel configuration
/api/v1/network 5 min Network statistics
/api/v1/solar 10 min Solar estimates

Rate Limiting

Built-in protection for all sources: HTTP 429 backoff with Retry-After, exponential backoff on consecutive errors, slow response warnings, and optional polite mode for shared instances.

Source Configuration

mesh_sources:
  - name: "local-meshview"
    type: meshview
    url: "http://192.168.1.100:8080"
    enabled: true

  - name: "meshmonitor"
    type: meshmonitor
    url: "http://192.168.1.100:3333"
    api_token: "your-bearer-token"
    enabled: true

Knowledge Base (RAG)

MeshAI uses a hybrid knowledge retrieval system with two backends:

Primary: RECON Qdrant Backend

Queries RECON's knowledge extraction pipeline — 2.8M+ vectors covering survival skills, communications, medical, technical documentation, Meshtastic docs, and more. Uses the same embedding infrastructure as RECON:

  • Dense embeddings: TEI service with BAAI/bge-m3 (1024-dim)
  • Sparse embeddings: bge-m3-sparse with IDF modifier
  • Search: Qdrant hybrid with Reciprocal Rank Fusion (dense + sparse)

No data is copied — MeshAI queries RECON's Qdrant and TEI services over the network.

knowledge:
  enabled: true
  backend: auto            # "qdrant", "sqlite", or "auto" (try qdrant, fall back)
  qdrant_host: "192.168.1.150"
  qdrant_port: 6333
  qdrant_collection: "recon_knowledge_hybrid"
  tei_host: "192.168.1.150"
  tei_port: 8090
  sparse_host: "192.168.1.150"
  sparse_port: 8091
  use_sparse: true
  top_k: 5

Fallback: Local SQLite

If the Qdrant backend is unreachable, MeshAI falls back to a local SQLite knowledge base using FTS5 keyword search and bge-small-en-v1.5 vector embeddings (384-dim).

# Build from Meshtastic ZIM file
python scripts/zim_to_knowledge.py meshtastic.zim --output knowledge.db
knowledge:
  enabled: true
  backend: sqlite
  db_path: /data/meshai_knowledge.db
  top_k: 5

Requires sqlite-vec and fastembed for the SQLite backend.

Architecture

┌──────────────────────────────────────────────────────────────────────┐
│                              MeshAI                                  │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  DATA SOURCES              INTELLIGENCE              DELIVERY        │
│  ┌─────────────┐          ┌──────────────┐         ┌────────────┐   │
│  │ Meshview ×N  │─────┐   │ Health Engine │────────▶│  Reporter  │   │
│  │ (staggered)  │     │   │ 5-pillar     │         │ Tier 1/2   │   │
│  └─────────────┘     ▼   │ scoring      │         └─────┬──────┘   │
│  ┌─────────────┐  ┌──────┴──┐            │               │          │
│  │ MeshMonitor │─▶│  Data   │─┘          │         ┌─────▼──────┐   │
│  │ (staggered) │  │  Store  │            │         │   Router   │   │
│  └─────────────┘  │ SQLite  │            │         │ scope/dist │   │
│                   └─────────┘            │         └─────┬──────┘   │
│                        │                 │               │          │
│                   ┌────▼────┐      ┌─────▼──────┐  ┌────▼────┐    │
│                   │ Feeder  │      │    LLM     │  │ Chunker │    │
│                   │ Sampling│      │  Backend   │  │LoRa-fit │    │
│                   └─────────┘      └────────────┘  └────┬────┘    │
│                                                         │         │
│  KNOWLEDGE             ALERTS             DELIVERY      │         │
│  ┌─────────────┐  ┌─────────────┐  ┌──────────────┐    │         │
│  │ RECON/Qdrant│  │   Alert     │  │ Subscription │    │         │
│  │ 2.8M vectors│  │   Engine    │  │   Manager    │    │         │
│  │ (network)   │  │ 17 triggers │  │ daily/weekly │    │         │
│  ├─────────────┤  │  scaling    │  │   alerts     │    │         │
│  │ SQLite FTS5 │  │  cooldown   │  └──────┬───────┘    │         │
│  │ (fallback)  │  └──────┬──────┘         │            │         │
│  └─────────────┘         │          ┌─────▼────────┐   │         │
│                          └─────────▶│  Responder   │◀──┘         │
│  ┌─────────────┐                    │ ACK-paced DM │             │
│  │ Conversation│                    │ Channel alert│             │
│  │   History   │                    └──────────────┘             │
│  └─────────────┘                                                 │
│                                                                   │
└───────────────────────────────────────────────────────────────────┘
         │                    │
    ┌────▼────┐          ┌────▼────┐
    │  TEI    │          │ Qdrant  │
    │ bge-m3  │          │ hybrid  │
    │ cortex  │          │ cortex  │
    └─────────┘          └─────────┘

Dashboard API Reference

The dashboard exposes a REST API (default port 8080):

Core Endpoints

Endpoint Method Description
/api/health GET System health check
/api/status GET Full system status with health scores
/api/nodes GET Connected mesh nodes
/api/messages GET Recent mesh messages

Environmental Data

Endpoint Method Description
/api/env/earthquakes GET Recent earthquakes
/api/env/weather GET Weather conditions and alerts
/api/env/fires GET Active wildfires from NIFC
/api/env/hotspots GET NASA FIRMS satellite detections
/api/env/traffic GET Traffic incidents
/api/env/water GET Stream gauge readings
/api/env/space GET Space weather data
/api/env/air GET Air quality readings

Alerts

Endpoint Method Description
/api/alerts/active GET Currently active alerts
/api/alerts/history GET Historical alerts (?severity=, ?source=, ?limit=, ?offset=)
/api/alerts/{id}/ack POST Acknowledge an alert
/api/subscriptions GET Alert subscriptions

WebSocket

Connect to /ws for real-time updates:

const ws = new WebSocket('ws://localhost:8080/ws');
ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  // data.type: 'message', 'alert', 'node_update', 'health_update'
};

Message Chunking

Long responses are split into mesh-friendly chunks with sentence-aware splitting, configurable limits, and continuation prompts. Command output (like !health) packs multiple lines into 2-3 messages using newlines within each message to minimize airtime usage.

response:
  max_length: 200       # Max chars per message
  max_messages: 3       # Messages before continuation prompt

Alerting

Real-time alerts when mesh conditions change, with scaling cooldowns to prevent spam.

Alert Conditions (17 total, each toggleable)

Pillar Condition Default Threshold
Infrastructure Router goes offline
Infrastructure Router recovery
Infrastructure New router appears
Power Battery warning <50%
Power Battery critical <25%
Power Battery emergency <10%
Power 7-day declining trend >10% drop with rate
Power USB → battery (power outage)
Power Solar not charging during day
Utilization Sustained high utilization >20% for 6h
Utilization Packet flood >500 pkts/24h
Coverage Infra drops to single gateway
Coverage Feeder gateway stops responding
Coverage Region total blackout All infra offline
Scores Mesh health score drop <70/100
Scores Region health score drop <60/100

Scaling Cooldown

Alerts don't spam. When a condition triggers:

  1. Alert 1: fires immediately
  2. Alert 2: 12 hours later (if still in condition)
  3. Alert 3: 24 hours after that
  4. Alert 4: 48 hours after that
  5. Stops until condition resolves

When the condition clears, one recovery notification fires and the tracker resets.

Delivery

Alerts are delivered two ways:

  • Channel broadcast: configurable channel index for mesh-wide visibility
  • DM to subscribers: users who ran !sub alerts receive DMs matching their scope

Critical Nodes

Designate important infrastructure (e.g., MHR, HPR) as critical. When a critical node goes offline, alerts use priority formatting.

mesh_intelligence:
  critical_nodes: ["MHR", "HPR"]
  alert_channel: 0        # Channel for broadcast alerts (-1 = disabled)

All conditions and thresholds are configurable via the TUI under Mesh Intelligence → Alert Rules.

LLM Configuration

llm:
  backend: "google"            # openai, anthropic, google
  api_key: "your-api-key"
  model: "gemini-2.0-flash"

Local LLMs

MeshAI works with any OpenAI-compatible API:

  • LiteLLM: base_url: "http://localhost:4000/v1"
  • Open WebUI: base_url: "http://localhost:3000/api"
  • Ollama: base_url: "http://localhost:11434/v1"

Docker

connection:
  type: "tcp"
  tcp_host: "192.168.1.100"
  tcp_port: 4403

Serial Connection

connection:
  type: "serial"
  serial_port: "/dev/ttyUSB0"

Edit docker-compose.serial.yml to match your device path.

Environment Variables

LLM_API_KEY=your-key-here docker compose up -d

Running Alongside Other Services

advBBS

MeshAI coexists with advBBS on the same node. BBS protocol messages (sync, RAP, mail notifications) are automatically filtered. No configuration needed.

bot:
  filter_bbs_protocols: true

MeshMonitor

MeshAI integrates with MeshMonitor at two levels: it fetches MeshMonitor's auto-responder patterns to avoid duplicate responses, and it uses MeshMonitor's API as a data source for mesh intelligence (battery, telemetry, traceroutes, solar).

meshmonitor:
  enabled: true
  url: "http://192.168.1.100:8080"
  inject_into_prompt: true
  refresh_interval: 300

Running as a Service

# /etc/systemd/system/meshai.service
[Unit]
Description=MeshAI - Meshtastic Mesh Intelligence
After=network.target

[Service]
Type=simple
User=your-user
WorkingDirectory=/path/to/meshai
ExecStart=/usr/bin/python3 -m meshai
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable meshai
sudo systemctl start meshai

Acknowledgments

  • Meshtastic — the mesh networking platform
  • MeshMonitor by Yeraze — monitoring integration and data source
  • advBBS — BBS coexistence design
  • sqlite-vec by Alex Garcia — vector search in SQLite
  • fastembed by Qdrant — fast local embeddings

License

MIT License

Author

K7ZVX - matt@echo6.co