-
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 available to your Crow node, either over the network or attached by USB.
For current Crow builds, the recommended MeshCore integration is the MeshCore Companion binary API. Crow can use the same Companion message backend over:
- TCP to a network-reachable MeshCore endpoint, normally port
4403. - USB serial through
/dev/ttyACM0or/dev/ttyUSB0.
This is a binary framed protocol, not a line-oriented command console. Crow
sends the Companion startup frame, receives device self-info, drains queued
messages after 0x83 message-waiting notifications, and sends text through the
same backend.
KISS is not the MeshCore Companion protocol. Crow's kiss_tcp mode is
APRS/AX.25 support and should not be used for MeshCore Companion traffic.
Add or edit the top-level configuration in /etc/crow.conf.override.
Restart Crow after changing configuration.
Use TCP when the Companion API is reachable over the network:
{
"meshcore": { "backend": "tcp" },
"meshcore_tcp_api": {
"enabled": true,
"host": "192.168.4.1",
"port": 4403,
"max_pending_rx": 4,
"channel_discovery": true,
"channel_refresh_seconds": 600
}
}Use the MeshCore device or Companion API bridge IP for host, not the Crow
node IP. The default Companion TCP port is 4403; do not use Crow's
WebSocket/UI port for this setting.
Use serial when the MeshCore node is physically attached to the Crow host:
{
"meshcore": { "backend": "serial" },
"meshcore_serial_api": {
"enabled": true,
"device": "/dev/ttyACM0",
"baud": 115200,
"app_start_profile": "meshcore_cli",
"max_pending_rx": 4,
"channel_discovery": false,
"channel_slots": {
"0": "MeshCore izOH6cXN6mrJ5e26oRXNcg=="
}
}
}/dev/ttyUSB0 is also supported. meshcore_usb_api is accepted as an alias
for meshcore_serial_api.
TCP is preferred when TCP and serial are both enabled without an explicit
selector. Set meshcore.backend to serial to force USB.
Accepted explicit selectors are:
TCP: api, tcp, tcp-api, companion-api
USB: serial, serial-api, usb, usb-api
UDP: udp
A channel entry by itself does not enable a MeshCore backend; one of the transport configurations above is also required.
The built-in MeshCore public channel is:
MeshCore izOH6cXN6mrJ5e26oRXNcg==
It uses MeshCore channel slot 0 and is created automatically by Crow. To use
a custom MeshCore channel, configure the same name/key in Crow and MeshCore.
TCP can use channel_discovery to inspect slots on the radio. USB serial uses
explicit slot mapping.
If a custom slot cannot be resolved from discovery, provide an optional map:
{
"meshcore_tcp_api": {
"enabled": true,
"host": "192.168.4.1",
"channel_slots": {
"2": "MeshTalk AQ=="
}
}
}The map is slot number to exact Crow channel namekey. For USB serial, place
the same mapping under meshcore_serial_api. Serial uses explicit mapping and
does not load the optional TCP discovery scanner.
The TCP and USB serial paths share the same framed Companion parser and group TX/RX implementation.
Crow receives:
- direct messages delivered to the connected MeshCore node;
- public and custom channel messages from mapped MeshCore slots;
- queued messages drained after
0x83message-waiting notifications.
Crow sends:
- channel text with Companion command
0x03; - direct text with Companion command
0x02on TCP, when the recipient public-key prefix is known.
TCP direct replies require Crow to learn the target MeshCore public-key prefix from a prior inbound direct message. If the prefix is not known, Crow fails the direct send safely. Native USB serial direct send is intentionally disabled; group text remains bidirectional.
Useful status counters include:
pending_rx
message_waiting
sync_requests
no_more_messages
channel_sends_ok
channel_sends_failed
direct_sends_ok
direct_sends_failed
outbound_group_sent
outbound_group_rejected
outbound_confirmed
radio_errors
Restart Crow:
/etc/init.d/crow restartFor TCP, confirm the MeshCore endpoint is reachable:
nc -zv 192.168.4.1 4403Check startup logs:
logread | grep -E 'meshcore_backend|meshcore_tcp_api|meshcore_serial_api'Expected startup output includes selected tcp backend or selected serial backend, followed by a successful Companion handshake.
Send a unique message from another MeshCore node on the public channel. The message should appear in Crow. Then send a message from Crow on the public channel and verify that a second MeshCore node receives it.
Crow has been field-tested on AREDN Hub5 and BaseBox5 nodes. MeshCore USB
testing used a RAKwireless WisCore RAK4631 attached at /dev/ttyACM0; TCP
Companion testing used a network-reachable MeshCore endpoint.
The v0.0.2-r21140793 APK was upgraded live on Hub5 and BB5MC on 2026-09-02.
Both nodes preserved their configuration checksums and recovered Crow, the
watchdog, HTTP UI, and APRS/Xastir connections. Their Companion endpoints
connected and then closed without returning frames, so that deployment is not
a current-release handshake or RF-delivery proof.
The last successful USB protocol handshake was the following historical test
on 2026-08-25 on KJ6DZB-WSB-hub5 (AREDN 4.26.7.0):
- Source:
main, commit4eea321. - The attached RAK USB Companion radio enumerates as a RAKwireless WisCore
RAK4631 (
239a:8029) at/dev/ttyACM0. - Hub5 required the matching USB host/CDC drivers (
kmod-usb2,kmod-usb-acm,kmod-usb-dwc3,kmod-usb-dwc3-qcom, andkmod-usb3). - AREDN's minimal image omits
stty, so Crow's packaged staticcrow-rawttyhelper applies persistent 115200/raw termios settings. This was verified independently before Crow was restarted. - Crow selects the direct serial backend, opens
/dev/ttyACM0, sendsCMD_APP_START, and receivesRESP_SELF_INFOfrom the radio, identified asKJ6DZB-Crow. - At that commit,
CMD_GET_CHANNELdiscovery was verified on slots 0–7. The radio reports only thePublicgroup in slot 0; no matching configured Crow group channel was found or imported automatically. - Host-side protocol tests passed: serial Companion tests (57), TCP Companion tests (51), backend-selection checks, and router/gatekeeper matrix checks.
- That
mainintegration repeated the USB Companion handshake successfully before its publication. Current serial releases instead use explicit slot mappings and do not load the TCP discovery scanner.
Group receive, group transmit, and over-air delivery are still pending.
Before enabling transmit, explicitly configure the same group name/key in both
Crow and the radio, then bind Crow's tx_channel_index to the discovered
radio slot. Crow deliberately does not persist a key discovered from the radio
or select a transmit channel automatically. Direct messages and GPS were not
tested in this validation.
For developer-level protocol tests, see the main repository docs and run:
node tests/run_meshcore_tcp_api_tests.jsWhen TCP channel_discovery is enabled, Crow queries MeshCore channel slots with
CMD_GET_CHANNEL (0x1F) after startup and on the refresh timer.
Discovery is runtime-only. It helps Crow resolve MeshCore slots and inspect the radio's channel state, but it does not persist channel secrets or overwrite operator-managed configuration. USB serial uses the explicit slot mapping described above instead.
Once a channel is available, join it with:
/join #TacNet key=your-passphrase
See Commands for command details and Configuring Channels for channel setup.
The older MeshCore2Net/UDP path remains available for deployments that already use it. New installs should prefer the Companion TCP or USB serial backend above.
Building an AREDN to MeshCore hardware bridge is more involved than the Meshtastic bridge. By default, MeshCore does not provide Ethernet access, but the official firmware can send and receive packets through the serial port on a MeshCore node. See https://github.com/meshcore-dev/MeshCore.
These instructions use the WisBlock system: the WisBlock Base (RAK19007) and the WisBlock Core (RAK4631). This device has a serial port available and is powered and programmed over USB. A Raspberry Pi can support remote programming and configuration over USB, plus serial packet forwarding.

The picture above shows the Raspberry Pi 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.
The MeshCore node must be configured first. The Python tools are available at https://github.com/meshcore-dev/meshcore-cli.
After configuration, retrieve the node's public key:
meshcli -s /dev/ttyACM0 -r get public.keyTo copy MeshCore packets between the MeshCore node and the local network, the Raspberry Pi must run bridge software. The historical bridge is https://github.com/kn6plv/MeshCore2Net.
Install NodeJS using the official instructions at https://github.com/nvm-sh/nvm#installing-and-updating, then install the bridge:
cd /root
git clone https://github.com/kn6plv/MeshCore2Net.git
cd MeshCore2Net
./install.shAssuming everything goes well, the bridge will run as a service after reboot.
- Configuration - MeshCore bridge configuration.
- Configuring Channels - channel setup and backend selection.
-
Commands -
/cmd discover,/cmd info, and/join. - Strict Gatekeeper - callsign and access-control behavior.