@andyshinn/n8n-nodes-meshcore-ts
v0.1.0
Published
n8n community node for MeshCore radios over BLE, serial, and TCP
Maintainers
Readme
n8n-nodes-meshcore-ts
An n8n community node package for controlling and listening to MeshCore LoRa radios from n8n workflows. It bridges MeshCore companion radios over BLE (Bluetooth LE), Serial (USB), and TCP / WiFi using the @andyshinn/meshcore-ts library.
Important: Self-Hosted Only
This package uses native Node.js addons (@stoprocent/noble for BLE, serialport for serial). Because of these native dependencies it:
- Cannot run on n8n Cloud
- Is not eligible for the n8n Verified Community Nodes program
- Requires a self-hosted n8n instance running on a machine with direct radio access
Installation
Community Nodes UI (recommended for self-hosted)
- In n8n, go to Settings → Community Nodes
- Click Install
- Enter
@andyshinn/n8n-nodes-meshcore-ts - Click Install
npm / manual
npm install @andyshinn/n8n-nodes-meshcore-tsThen restart n8n so it picks up the new package.
Native Dependency Installation
Depending on your transport, you may need to install additional native packages into your n8n environment:
| Transport | Extra package required |
|-----------|----------------------|
| TCP / WiFi | None — works out of the box |
| Serial (USB) | npm install serialport |
| BLE (Bluetooth LE) | npm install @stoprocent/noble |
Linux BLE prerequisites
BLE scanning on Linux requires the Bluetooth development headers and a raw-socket capability grant on the node binary:
# Install Bluetooth headers (Debian/Ubuntu)
sudo apt-get install libbluetooth-dev
# Grant raw-socket capability so Node can open HCI sockets without root
sudo setcap cap_net_raw+eip $(readlink -f $(which node))BLE must be OS-paired first
Before n8n can connect to a BLE radio, the radio must be paired and bonded at the OS level (including PIN entry). On Linux use bluetoothctl, on macOS use System Settings → Bluetooth. n8n / this package does not initiate pairing — it only connects to already-bonded devices.
Single-Process Recommendation
The shared connection manager that this package uses to multiplex the connection between the Trigger and action nodes is per-process. If you run multiple n8n worker processes (e.g., with the queue mode worker command), each process will open its own physical connection to the radio.
For BLE and Serial, which are exclusive resources, you should either:
- Run n8n in main-process mode (default single-process) instead of queue mode, or
- Pin all MeshCore workflows to a single worker using n8n's routing tags
TCP connections are generally not exclusive, but radio-side connection limits still apply.
Credentials
The credential documentation URL links to this section:
#credentials
Create a MeshCore API credential and configure the following fields:
Transport
| Value | Description |
|-------|-------------|
| tcp | TCP / WiFi — connects to a MeshCore companion radio over TCP |
| serial | Serial (USB) — connects via a USB-serial port |
| ble | BLE — connects via Bluetooth LE (requires OS pairing first) |
TCP fields (shown when Transport = TCP)
| Field | Default | Description |
|-------|---------|-------------|
| Host | (required) | IP address or hostname of the radio |
| Port | 5000 | TCP port the radio listens on |
Serial fields (shown when Transport = Serial)
| Field | Default | Description |
|-------|---------|-------------|
| Serial Path | (required) | Device path, e.g. /dev/ttyUSB0 or COM3 |
| Baud Rate | 115200 | Serial baud rate |
BLE fields (shown when Transport = BLE)
| Field | Default | Description |
|-------|---------|-------------|
| Device Address | (optional) | BLE MAC address or UUID. Leave blank to match by name. |
| Device Name | (optional) | Advertised local name. Leave blank to connect to the first MeshCore device found. |
| Scan Timeout (ms) | 15000 | How long to scan before giving up |
Shared fields
| Field | Default | Description |
|-------|---------|-------------|
| App Name | n8n-nodes-meshcore | Identifies this client to the radio during the handshake |
Nodes
MeshCore Trigger
Starts a workflow when the radio emits events.
Add this node as the first node in any workflow that should react to radio activity.
Events
| Event | Description |
|-------|-------------|
| messages | Incoming direct messages and channel messages |
| contacts | Lightweight contact list update (public keys + names) |
| contactsFull | Full contact list update including all metadata |
| contactDiscovered | A new contact was discovered by the radio |
| contactEvicted | A contact was removed from the radio's list |
| discovered | A new device was discovered via mesh advertisement |
| channels | Channel list updated |
| messageState | Delivery/acknowledgment state change for a sent message |
| owner | Radio owner info updated |
| transportState | Underlying transport connected or disconnected |
Each trigger item has the following shape:
{
"event": "messages",
"data": { "key": "c:<pubkeyhex>", "messages": [ /* Message[] */ ] },
"receivedAt": "2026-06-19T12:34:56.789Z",
"connection": { "transport": "tcp", "id": "<connection key>" }
}event— the library event name (e.g.messages,contactDiscovered)data— the event payload (shape depends on the event; formessagesit is{ key, messages }wherekeyis the contact/channel key)receivedAt— ISO-8601 timestamp the item was emittedconnection.transport—tcp|serial|bleconnection.id— the stable connection key identifying the radio
MeshCore (action node)
Sends commands to the radio and returns the result.
Supports three resources:
Message
| Operation | Description |
|-----------|-------------|
| Send Direct Message | Send a DM to a contact by public-key (c:<hex>). Optionally wait for delivery acknowledgment. |
| Send Channel Message | Send a message to a channel by key (ch:<name>). |
Contact
| Operation | Description | |-----------|-------------| | List | Return all contacts known to the radio | | Get | Get a single contact by public-key hex | | Add | Add a contact to the radio by public-key hex | | Remove | Remove a contact from the radio by public-key hex |
Device
| Operation | Description | |-----------|-------------| | Get Info | Return device info (firmware version, node number, etc.) | | Set Advert Name | Change the radio's advertised name | | Send Advert | Broadcast a self-advertisement (flood or zero-hop) | | Reboot | Reboot the radio |
Example Workflow: Incoming DM → Reply
This is the simplest useful workflow you can build with this package.
- MeshCore Trigger — credential: your radio, events:
messages - IF node — condition:
{{ $json.data.key.startsWith("c:") }}(filter out channel messages, keep DMs) - MeshCore node — Resource: Message, Operation: Send Direct Message
- Contact Key:
={{ $json.data.key }}(the DM contact key from the incomingmessagesevent) - Text:
Thanks for your message! You said: {{ $json.data.messages[$json.data.messages.length - 1].body }}. Received at {{ $json.receivedAt }}.
- Contact Key:
When a DM arrives at the radio, n8n fires the trigger, the IF node confirms it is a direct message, and the action node sends the auto-reply back to the original sender.
License
MIT — see LICENSE.
Contributing
Issues and pull requests welcome at https://github.com/andyshinn/n8n-nodes-meshcore-ts.
