agessaman 80b6bcceea Refactor database connection handling in web viewer and improve error logging; fix keyword reporting to web viewer
- Simplified database connection management by using context managers to ensure connections are properly closed.
- Enhanced error handling during MQTT client disconnection in packet capture service, logging specific exceptions.
- Updated message handling in MessageHandler to capture command data for web viewer integration, improving response tracking.
2026-01-01 12:16:22 -08:00
2025-10-21 21:57:00 -07:00
2025-10-21 21:57:00 -07:00

MeshCore Bot

A Python bot that connects to MeshCore mesh networks via serial port, BLE, or TCP/IP. The bot responds to messages containing configured keywords, executes commands, and provides various data services including weather, solar conditions, and satellite pass information.

Features

  • Connection Methods: Serial port, BLE (Bluetooth Low Energy), or TCP/IP
  • Keyword Responses: Configurable keyword-response pairs with template variables
  • Command System: Plugin-based command architecture with built-in commands
  • Rate Limiting: Configurable rate limiting to prevent network spam
  • User Management: Ban/unban users with persistent storage
  • Scheduled Messages: Send messages at configured times
  • Direct Message Support: Respond to private messages
  • Logging: Console and file logging with configurable levels

Requirements

  • Python 3.7+
  • MeshCore-compatible device (Heltec V3, RAK Wireless, etc.)
  • USB cable or BLE capability

Installation

Quick Start (Development)

  1. Clone the repository:
git clone <repository-url>
cd meshcore-bot
  1. Install dependencies:
pip install -r requirements.txt
  1. Copy and configure the bot:
cp config.ini.example config.ini
# Edit config.ini with your settings
  1. Run the bot:
python3 meshcore_bot.py

Production Installation (Systemd Service)

For production deployment as a system service:

  1. Install as systemd service:
sudo ./install-service.sh
  1. Configure the bot:
sudo nano /opt/meshcore-bot/config.ini
  1. Start the service:
sudo systemctl start meshcore-bot
  1. Check status:
sudo systemctl status meshcore-bot

See SERVICE-INSTALLATION.md for detailed service installation instructions.

Configuration

The bot uses config.ini for all settings. Key configuration sections:

Connection

[Connection]
connection_type = serial          # serial, ble, or tcp
serial_port = /dev/ttyUSB0        # Serial port path (for serial)
#hostname = 192.168.1.60         # TCP hostname/IP (for TCP)
#tcp_port = 5000                  # TCP port (for TCP)
#ble_device_name = MeshCore       # BLE device name (for BLE)
timeout = 30                      # Connection timeout

Bot Settings

[Bot]
bot_name = MeshCoreBot            # Bot identification name
enabled = true                    # Enable/disable bot
rate_limit_seconds = 2            # Rate limiting interval
startup_advert = flood            # Send advert on startup

Keywords

[Keywords]
# Format: keyword = response_template
# Variables: {sender}, {connection_info}, {snr}, {timestamp}, {path}
test = "Message received from {sender} | {connection_info}"
help = "Bot Help: test, ping, help, hello, cmd, wx, aqi, sun, moon, solar, hfcond, satpass, dice, roll, joke, dadjoke, sports, channels, path, prefix, repeater, stats, alert"

Channels

[Channels]
monitor_channels = general,test,emergency  # Channels to monitor
respond_to_dms = true                      # Enable DM responses

External Data APIs

[External_Data]
# API keys for external services
n2yo_api_key =                    # Satellite pass data
airnow_api_key =                  # Air quality data

Alert Command

[Alert_Command]
alert_enabled = true                    # Enable/disable alert command
max_incident_age_hours = 24             # Maximum age for incidents (hours)
max_distance_km = 20.0                  # Maximum distance for proximity queries (km)
agency.city.<city_name> = <agency_ids>   # City-specific agency IDs (e.g., agency.city.seattle = 17D20,17M15)
agency.county.<county_name> = <agency_ids> # County-specific agency IDs (aggregates all city agencies)

Logging

[Logging]
log_level = INFO                  # DEBUG, INFO, WARNING, ERROR, CRITICAL
log_file = meshcore_bot.log       # Log file path
colored_output = true             # Enable colored console output

Usage

Running the Bot

python meshcore_bot.py

Available Commands

For a comprehensive list of all available commands with examples and detailed explanations, see COMMANDS.md.

Quick reference:

  • Basic: test, ping, help, hello, cmd
  • Information: wx, gwx, aqi, sun, moon, solar, solarforecast, hfcond, satpass, channels
  • Emergency: alert
  • Gaming: dice, roll
  • Entertainment: joke, dadjoke, hacker
  • Sports: sports
  • MeshCore Utility: path, prefix, stats, multitest
  • Management (DM only): repeater, advert, feed

Message Response Templates

Keyword responses support these template variables:

  • {sender} - Sender's node ID
  • {connection_info} - Connection details (direct/routed)
  • {snr} - Signal-to-noise ratio
  • {timestamp} - Message timestamp
  • {path} - Message routing path

Example:

[Keywords]
test = "Message received from {sender} | {connection_info}"
ping = "Pong!"
help = "Bot Help: test, ping, help, hello, cmd, wx, gwx, aqi, sun, moon, solar, solarforecast, hfcond, satpass, dice, roll, joke, dadjoke, sports, channels, path, prefix, repeater, stats, multitest, alert, webviewer"

Hardware Setup

Serial Connection

  1. Flash MeshCore firmware to your device
  2. Connect via USB
  3. Configure serial port in config.ini:
    [Connection]
    connection_type = serial
    serial_port = /dev/ttyUSB0  # Linux
    # serial_port = COM3        # Windows
    # serial_port = /dev/tty.usbserial-*  # macOS
    

BLE Connection

  1. Ensure your MeshCore device supports BLE
  2. Configure BLE in config.ini:
    [Connection]
    connection_type = ble
    ble_device_name = MeshCore
    

TCP Connection

  1. Ensure your MeshCore device has TCP/IP connectivity (e.g., via gateway or bridge)
  2. Configure TCP in config.ini:
    [Connection]
    connection_type = tcp
    hostname = 192.168.1.60  # IP address or hostname
    tcp_port = 5000          # TCP port (default: 5000)
    

Troubleshooting

Common Issues

  1. Serial Port Not Found:

    • Check device connection
    • Verify port name in config
    • List available ports: python -c "import serial.tools.list_ports; print([p.device for p in serial.tools.list_ports.comports()])"
  2. BLE Connection Issues:

    • Ensure device is discoverable
    • Check device name in config
    • Verify BLE permissions
  3. TCP Connection Issues:

    • Verify hostname/IP address is correct
    • Check that TCP port is open and accessible
    • Ensure network connectivity to the device
    • Verify the MeshCore device supports TCP connections
    • Check firewall settings if connection fails
  4. Message Parsing Errors:

    • Enable DEBUG logging for detailed information
    • Check meshcore library documentation for protocol details
  5. Rate Limiting:

    • Adjust rate_limit_seconds in config
    • Check logs for rate limiting messages

Debug Mode

Enable debug logging:

[Logging]
log_level = DEBUG

Architecture

The bot uses a modular plugin architecture:

  • Core modules (modules/): Shared utilities and core functionality
  • Command plugins (modules/commands/): Individual command implementations
  • Plugin loader: Dynamic discovery and loading of command plugins
  • Message handler: Processes incoming messages and routes to appropriate handlers

Adding New Commands

  1. Create a new command file in modules/commands/
  2. Inherit from BaseCommand
  3. Implement the execute() method
  4. The plugin loader will automatically discover and load the command

Example:

from .base_command import BaseCommand
from ..models import MeshMessage

class MyCommand(BaseCommand):
    name = "mycommand"
    keywords = ['mycommand']
    description = "My custom command"
    
    async def execute(self, message: MeshMessage) -> bool:
        await self.send_response(message, "Hello from my command!")
        return True

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Submit a pull request against the dev branch

License

This project is licensed under the MIT License.

Packet Capture Service

The bot includes an integrated packet capture service that can capture packets from the MeshCore network and publish them to MQTT brokers. This service is based on the standalone meshcore-packet-capture project.

Features

  • Packet Capture: Captures all incoming packets from the MeshCore network
  • MQTT Publishing: Publishes packets to one or more MQTT brokers
  • Multiple Brokers: Support for multiple MQTT brokers with individual configuration
  • JWT Authentication: Supports JWT-based authentication with on-device or Python signing
  • Status Publishing: Periodically publishes device status and statistics
  • File Output: Optional file output for packet logging

Configuration

Enable the packet capture service in config.ini:

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

# Owner information (for JWT authentication)
owner_public_key = YOUR_OWNER_PUBLIC_KEY
owner_email = your.email@example.com

# Private key (optional if using on-device signing)
private_key_path = /path/to/private_key.txt
auth_token_method = device           # device or python

# IATA airport code for topic templating
iata = LOC

# MQTT Broker Configuration (mqttN_* format)
# Multiple brokers can be configured (mqtt1_*, mqtt2_*, etc.)

# Broker 1 (Let's Mesh Analyzer - EU)
mqtt1_server = mqtt-eu-v1.letsmesh.net
mqtt1_port = 443
mqtt1_transport = websockets
mqtt1_use_tls = true
mqtt1_use_auth_token = true
mqtt1_token_audience = mqtt-eu-v1.letsmesh.net
mqtt1_topic_status = meshcore/{IATA}/{PUBLIC_KEY}/status
mqtt1_topic_packets = meshcore/{IATA}/{PUBLIC_KEY}/packets
mqtt1_websocket_path = /mqtt

# Broker 2 (Let's Mesh Analyzer - US)
mqtt2_server = mqtt-us-v1.letsmesh.net
mqtt2_port = 443
mqtt2_transport = websockets
mqtt2_use_tls = true
mqtt2_use_auth_token = true
mqtt2_token_audience = mqtt-us-v1.letsmesh.net
mqtt2_topic_status = meshcore/{IATA}/{PUBLIC_KEY}/status
mqtt2_topic_packets = meshcore/{IATA}/{PUBLIC_KEY}/packets
mqtt2_websocket_path = /mqtt

# Stats and status publishing
stats_in_status_enabled = true
stats_refresh_interval = 300         # Publish status every 5 minutes

# JWT renewal interval (seconds, 0 = disabled)
jwt_renewal_interval = 3600

# Health check interval (seconds, 0 = disabled)
health_check_interval = 30
health_check_grace_period = 2

MQTT Topic Templates

Topic templates support placeholders:

  • {IATA} - Replaced with the configured IATA code
  • {PUBLIC_KEY} - Replaced with the device's public key

Standalone Version

For a standalone packet capture solution that doesn't require the full bot, see the meshcore-packet-capture project.

Acknowledgments

Description
No description provided
Readme 17 MiB
Languages
Python 76.1%
HTML 10.9%
JavaScript 10.7%
Shell 1.8%
Nix 0.5%