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.
- 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
- Python 3.7+
- MeshCore-compatible device (Heltec V3, RAK Wireless, etc.)
- USB cable or BLE capability
- Clone the repository:
git clone <repository-url>
cd meshcore-bot- Install dependencies:
pip install -r requirements.txt- Copy and configure the bot:
cp config.ini.example config.ini
# Edit config.ini with your settings- Run the bot:
python3 meshcore_bot.pyFor production deployment as a system service:
- Install as systemd service:
sudo ./install-service.sh- Configure the bot:
sudo nano /opt/meshcore-bot/config.ini- Start the service:
sudo systemctl start meshcore-bot- Check status:
sudo systemctl status meshcore-botSee SERVICE-INSTALLATION.md for detailed service installation instructions.
The bot uses config.ini for all settings. Key configuration sections:
[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]
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]
# 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]
monitor_channels = general,test,emergency # Channels to monitor
respond_to_dms = true # Enable DM responses[External_Data]
# API keys for external services
n2yo_api_key = # Satellite pass data
airnow_api_key = # Air quality data[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]
log_level = INFO # DEBUG, INFO, WARNING, ERROR, CRITICAL
log_file = meshcore_bot.log # Log file path
colored_output = true # Enable colored console outputpython meshcore_bot.pyThe bot responds to these commands:
Basic Commands:
testort- Test message response (can include optional phrase:test <phrase>)ping- Ping/pong responsehelp- Show available commands (usehelp <command>for command details)hello- Greeting response (also responds to: hi, hey, howdy, greetings, etc.)cmd- List available commands in compact format
Information Commands:
channels- List hashtag channels (usechannelsfor general,channels listfor all categories,channels <category>for specific categories,channels #channelfor specific channel info)wx <zipcode>- Weather information for US zip code (also:weather,wxa,wxalert)gwx <location>- Global weather for any location worldwide (also:globalweather,gwxa)aqi <location>- Air quality index (usage:aqi seattle,aqi greenwood,aqi vancouver canada,aqi 47.6,-122.3, oraqi help)sun- Sunrise/sunset timesmoon- Moon phase and timessolar- Solar conditions and HF band statussolarforecastorsf- Solar panel production forecast (usage:sf <location|repeater_name|coordinates|zipcode> [panel_size] [azimuth, 0=south] [angle])hfcond- HF band conditionssatpass <NORAD>- Satellite pass information (default: radio passes, all passes above horizon)satpass <NORAD> visual- Visual passes only (must be visually observable)satpass <shortcut>- Use shortcuts likeiss,hst,hubble,goes18,tiangong
Emergency Commands:
alert <city|zipcode|street city|lat,lon|county> [all]- Get active emergency incidents (e.g.,alert seattle,alert 98101,alert seattle all)
Gaming Commands:
dice- Roll dice (d6 by default, or specify likedice d20,dice 2d6)roll- Roll random number (1-100 by default, or specify likeroll 50)
Entertainment Commands:
joke- Get a random joke (usejoke [category]for specific category)dadjoke- Get a dad joke from icanhazdadjoke.comhacker- Responds to Linux commands (sudo,ps aux,grep,ls -l, etc.) with supervillain mainframe errors
Sports Commands:
sports- Get scores for default teamssports <team>- Get scores for specific teamsports <league>- Get scores for league (nfl, mlb, nba, etc.)
MeshCore Utility Commands:
pathordecodeorroute- Decode message routing pathprefix <XX>- Look up repeaters by two-character prefix (e.g.,prefix 1A)prefix refresh- Refresh prefix cacheprefix freeorprefix available- Show available prefixesprefix <XX> all- Include all repeaters (not just active)
stats- Show bot usage statistics for past 24 hoursstats messages- Message statisticsstats channels- Channel statisticsstats paths- Path statistics
multitestormt- Listens for 6 seconds and collects all unique paths from incoming messages
Management Commands (DM only):
repeaterorrepeatersorrp- Manage repeater contacts (DM only, requires ACL permissions)repeater scan- Scan and catalog new repeatersrepeater list- List repeater contacts (use--allto show purged ones)repeater purge <days>- Purge repeaters older than specified daysrepeater purge <name>- Purge specific repeater by namerepeater purge all- Purge all repeatersrepeater restore <name>- Restore a previously purged repeaterrepeater stats- Show repeater management statisticsrepeater status- Show contact list status and limitsrepeater manage- Auto-manage contact list (use--dry-runto preview)- See
help repeaterfor full list of subcommands
advert- Send network flood advert (DM only, 1hr cooldown)
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"- Flash MeshCore firmware to your device
- Connect via USB
- 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
- Ensure your MeshCore device supports BLE
- Configure BLE in
config.ini:[Connection] connection_type = ble ble_device_name = MeshCore
- Ensure your MeshCore device has TCP/IP connectivity (e.g., via gateway or bridge)
- 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)
-
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()])"
-
BLE Connection Issues:
- Ensure device is discoverable
- Check device name in config
- Verify BLE permissions
-
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
-
Message Parsing Errors:
- Enable DEBUG logging for detailed information
- Check meshcore library documentation for protocol details
-
Rate Limiting:
- Adjust
rate_limit_secondsin config - Check logs for rate limiting messages
- Adjust
Enable debug logging:
[Logging]
log_level = DEBUGThe 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
- Create a new command file in
modules/commands/ - Inherit from
BaseCommand - Implement the
execute()method - 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- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
This project is licensed under the MIT License.
- MeshCore Project for the mesh networking protocol
- Some commands adapted from MeshingAround bot by K7MHI Kelly Keeton 2024