Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
121 commits
Select commit Hold shift + click to select a range
15fb42a
Refactor environment variables in docker-compose
Mitchcom Jan 8, 2026
f7aea78
Change STORAGE_API_ROOT to new meshflow URL
Mitchcom Jan 8, 2026
6e86d49
Enhance !tr command with full bidirectional path and fix storage errors
Jan 12, 2026
81d16a7
Update usage instructions and add new command
Mitchcom Jan 13, 2026
5cdbf0b
Split traceroute response into separate outbound and inbound messages
Jan 13, 2026
2566d2c
Add TCP proxy service for multi-client support and update docker-compose
Feb 2, 2026
549cd12
Fix env variable name in docker-compose
Feb 2, 2026
9ac4995
Hardcode MESHTASTIC_IP to 192.168.4.210 for immediate fix
Feb 2, 2026
d3c038f
Fix ADMIN_NODES crash and add proxy startup delay
Feb 2, 2026
60fa5b2
Fix proxy broken pipe error with auto-reconnect logic
Feb 2, 2026
5bf6a57
Update docker-compose with IP comment and variable support
Feb 2, 2026
a7fe686
Pass STORAGE_API vars to container
Feb 2, 2026
cabe3d5
Filter unsupported packet types to avoid API errors
Feb 2, 2026
25efd66
Add proxy watchdog to reconnect on silence
Feb 3, 2026
5faddc0
Implement !status command and proxy health tracking
Feb 3, 2026
38a0527
Fix StatusCommand inheritance and imports
Feb 3, 2026
acd7bb8
Increase watchdog timeout to 300s to avoid false positives
Feb 3, 2026
10ff6e0
Fix: tcp_proxy reconnect bug where it monitored closed sockets
Feb 3, 2026
5dace2a
Fix: Restore missing variable initializations in tcp_proxy
Feb 3, 2026
0474366
UI: Add newline to !help command response
Feb 3, 2026
5f0fd70
Fix logging: correctly identify channels and adjust debug levels
Feb 4, 2026
3c3ab1a
Merge branch 'feature/traceroute-update'
Feb 4, 2026
4712c89
Merge branch 'feature/tcp-proxy'
Feb 4, 2026
23a3459
Update README with new features and commands
Feb 4, 2026
8c04a1d
Add hourly node count reporting to Channel 2
Feb 4, 2026
15159e4
Fix TCP proxy init buffer replay speed
Feb 4, 2026
be3e303
Send node count report 10s after connection
Feb 4, 2026
36785e9
Add debug logging for report_node_count and channel list
Feb 4, 2026
eaefe5a
Log channel roles and enable wantAck for reporting
Feb 4, 2026
c0678e5
Test: Send node count to Channel 0 (Primary)
Feb 4, 2026
2ce7795
Finalize node count reporting on Channel 2
Feb 4, 2026
f4c6d56
Add !nodes totals command and make report_node_count flexible
Feb 5, 2026
e314bd8
Sync docker-compose.yaml from live server (Fix Watchtower API version)
Feb 5, 2026
5602609
Correct environment variable name to MESHTASTIC_IP in docker-compose.…
Feb 5, 2026
0a35591
Update node count reporting: 3-hour intervals, immediate alert on 0 n…
Feb 5, 2026
4e003a1
Update README with !nodes totals command and reporting features
Feb 5, 2026
22ea9da
Update README with personalization details
Mitchcom Feb 5, 2026
a4c4a4b
Update README with Node-totals feature description
Mitchcom Feb 5, 2026
6a5dce5
Explain docker-compose vs docker-compose-remote in README
Feb 5, 2026
3f63a1e
Increase TCP proxy buffer size to 16KB for better large data handling
Feb 6, 2026
f8afa97
Allow common commands (!ping, !hello, !nodes, !status, !whoami) in pu…
Feb 6, 2026
3e02306
Resolve merge conflicts and add customization toggles
Feb 9, 2026
ecd197d
Add startup logging and fix IP mapping
Feb 9, 2026
039335a
Merge feature/tcp-proxy into main and update README
Feb 9, 2026
fa02fdd
Update .env example in README
Feb 9, 2026
e73c254
Implement handshake and rolling buffers in TCP proxy for multi-client…
Feb 12, 2026
0610e25
Refine TcpProxy buffering: reduce handshake size, add pacing for repl…
Feb 12, 2026
5b20701
Fix TCP Proxy: Implement packet framing to ensure stream integrity an…
Feb 12, 2026
538e6f0
Fix syntax error in tcp_proxy.py
Feb 12, 2026
fec6b4b
Fix duplicate messages in TCP Proxy: implement client ready states an…
Feb 12, 2026
032a965
Fix message sending: remove client ready states to prevent dropped AC…
Feb 12, 2026
c180175
Fix NoneType crash and improve connection stability: implement 2s rep…
Feb 12, 2026
c7ca99b
Improve Proxy stability: enable TCP Keep-Alives and implement paced o…
Feb 13, 2026
9a91662
Fix proxy sync: disconnect all clients on radio loss to force re-sync…
Feb 13, 2026
42938e1
Fix node timestamp bug and implement non-blocking proxy reconnection …
Feb 14, 2026
295cf3d
Fix: Respect ENABLE_FEATURE_NODE_TOTALS setting for connection-time r…
Feb 14, 2026
138321b
Fix: Add missing environment variables to docker-compose.yaml and imp…
Feb 14, 2026
db330ed
Add configurable node report frequency via FREQUENCY_OF_NODE_REPORTS …
Feb 14, 2026
78bf240
Add detailed logging for Storage API troubleshooting
Feb 16, 2026
0ffb8cf
Log Storage API responses at INFO level
Feb 16, 2026
b3d3554
Fix 404 errors by adding guards for uninitialized node ID
Feb 16, 2026
f8ea101
Fix watchtower Docker API version mismatch
Feb 17, 2026
357d950
Fix Meshflow API compatibility, update MTEK IP, and resolve NoneType …
Feb 17, 2026
611059c
Enhance proxy heartbeat to log client IPs
Feb 17, 2026
dcb5183
Fix onResponseTraceRoute signature for newer meshtastic library
Feb 17, 2026
b174aa0
Refine onResponseTraceRoute to handle dictionary packets
Feb 17, 2026
2c1ebdc
Add timeout notification for traceroute requests
Feb 17, 2026
c5e38b1
Add verbose connection/disconnection logging to proxy
Feb 18, 2026
4722b83
Add support for targeted traceroute via !tr <shortname>
Feb 19, 2026
14fd1d5
Fix traceroute hang by supporting multiple concurrent requesters per …
Feb 19, 2026
cbdf8b0
Add debug logging to diagnose message receipt issues after traceroute
Feb 19, 2026
3af6b70
Fix bot hang by making traceroute callback defensive against NoneType…
Feb 19, 2026
cd091da
Add processing reaction and improve timeout responsiveness
Feb 19, 2026
0f9830c
Improve traceroute data extraction and diagnostic logging
Feb 19, 2026
9b5c768
Fix traceroute data extraction by checking 'traceroute' key
Feb 19, 2026
c5443cb
Further improvements to traceroute stability and diagnostics
Feb 19, 2026
ffe63b0
Offload blocking command and traceroute processing to threads to prev…
Feb 19, 2026
0768928
Small cleanup of redundant import in bot.py
Feb 19, 2026
8496cc8
Cumulative stability fixes: formatting, robust ID detection, and bett…
Feb 19, 2026
f7939e0
FIX: Restore missing methods in bot.py
Feb 19, 2026
9fd858c
Reduce congestion and improve traceroute result delivery by setting w…
Feb 20, 2026
f4ddada
Silence watchtower errors and increase radio settle time for tracerou…
Feb 20, 2026
231513b
Append target/local node to traceroute output for full path visibility
Feb 20, 2026
0186cb4
FIX: Correct indentation in bot.py and ensure full traceroute path vi…
Feb 20, 2026
ccb07ab
Update README to document targeted traceroute feature
Feb 20, 2026
6d10ea7
Update traceroute command description in README
Mitchcom Feb 20, 2026
68770f0
Ensure traceroute always sends two messages (TO and FROM) even for di…
Feb 20, 2026
c1af6c9
Merge branch 'Extended-TR' of https://github.com/Mitchcom/meshtastic-…
Feb 20, 2026
141a0eb
Update README: add (outbound & inbound) to targeted traceroute descri…
Feb 20, 2026
6d18611
feat: implement !nodes totals subcommand and fix tests
Feb 21, 2026
f73467c
perf: optimize node sync to reduce redundant logs and storage writes
Feb 21, 2026
60dec91
Fix TcpProxy deadlock: Implement RLock and synchronized snapshots. Ad…
Feb 21, 2026
54c555f
Fix TcpProxy socket blocking: Implement 10s timeouts for all sockets …
Feb 21, 2026
84a25ca
Fix redundant 30 minute timeout response on !tr
Mar 4, 2026
7180994
Expose TCP proxy port 4403 on remote compose
Mar 4, 2026
324202f
Refactor Core Services: Asyncio Proxy, Thread-Safe DBs, Narrowed Errors
Mar 5, 2026
38f486b
Fix emoji reaction protobuf type mismatch: expect int instead of bool
Mar 5, 2026
5cfa693
Add detailed traceroute debugging logs
Mar 5, 2026
9f3215d
Add more traceroute debugging logs
Mar 5, 2026
8c778e2
Enable INFO logging for core interfaces
Mar 5, 2026
fa7ce24
Add packet ID and request ID tracking for traceroute
Mar 5, 2026
2e9d95f
Force full traceroute even for 0-hop nodes and add logging
Mar 5, 2026
4144600
Final cleanup: Revert log levels and restore Zero Hops optimization
Mar 5, 2026
2a7038b
Consolidate traceroute response into a single message for reliability
Mar 5, 2026
0ec15d7
Optimize traceroute response for 200 char limit
Mar 5, 2026
fa7b265
Fix combined_response variable error
Mar 5, 2026
8d3f226
Permanently remove Zero Hops shortcut to force real trace verification
Mar 5, 2026
e3a4a48
Fix traceroute response context and enable ACKs for reliability
Mar 5, 2026
80e75cc
Add hop counts to consolidated traceroute message
Mar 5, 2026
c2e1a67
Update traceroute to reply in DM only and use thumbs up for public re…
Mar 5, 2026
e3bb6a1
Ignore ROUTING_APP in StorageAPI to prevent backend API errors
Mar 5, 2026
d150741
Enhance logging output and documentation updates
Mar 6, 2026
0d3c3be
Update README with new logging formats
Mar 6, 2026
a6f77d8
Add undocumented commands to README
Mar 6, 2026
f7301a0
feat: add admin command to help menu
Mar 9, 2026
04bc77d
feat: implement exponential backoff and improved logging in TcpProxy
Mar 12, 2026
ef277b2
feat: make TCP proxy cache sizes configurable via env vars
Mar 14, 2026
c5bc107
Merge upstream/main: resolved conflicts in main, bot, factory and res…
Mar 18, 2026
b25cc8f
Fix UnboundLocalError in StorageAPI response handling
Mar 18, 2026
5513938
Fix SQLite connection leak and improve IGNORE_PORTNUMS matching
Mar 18, 2026
84276c7
Merge branch 'main' into merge-upstream-preserve-features
maattm Mar 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,28 @@ ADMIN_NODES='!aae8900d'
# The root URL of the Meshflow API
STORAGE_API_ROOT='http://localhost:8000'
STORAGE_API_TOKEN=...
# Features
ENABLE_TCP_PROXY=true
# Handshake Cache size for TCP proxy (how many historical packets to cache to allow new clients to catch up quickly)
PROXY_HANDSHAKE_CACHE_SIZE=100
# Rolling Cache size for TCP proxy (how many recent packets to keep in the rolling buffer)
PROXY_ROLLING_CACHE_SIZE=100
ENABLE_FEATURE_NODE_TOTALS=true
FREQUENCY_OF_NODE_REPORTS=3
CHANNEL_FOR_NODE_TOTAL_BROADCAST=2

# Commands
ENABLE_COMMAND_PING=true
ENABLE_COMMAND_TR=true
ENABLE_COMMAND_HELLO=true
ENABLE_COMMAND_HELP=true
ENABLE_COMMAND_NODES=true
ENABLE_COMMAND_WHOAMI=true
ENABLE_COMMAND_PREFS=true
ENABLE_COMMAND_ADMIN=true
ENABLE_COMMAND_STATUS=true

# API Version (usually 1 or 2)
STORAGE_API_VERSION=2

# Use these if you want to upload to a second API (usually used during testing)
Expand All @@ -15,10 +37,10 @@ STORAGE_API_VERSION=2
# Use this if you want to receive commands from the Meshflow server (e.g. traceroute)
MESHFLOW_WS_URL=ws://localhost:8000

# Comma-separated portnums to skip when submitting packets to the API (e.g. custom or rejected ports)
# Comma-separated portnums to skip when submitting packets to the API (e.g. custom or rejected portnums)
IGNORE_PORTNUMS=345,ROUTING_APP

# Traceroute config
# Traceroute config (for WebSocket commands)
TR_HOPS_LIMIT=5
# Min seconds between traceroutes (firmware enforces ~30s; we rate-limit client-side)
TR_MIN_INTERVAL_SEC=30
Expand Down
115 changes: 93 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Meshtastic Bot

### Although this is based on https://github.com/pskillen/meshtastic-bot I have personalised it a lot to my own setup for commands, auto replies and automations etc

I am now working on Node-totals which I hope to be able to report the number of nodes my remote nodes can see.

Meshtastic Bot is a Python-based bot for interacting with Meshtastic devices. It listens for messages, processes commands, and responds with appropriate actions. This guide is focused on helping you run the bot as-is, with minimal setup.

## Quick Start: Run with Docker
Expand All @@ -12,34 +16,39 @@ The easiest way to run Meshtastic Bot is using Docker. This method requires mini
- Create a `.env` file in your project directory with the required environment variables:

```
MESHTASTIC_NODE_IP=your_meshtastic_node_ip
MESHTASTIC_IP=your_meshtastic_node_ip
ADMIN_NODES=comma_separated_admin_node_ids
STORAGE_API_ROOT=your_storage_api_url
STORAGE_API_TOKEN=your_storage_api_token
STORAGE_API_ROOT=https://meshflow.pskillen.xyz
STORAGE_API_TOKEN=your_storage_api_token from above site
# Optionally, you can upload to a second API as well
STORAGE_API_2_ROOT=your_storage_api_2_url
STORAGE_API_2_TOKEN=your_storage_api_2_token

# Feature Toggles
ENABLE_TCP_PROXY=true

# Command Toggles (set to false to disable)
ENABLE_COMMAND_PING=true
ENABLE_COMMAND_TR=true
ENABLE_COMMAND_HELLO=true
ENABLE_COMMAND_HELP=true
ENABLE_COMMAND_NODES=true
ENABLE_COMMAND_WHOAMI=true
ENABLE_COMMAND_PREFS=true
ENABLE_COMMAND_ADMIN=true
ENABLE_COMMAND_STATUS=true
```

### 2. Use This `docker-compose.yaml`

```yaml
version: '3.8'

services:
bot:
image: ghcr.io/pskillen/meshtastic-bot:latest
container_name: meshtastic-bot
restart: unless-stopped
environment:
- MESHTASTIC_IP=${MESHTASTIC_NODE_IP}
- ADMIN_NODES=${ADMIN_NODES}
- STORAGE_API_ROOT=${STORAGE_API_ROOT}
- STORAGE_API_TOKEN=${STORAGE_API_TOKEN}
- STORAGE_API_VERSION=2
- STORAGE_API_2_ROOT=${STORAGE_API_2_ROOT}
- STORAGE_API_2_TOKEN=${STORAGE_API_2_TOKEN}
- STORAGE_API_2_VERSION=2
env_file:
- meshtastic-bot.env
volumes:
- mesh_bot_data:/app/data

Expand All @@ -57,6 +66,46 @@ The bot will now run in the background. Data will be persisted locally in the `m

---

## Customization

You can enable or disable specific features and commands using environment variables in your `.env` or `meshtastic-bot.env` file. All options default to `true` if not specified.

### Feature Toggles
- `ENABLE_TCP_PROXY`: Set to `false` to disable the internal TCP proxy. The bot will connect directly to `MESHTASTIC_IP`.
- `PROXY_HANDSHAKE_CACHE_SIZE`: Number of initial packets to cache for connecting proxy clients (default `100`).
- `PROXY_ROLLING_CACHE_SIZE`: Number of recent packets to cache in a rolling queue for connecting proxy clients (default `100`).

### Command Toggles
Set any of the following to `false` to disable the command and hide it from the `!help` menu:
- `ENABLE_COMMAND_PING`
- `ENABLE_COMMAND_TR`
- `ENABLE_COMMAND_HELLO`
- `ENABLE_COMMAND_HELP`
- `ENABLE_COMMAND_NODES`
- `ENABLE_COMMAND_WHOAMI`
- `ENABLE_COMMAND_PREFS`
- `ENABLE_COMMAND_ADMIN`
- `ENABLE_COMMAND_STATUS`

---

## Docker Compose Options

There are two primary ways to run the bot using Docker:

### 1. Standard (`docker-compose.yaml`) - **Recommended for local builds**
- **Purpose**: Stable use with local source control.
- **How it works**: It builds the bot locally from the source files in the repository.
- **Includes**: Integrated **Watchtower** service which automatically checks for and applies updates to the `meshtastic-bot` container every hour.
- **Environment**: Configuration is pulled from your `.env` file.

### 2. Remote/Pre-built (`docker-compose-remote.yaml`)
- **Purpose**: Quick deployment using the official container.
- **How it works**: Pulls the pre-built image from the **GitHub Container Registry** (`ghcr.io`).
- **Configuration**: Uses `meshtastic-bot.env` for environment variables and a named Docker volume (`mesh_bot_data`) for persistence.

---

## Native Installation (Advanced/Development)

If you prefer to run the bot natively (e.g., for development or customization):
Expand Down Expand Up @@ -85,17 +134,39 @@ If you prefer to run the bot natively (e.g., for development or customization):

## Usage

The bot listens for messages and responds to commands. You can interact with it via supported Meshtastic channels.
The bot listens for messages and responds to commands as a direct message. You can interact with it via supported Meshtastic channels.

### Supported Commands

| Command | Description |
|-----------|------------------------------------------------|
| `!help` | Displays a list of available commands |
| `!hello` | Displays information about the bot |
| `!ping` | Responds with "Pong!" |
| `!nodes` | Displays a list of connected nodes, stats, etc |
| `!whoami` | Displays information about the sender |
| Command | Description |
|-----------|---------------------------------------------------------------|
| `!help` | Displays a list of available commands |
| `!hello` | Displays information about the bot |
| `!ping` | Responds with "Pong!" |
| `!nodes` | Displays a list of connected nodes, stats, etc |
| `!nodes totals` | Manually triggers a node count report |
| `!whoami` | Displays information about the sender |
| `!tr` | Performs a traceroute to the sender (outbound & inbound) |
| `!status` | Displays bot status and radio connection details |

## Features

### Node Count Reporting
The bot monitors mesh visibility and provides automated reporting:
- **Scheduled Reports:** Every 3 hours, a status update is sent to Channel 2 (GregPrivate) with the current online node count.
- **Immediate Alerts:** If the visible node count drops to zero, the bot sends an immediate warning.
- **Manual Check:** Use `!nodes totals` to get an instant report via DM.

### Enhanced Connectivity (TCP Proxy)
The bot now includes a built-in TCP proxy to manage the connection to the Meshtastic node. This improves stability and allows for automatic reconnection if the radio connection is lost.

### Improved Logging
Messages received on named Group Channels (e.g., 'LongRange', 'PrivateChat') are now logged with their specific channel name, making it easier to track conversations across different mesh networks.

### Advanced Traceroute
The `!tr` command has been upgraded to show the full path:
- **Outbound:** The route from the bot to your node.
- **Inbound:** The route back from your node to the bot (if available).

---

Expand Down
16 changes: 16 additions & 0 deletions docker-compose-remote.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#----- Docker Compose.yaml ------
services:
bot:
image: ghcr.io/pskillen/meshtastic-bot:latest
container_name: meshtastic-bot
restart: unless-stopped
ports:
- "4403:4403"
env_file:
- meshtastic-bot.env
volumes:
- ./src:/app/src
- mesh_bot_data:/app/data

volumes:
mesh_bot_data:
37 changes: 26 additions & 11 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,39 @@
---

services:
meshtastic-bot:
image: ghcr.io/pskillen/meshtastic-bot:latest
build:
context: "./"
bot:
build: .
container_name: meshtastic-bot
restart: unless-stopped
ports:
- "4403:4403"
environment:
- MESHTASTIC_IP=meshtastic.local
- ADMIN_NODES='!aae8900d' # Change this, unless you want me to be the admin of your bot
volumes:
- ./data:/app/data
depends_on:
- watchtower
- MESHTASTIC_IP=${MESHTASTIC_IP:-192.168.4.210} # Your Meshtastic Node IP here
- STORAGE_API_ROOT=${STORAGE_API_ROOT}
- STORAGE_API_TOKEN=${STORAGE_API_TOKEN}
- STORAGE_API_VERSION=${STORAGE_API_VERSION}
- ENABLE_TCP_PROXY=${ENABLE_TCP_PROXY:-true}
- ENABLE_FEATURE_NODE_TOTALS=${ENABLE_FEATURE_NODE_TOTALS:-true}
- FREQUENCY_OF_NODE_REPORTS=${FREQUENCY_OF_NODE_REPORTS:-3}
- CHANNEL_FOR_NODE_TOTAL_BROADCAST=${CHANNEL_FOR_NODE_TOTAL_BROADCAST:-2}
- ENABLE_COMMAND_PING=${ENABLE_COMMAND_PING:-true}
- ENABLE_COMMAND_TR=${ENABLE_COMMAND_TR:-true}
- ENABLE_COMMAND_HELLO=${ENABLE_COMMAND_HELLO:-true}
- ENABLE_COMMAND_HELP=${ENABLE_COMMAND_HELP:-true}
- ENABLE_COMMAND_NODES=${ENABLE_COMMAND_NODES:-true}
- ENABLE_COMMAND_WHOAMI=${ENABLE_COMMAND_WHOAMI:-true}
- ENABLE_COMMAND_PREFS=${ENABLE_COMMAND_PREFS:-true}
- ENABLE_COMMAND_ADMIN=${ENABLE_COMMAND_ADMIN:-true}
- ENABLE_COMMAND_STATUS=${ENABLE_COMMAND_STATUS:-true}
labels:
- "com.centurylinklabs.watchtower.enable=false"

watchtower:
image: containrrr/watchtower
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 3600 meshtastic-bot # Check for updates every hour
environment:
- DOCKER_API_VERSION=1.44
command: --interval 3600 --label-enable
15 changes: 15 additions & 0 deletions find_node.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import sqlite3
import sys

try:
conn = sqlite3.connect('/app/data/node_db.sqlite')
cursor = conn.cursor()
cursor.execute("SELECT long_name, short_name, id FROM nodes WHERE short_name LIKE '%mte4%' OR long_name LIKE '%mte4%'")
rows = cursor.fetchall()
if not rows:
print("No node found with 'mte4' in name.")
for row in rows:
print(f"Found: {row}")
conn.close()
except Exception as e:
print(f"Error: {e}")
Loading