Files
meshcore-bot/docs/packet-capture.md
agessaman 8b363afed7 Update IATA code in configuration files and packet capture service
- Changed the default IATA code from 'LOC' to 'XYZ' in `config.ini.example` and `packet-capture.md` to reflect updated routing requirements.
- Updated the `PacketCaptureService` to use 'XYZ' as the fallback IATA code, ensuring consistency across the application.
2026-03-09 22:09:39 -07:00

6.7 KiB
Raw Permalink Blame History

Packet Capture Service

Captures packets from the MeshCore network and publishes them to MQTT brokers.


Quick Start

  1. Configure Bot - Edit config.ini:
[PacketCapture]
enabled = true

# Owner info for JWT auth -- these are optional
owner_public_key = YOUR_COMPANION_PUBLIC_KEY_HERE
owner_email = your.email@example.com

# IATA code for topic routing (XYZ is invalid set it to a real IATA)
iata = XYZ

# MQTT Broker (Let's Mesh Analyzer)
mqtt1_enabled = true
mqtt1_server = mqtt-us-v1.letsmesh.net
mqtt1_port = 443
mqtt1_transport = websockets
mqtt1_use_tls = true
mqtt1_use_auth_token = true
mqtt1_token_audience = mqtt-us-v1.letsmesh.net
mqtt1_topic_status = meshcore/{IATA}/{PUBLIC_KEY}/status
mqtt1_topic_packets = meshcore/{IATA}/{PUBLIC_KEY}/packets
  1. Restart Bot - The service starts automatically

Configuration

Basic Settings

[PacketCapture]
enabled = true                    # Enable packet capture
output_file = packets.json        # Optional: save to file
verbose = false                   # Detailed packet logging
debug = false                     # Debug mode

Authentication

auth_token_method = device        # Use device's built-in signing
# No private key file needed

Option 2: Python Signing

auth_token_method = python        # Use Python signing
private_key_path = /path/to/key.txt  # Path to private key file

MQTT Brokers

Configure multiple brokers using mqttN_* pattern:

# Broker 1
mqtt1_enabled = true
mqtt1_server = mqtt-us-v1.letsmesh.net
mqtt1_port = 443
mqtt1_transport = websockets      # tcp or websockets
mqtt1_use_tls = true
mqtt1_use_auth_token = true
mqtt1_topic_status = meshcore/{IATA}/{PUBLIC_KEY}/status
mqtt1_topic_packets = meshcore/{IATA}/{PUBLIC_KEY}/packets

# Broker 2
mqtt2_enabled = true
mqtt2_server = your.broker.com
mqtt2_port = 1883
mqtt2_transport = tcp
mqtt2_username = user
mqtt2_password = pass

Filtering by packet type

You can limit which packet types are uploaded to each broker with mqttN_upload_packet_types. Use a comma-separated list of type numbers; if unset or empty, all packet types are uploaded.

# Only upload text messages and adverts to this broker
mqtt1_upload_packet_types = 2, 4

# Broker 2 gets everything (default)
# mqtt2_upload_packet_types =

Packet type reference:

Type Name Description
0 REQ Request
1 RESPONSE Response
2 TXT_MSG Text message
3 ACK Acknowledgment
4 ADVERT Advertisement
5 GRP_TXT Group text
6 GRP_DATA Group data
7 ANON_REQ Anonymous request
8 PATH Path
9 TRACE Trace
10 MULTIPART Multipart
1115 Type11RAW_CUSTOM Other types

Packets that are excluded by this filter are still written to the output file (if configured) and still counted; they are only skipped for MQTT upload to that broker. Debug logs will show "Skipping" for those packets.

Topic Templates

Placeholders:

  • {IATA} - Your IATA code (e.g., SEA)
  • {iata} - Lowercase IATA code
  • {PUBLIC_KEY} - Device public key (uppercase)
  • {public_key} - Device public key (lowercase)

Status Publishing

stats_in_status_enabled = true    # Include device stats in status
stats_refresh_interval = 300      # Publish status every 5 minutes
jwt_renewal_interval = 86400      # Renew JWT every 24 hours

Packet Format

Packet Message

{
  "origin": "MyBot",
  "origin_id": "ABCD1234...",
  "timestamp": "2026-01-04T12:34:56",
  "type": "PACKET",
  "direction": "rx",
  "len": "42",
  "packet_type": "2",
  "route": "D",
  "payload_len": "32",
  "raw": "DEADBEEF...",
  "SNR": "8.5",
  "RSSI": "-42",
  "hash": "ABC123..."
}

Status Message

{
  "status": "online",
  "timestamp": "2026-01-04T12:34:56",
  "origin": "MyBot",
  "origin_id": "ABCD1234...",
  "model": "Heltec V3",
  "firmware_version": "v3.1.2",
  "radio": "915000000,250,9,8",
  "client_version": "meshcore-bot/1.0.0",
  "stats": {
    "rx_packets": 1234,
    "tx_packets": 567
  }
}

Troubleshooting

Service Not Starting

Check logs:

tail -f meshcore_bot.log | grep PacketCapture

Common issues:

  • enabled = false in config
  • Missing paho-mqtt library: pip install paho-mqtt

MQTT Not Connecting

  1. Check broker settings - Verify hostname and port
  2. Test connection manually:
    mosquitto_pub -h mqtt-us-v1.letsmesh.net -p 443 -t test -m "test"
    
  3. Check authentication - Verify JWT token generation
  4. Check logs - Look for connection errors

No Packets Being Published

  1. Verify MQTT connection - Check logs for "Connected to MQTT broker"
  2. Check packet count - Service logs "Captured packet #N" (or "Skipping packet #N" when filtered) for each packet
  3. Verify topics - Ensure topics match broker expectations
  4. Check upload filter - If mqttN_upload_packet_types is set, only those types are uploaded. DEBUG Logs show "packet type X not in [Y, Z]" when a packet is skipped

Advanced

Multiple Brokers

Configure up to 10 brokers (mqtt1_* through mqtt10_*). Each broker has independent connection tracking and auto-reconnection.

Health Monitoring

health_check_interval = 30        # Check connection every 30s
health_check_grace_period = 2     # Allow 2 failures before warning

JWT Authentication

Tokens are valid for 24 hours and auto-renewed. The service tries on-device signing first (if auth_token_method = device), then falls back to Python signing.

Token Format:

{
  "iat": 1234567890,
  "exp": 1234654290,
  "aud": "mqtt-us-v1.letsmesh.net",
  "publicKey": "DEVICE_PUBLIC_KEY",
  "owner": "OWNER_PUBLIC_KEY",
  "email": "your@email.com",
  "iata": "SEA"
}

FAQ

Q: Do I need to provide a private key? A: Not if using on-device signing (auth_token_method = device). The service will fetch the key from your device automatically.

Q: Can I publish to my own MQTT broker? A: Yes. Set mqtt1_use_auth_token = false and provide mqtt1_username and mqtt1_password.

Q: What's the difference between TCP and WebSockets? A: WebSockets work through firewalls better (uses HTTPS port 443). TCP is lighter but may be blocked.

Q: How do I disable packet capture but keep status publishing? A: You can't disable just packet capture - it's all or nothing. Consider filtering on the broker side.

Q: Can I capture TX (outgoing) packets? A: Currently only RX (incoming) packets are captured.