{"_id":"@andyshinn/n8n-nodes-meshcore-ts","name":"@andyshinn/n8n-nodes-meshcore-ts","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@andyshinn/n8n-nodes-meshcore-ts","version":"0.1.0","description":"n8n community node for MeshCore radios over BLE, serial, and TCP","keywords":["n8n-community-node-package","n8n","meshcore","lora","meshtastic","ble","serial"],"license":"MIT","homepage":"https://github.com/andyshinn/n8n-nodes-meshcore-ts","author":{"name":"Andy Shinn"},"repository":{"type":"git","url":"git+https://github.com/andyshinn/n8n-nodes-meshcore-ts.git"},"engines":{"node":">=22"},"n8n":{"n8nNodesApiVersion":1,"credentials":["dist/credentials/MeshCoreApi.credentials.js"],"nodes":["dist/nodes/MeshCore/MeshCore.node.js","dist/nodes/MeshCoreTrigger/MeshCoreTrigger.node.js"]},"dependencies":{"@andyshinn/meshcore-ts":"^0.3.0"},"optionalDependencies":{"@stoprocent/noble":"^2.5.5","serialport":"^13.0.0"},"peerDependencies":{"n8n-workflow":"*"},"devDependencies":{"@types/node":"^22.10.0","@typescript-eslint/parser":"^8.18.0","eslint":"^8.57.0","eslint-plugin-n8n-nodes-base":"^1.16.3","n8n-workflow":"*","prettier":"^3.4.0","rimraf":"^6.0.0","typescript":"^5.7.0","vitest":"^2.1.0"},"scripts":{"build":"rimraf dist && tsc && node scripts/copy-icons.mjs","dev":"tsc --watch","lint":"eslint --no-error-on-unmatched-pattern nodes credentials package.json","lint:fix":"eslint --no-error-on-unmatched-pattern nodes credentials package.json --fix","format":"prettier --write nodes credentials src","test":"vitest run","test:watch":"vitest"},"_id":"@andyshinn/n8n-nodes-meshcore-ts@0.1.0","bugs":{"url":"https://github.com/andyshinn/n8n-nodes-meshcore-ts/issues"},"_integrity":"sha512-ge+oeamCl42cNZpPtrWvuVmUC1GgxUBlRBQEyeUG7c0m8XMkrxKOis9a++GdHTf5ZFmpkw1XaR9Gz8Z/ieW1QA==","_resolved":"/private/var/folders/hm/5tzdggxs72s_3h50x_vg4bpr0000gn/T/9e8f497deaa0ae7934b1219874c324e1/andyshinn-n8n-nodes-meshcore-ts-0.1.0.tgz","_from":"file:andyshinn-n8n-nodes-meshcore-ts-0.1.0.tgz","_nodeVersion":"26.3.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-ge+oeamCl42cNZpPtrWvuVmUC1GgxUBlRBQEyeUG7c0m8XMkrxKOis9a++GdHTf5ZFmpkw1XaR9Gz8Z/ieW1QA==","shasum":"67c2b621d70096e67089ed9fd23da295a3fa978a","tarball":"https://registry.npmjs.org/@andyshinn/n8n-nodes-meshcore-ts/-/n8n-nodes-meshcore-ts-0.1.0.tgz","fileCount":52,"unpackedSize":80584,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCVCWMvm8ZeskcxJMIW6aqOcP3x131RcdW+GVUw3WkFpAIgHjCScdh5+zY5G88olPHlRR413Ezu0JT8mJ9deU2cC8k="}]},"_npmUser":{"name":"andyshinn","email":"andys+npm@andyshinn.as"},"directories":{},"maintainers":[{"name":"andyshinn","email":"andys+npm@andyshinn.as"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/n8n-nodes-meshcore-ts_0.1.0_1781899822038_0.18228838324131424"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-19T20:10:21.780Z","0.1.0":"2026-06-19T20:10:22.187Z","modified":"2026-06-19T20:10:22.399Z"},"maintainers":[{"name":"andyshinn","email":"andys+npm@andyshinn.as"}],"description":"n8n community node for MeshCore radios over BLE, serial, and TCP","homepage":"https://github.com/andyshinn/n8n-nodes-meshcore-ts","keywords":["n8n-community-node-package","n8n","meshcore","lora","meshtastic","ble","serial"],"repository":{"type":"git","url":"git+https://github.com/andyshinn/n8n-nodes-meshcore-ts.git"},"author":{"name":"Andy Shinn"},"bugs":{"url":"https://github.com/andyshinn/n8n-nodes-meshcore-ts/issues"},"license":"MIT","readme":"# n8n-nodes-meshcore-ts\n\nAn [n8n](https://n8n.io) community node package for controlling and listening to [MeshCore](https://github.com/ripplebiz/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`](https://www.npmjs.com/package/@andyshinn/meshcore-ts) library.\n\n## Important: Self-Hosted Only\n\nThis package uses native Node.js addons (`@stoprocent/noble` for BLE, `serialport` for serial). Because of these native dependencies it:\n\n- **Cannot run on n8n Cloud**\n- **Is not eligible for the n8n Verified Community Nodes program**\n- **Requires a self-hosted n8n instance** running on a machine with direct radio access\n\n## Installation\n\n### Community Nodes UI (recommended for self-hosted)\n\n1. In n8n, go to **Settings → Community Nodes**\n2. Click **Install**\n3. Enter `@andyshinn/n8n-nodes-meshcore-ts`\n4. Click **Install**\n\n### npm / manual\n\n```bash\nnpm install @andyshinn/n8n-nodes-meshcore-ts\n```\n\nThen restart n8n so it picks up the new package.\n\n## Native Dependency Installation\n\nDepending on your transport, you may need to install additional native packages into your n8n environment:\n\n| Transport | Extra package required |\n|-----------|----------------------|\n| TCP / WiFi | None — works out of the box |\n| Serial (USB) | `npm install serialport` |\n| BLE (Bluetooth LE) | `npm install @stoprocent/noble` |\n\n### Linux BLE prerequisites\n\nBLE scanning on Linux requires the Bluetooth development headers and a raw-socket capability grant on the `node` binary:\n\n```bash\n# Install Bluetooth headers (Debian/Ubuntu)\nsudo apt-get install libbluetooth-dev\n\n# Grant raw-socket capability so Node can open HCI sockets without root\nsudo setcap cap_net_raw+eip $(readlink -f $(which node))\n```\n\n### BLE must be OS-paired first\n\nBefore 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.\n\n## Single-Process Recommendation\n\nThe 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.\n\nFor BLE and Serial, which are exclusive resources, you should either:\n\n- Run n8n in **main-process mode** (default single-process) instead of queue mode, or\n- Pin all MeshCore workflows to a single worker using n8n's routing tags\n\nTCP connections are generally not exclusive, but radio-side connection limits still apply.\n\n---\n\n## Credentials\n\n> The credential documentation URL links to this section: `#credentials`\n\nCreate a **MeshCore API** credential and configure the following fields:\n\n### Transport\n\n| Value | Description |\n|-------|-------------|\n| `tcp` | TCP / WiFi — connects to a MeshCore companion radio over TCP |\n| `serial` | Serial (USB) — connects via a USB-serial port |\n| `ble` | BLE — connects via Bluetooth LE (requires OS pairing first) |\n\n### TCP fields (shown when Transport = TCP)\n\n| Field | Default | Description |\n|-------|---------|-------------|\n| Host | _(required)_ | IP address or hostname of the radio |\n| Port | `5000` | TCP port the radio listens on |\n\n### Serial fields (shown when Transport = Serial)\n\n| Field | Default | Description |\n|-------|---------|-------------|\n| Serial Path | _(required)_ | Device path, e.g. `/dev/ttyUSB0` or `COM3` |\n| Baud Rate | `115200` | Serial baud rate |\n\n### BLE fields (shown when Transport = BLE)\n\n| Field | Default | Description |\n|-------|---------|-------------|\n| Device Address | _(optional)_ | BLE MAC address or UUID. Leave blank to match by name. |\n| Device Name | _(optional)_ | Advertised local name. Leave blank to connect to the first MeshCore device found. |\n| Scan Timeout (ms) | `15000` | How long to scan before giving up |\n\n### Shared fields\n\n| Field | Default | Description |\n|-------|---------|-------------|\n| App Name | `n8n-nodes-meshcore` | Identifies this client to the radio during the handshake |\n\n---\n\n## Nodes\n\n### MeshCore Trigger\n\n**Starts a workflow** when the radio emits events.\n\nAdd this node as the first node in any workflow that should react to radio activity.\n\n#### Events\n\n| Event | Description |\n|-------|-------------|\n| `messages` | Incoming direct messages and channel messages |\n| `contacts` | Lightweight contact list update (public keys + names) |\n| `contactsFull` | Full contact list update including all metadata |\n| `contactDiscovered` | A new contact was discovered by the radio |\n| `contactEvicted` | A contact was removed from the radio's list |\n| `discovered` | A new device was discovered via mesh advertisement |\n| `channels` | Channel list updated |\n| `messageState` | Delivery/acknowledgment state change for a sent message |\n| `owner` | Radio owner info updated |\n| `transportState` | Underlying transport connected or disconnected |\n\nEach trigger item has the following shape:\n\n```json\n{\n  \"event\": \"messages\",\n  \"data\": { \"key\": \"c:<pubkeyhex>\", \"messages\": [ /* Message[] */ ] },\n  \"receivedAt\": \"2026-06-19T12:34:56.789Z\",\n  \"connection\": { \"transport\": \"tcp\", \"id\": \"<connection key>\" }\n}\n```\n\n- `event` — the library event name (e.g. `messages`, `contactDiscovered`)\n- `data` — the event payload (shape depends on the event; for `messages` it is `{ key, messages }` where `key` is the contact/channel key)\n- `receivedAt` — ISO-8601 timestamp the item was emitted\n- `connection.transport` — `tcp` | `serial` | `ble`\n- `connection.id` — the stable connection key identifying the radio\n\n### MeshCore (action node)\n\n**Sends commands to the radio** and returns the result.\n\nSupports three resources:\n\n#### Message\n\n| Operation | Description |\n|-----------|-------------|\n| Send Direct Message | Send a DM to a contact by public-key (`c:<hex>`). Optionally wait for delivery acknowledgment. |\n| Send Channel Message | Send a message to a channel by key (`ch:<name>`). |\n\n#### Contact\n\n| Operation | Description |\n|-----------|-------------|\n| List | Return all contacts known to the radio |\n| Get | Get a single contact by public-key hex |\n| Add | Add a contact to the radio by public-key hex |\n| Remove | Remove a contact from the radio by public-key hex |\n\n#### Device\n\n| Operation | Description |\n|-----------|-------------|\n| Get Info | Return device info (firmware version, node number, etc.) |\n| Set Advert Name | Change the radio's advertised name |\n| Send Advert | Broadcast a self-advertisement (flood or zero-hop) |\n| Reboot | Reboot the radio |\n\n---\n\n## Example Workflow: Incoming DM → Reply\n\nThis is the simplest useful workflow you can build with this package.\n\n1. **MeshCore Trigger** — credential: your radio, events: `messages`\n2. **IF** node — condition: `{{ $json.data.key.startsWith(\"c:\") }}` (filter out channel messages, keep DMs)\n3. **MeshCore** node — Resource: Message, Operation: Send Direct Message\n   - Contact Key: `={{ $json.data.key }}` (the DM contact key from the incoming `messages` event)\n   - Text: `Thanks for your message! You said: {{ $json.data.messages[$json.data.messages.length - 1].body }}. Received at {{ $json.receivedAt }}.`\n\nWhen 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.\n\n---\n\n## License\n\nMIT — see [LICENSE](./LICENSE).\n\n## Contributing\n\nIssues and pull requests welcome at <https://github.com/andyshinn/n8n-nodes-meshcore-ts>.\n","readmeFilename":"README.md","_rev":"1-5a3e19aebced7708bc9b88463dd7d9dc"}