-
Notifications
You must be signed in to change notification settings - Fork 0
MeshCore
You should only enable the MeshCore bridge if you have an appropriate MeshCore device connected to the LAN interface on your Crow node.
Building an AREDN to MeshCore hardware bridge is, unfortunately, more involved than the Meshtastic bridge. By default, MeshCore does not provide any form of ethernet access. However, the official firmware (see https://github.com/meshcore-dev/MeshCore) does provide an option to receive and send packets via the serial port on a MeshCore node. This is what we will use to bridge to AREDN. (We are aware of pyMC_core as another alternative, but we want to use the official MeshCore firmware.)
These instructions use the WisBlock system; specifically the WisBlock Base (RAK19007) and the WisBlock Core (RAK4631) contains a pre-soldered RAK4630 (we specifically purchased this https://store.rokland.com/products/rak-wireless-wisblock-meshtastic-starter-kit which is sold for Meshtastic, but works fine for our purposes). This devices has a serial port available and is power and programmed over USB. We also use a Raspberry Pi to support bother remote programming and configuration support (via USB) of the MeshCore devices, as well as connecting to the serial port to send and receive MeshCore packets.

The picture above shows the Raspberry Pi (hidden under a PoE HAT) connected to the WisBlock boards via a USB cable and 3-wire ribbon serial cable. The PoE HAT allows powering and communicating with the board over a single ethernet cable.
... TODO ...
The MeshCore node must be configure. We use the Python tools to do this; see https://github.com/meshcore-dev/meshcore-cli. We will not go into detail on how to configure a MeshCore node; there are plenty of better places to learn about that.
After configuration we need to retrieve the node's public key which we will need later. You can do this with the following command:
meshcli -s /dev/ttyACM0 -r get public.key
To copy MeshCore packets between the MeshCore node and the local network, the Raspberry Pi must run a Bridge application. The current version is available here https://github.com/kn6plv/MeshCore2Net and is written in JavaScript to run on NodeJS.
The are various ways you might install NodeJS on the Raspberry Pi, but we want to use the official instruction here - https://github.com/nvm-sh/nvm#installing-and-updating
Please run these as root so NodeJS is installed in the correct location for the bridge service to find it.
Before installing and running the bridge make sure you have successfully install NodeJS following the instructions above. You will also need to have installed git.
Now, to install and run the bridge, follow these steps:
cd /root
git clone https://github.com/kn6plv/MeshCore2Net.git
cd MeshCore2Net
./install.sh
Assuming everything goes well, the bridge will now be running, and will run as a service even after a reboot.
To enable the MeshCore bridge, add the configuration shown in Configuration — MeshCore Bridge.
As a quick reference, you'll add the "meshcore": {} key to enable the bridge.
Crow will then receive MeshCore traffic from the MeshCore device connected to the node's LAN network and forward traffic to the same MeshCore device when necessary.
Crow includes a meshcore_tcp_api backend that connects directly via TCP to a MeshCore device's Companion API (port 4403). This backend now includes full auto-channel discovery (Phase 2 implementation).
Phase 1: Group Message Reception ✅
- ✅ TCP connection and Companion Protocol (MeshMonitor-compatible)
- ✅ Frame detection (0x07 direct, 0x08 group, 0x82 skip)
- ✅ Message routing to Crow's router (strict Gatekeeper filtering)
- ✅ Slot-based channel identification (8 max channels)
Phase 2: Auto-Channel Discovery ✅ (NEW — 2026-06-20)
- ✅ Automatic detection of channels programmed on the radio
- ✅ Queries radio's 8 memory slots (0-7) using CMD_GET_CHANNEL (0x1F)
- ✅ Parses PACKET_CHANNEL_INFO (0x12) responses (50 bytes each)
- ✅ Auto-creates Crow channels from discovered groups
- ✅ Periodic sync every 5 minutes (configurable)
- ✅ Change detection:
- Detects new channels programmed into the radio
- Detects deleted channels (slots cleared)
- Detects renamed channels
- Detects key rotations (AES secret changes)
Phase 3: AREDN Bridging ✅
- ✅ Group message tagging for FCC Part 97 compliance
- ✅ Format:
[CALLSIGN@MCGW-GroupName via GW] - ✅ Audit logging of all group→AREDN bridges
Phase 4: Discovery UI & Access Control ✅
- ✅
/cmd discover— List auto-discovered MeshCore groups - ✅
/cmd info <namekey>— Show channel details - ✅
/join #name key=passphrase— One-shot channel join (SHA-256) - ✅ Per-channel callsign ACLs (allow/deny lists, wildcards)
- ✅ Weak-identity enforcement for group messages
When Crow boots with MeshCore TCP enabled:
- Connects to MeshCore device (Companion API, port 4403)
- Sends CMD_GET_CHANNEL (0x1F) query for each slot 0-7
- Receives PACKET_CHANNEL_INFO (0x12) responses
- Parses channel name, secret key, and configuration status
- Auto-creates Crow channels for each active group
- Logs discovery results
Example: Radio has "TacNet" and "Emergency" in slots 0-1
→ /cmd discover
✓ MeshCore Groups (auto-discovered):
• TacNet (slot 0, 16-byte key)
• Emergency (slot 1, 16-byte key)
Crow re-queries the radio to detect changes:
- Compares current discovery against previous state
- NEW: Alerts if user added a channel to the radio
- DELETED: Marks channel as deprecated if removed from radio
- RENAMED: Updates channel name in Crow
- KEY ROTATION: Alerts user if channel's secret key changed
Example: User programs "TacNet2" in slot 2 on the radio
Crow detects:
✓ NEW group: TacNet2 (slot 2)
✓ Auto-creates channel in Crow
✓ Logs: "NEW group detected: slot 2, name=TacNet2"
Enable auto-discovery in Configuration.md (meshcore_discovery section):
"meshcore_discovery": {
"enabled": true,
"sync_interval_ms": 300000 // 5 minutes (default)
}For full configuration details, see Configuration — MeshCore TCP API.
Once a channel is auto-discovered, join it with:
/join #TacNet key=your-passphrase
Crow will:
- Derive the channel's symmetric key from your passphrase (SHA-256)
- Join the channel
- Display a channel namekey for reference
See Commands.md for details.
- FCC Part 97: Group messages tagged with weak-identity format
- Callsign Enforcement: Two-layer gatekeeper (global + per-channel)
- Key Derivation: SHA-256 from passphrase (one-shot, not stored)
-
Wildcard ACLs: Support patterns like
K*,*DZB, exact matches
| Component | Status | Details |
|---|---|---|
| Frame detection | ✅ | 0x07, 0x08, 0x82 types |
| TCP handshake | ✅ | HELLO only (no SUBSCRIBE) |
| Slot querying | ✅ | CMD_GET_CHANNEL (0x1F) |
| Response parsing | ✅ | PACKET_CHANNEL_INFO parser |
| Empty slot detection | ✅ | is_configured logic |
| Periodic sync | ✅ | 5-min interval |
| Change detection | ✅ | New/deleted/renamed/key rotation |
| Auto-channel creation | ✅ | Integration with channel.uc |
| /cmd discover | ✅ | Lists groups |
| /cmd info | ✅ | Channel details |
| /join key= | ✅ | One-shot join |
| Per-channel ACL | ✅ | Wildcard patterns |
| AREDN tagging | ✅ | [CALL@MCGW-Group via GW] |
All 4 phases complete and tested. Ready for device validation.
Week 1 (Testing):
- Device testing of frame detection and routing
- Verify auto-discovery on real MeshCore radio
- Validate periodic sync and change detection
Week 2 (Deployment):
- Full integration testing
- AREDN bridging validation
- Production deployment
-
Commands.md —
/cmd discover,/cmd info,/join - Configuration.md — meshcore_discovery config
- Strict-Gatekeeper.md — Per-channel ACL patterns
- Configuring-Channels.md — Channel management
- Home
- Change Log
- Configuration
- Configuring Channels
- Backend Selection and Test Deployment
- Command Reference
- APRS Bridge
- LoRa Gateway Tags
- Meshtastic API Backend
- Memory Use
- Strict Gatekeeper
- Winlink
- USB Storage
APRS.mdBackend-Selection-and-Deployment.mdChange-Log.mdCommand-Reference.mdConfiguration.mdConfiguring-Channels.mdHome.mdLoRa-Gateway-Tags.mdMeshtastic-API.mdMemory-Use.mdStrict-Gatekeeper.mdUSB-Storage.mdWinlink.md_Sidebar.md
- Keep every
.mdwiki page linked here. - Keep
Home.mdand_Sidebar.mdin sync. - When a wiki page is removed, remove it from both the Home page inventory and this sidebar.