{"_id":"signalk-beluga-core","_rev":"8-da5b16796414b51724d7e774b687e13f","name":"signalk-beluga-core","dist-tags":{"latest":"0.2.2"},"versions":{"0.1.0":{"name":"signalk-beluga-core","version":"0.1.0","keywords":["signalk-node-server-plugin","signalk-category-hardware","signalk-category-ais","orca"],"author":{"name":"matztam"},"license":"AGPL-3.0-only","_id":"signalk-beluga-core@0.1.0","maintainers":[{"name":"matztam","email":"npm2026@afke.eu"}],"homepage":"https://github.com/matztam/signalk-beluga-core","bugs":{"url":"https://github.com/matztam/signalk-beluga-core/issues"},"dist":{"shasum":"b56df7fc4e3789a5c8e363dfcc07a8149008ae77","tarball":"https://registry.npmjs.org/signalk-beluga-core/-/signalk-beluga-core-0.1.0.tgz","fileCount":10,"integrity":"sha512-Qv9NU44TFwLzNGpF8IPL20KdXKGomDFou8TXhCsp1Tw8JrpIVkeyqLS8YmqzzaMEP1YPsSTxo/KdfFIoLjDSEA==","signatures":[{"sig":"MEYCIQCQyA4N6SDYGvF9baCW3enqrzbVyKNDB7VO1f501do+3AIhANa8WIxnNOym5daOyxjznKn5wsXKwv2VIPke80nt6UEW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":87773},"main":"index.js","engines":{"node":">=18.0.0"},"gitHead":"4f6d1e30d89694e16aff7de8eb1ab341644bf488","_npmUser":{"name":"matztam","email":"npm2026@afke.eu"},"repository":{"url":"git+https://github.com/matztam/signalk-beluga-core.git","type":"git"},"_npmVersion":"11.12.1","description":"ORCA Core emulator for SignalK — BLE advertisement, mDNS, REST API and WebSocket sensor stream compatible with the ORCA app","directories":{},"_nodeVersion":"24.15.0","dependencies":{"ws":"^8.14.2","express":"^4.18.2","bonjour-service":"^1.2.1"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/signalk-beluga-core_0.1.0_1777578709615_0.6635774183982719","host":"s3://npm-registry-packages-npm-production"},"signalk-plugin-enabled-by-default":false},"0.1.1":{"name":"signalk-beluga-core","version":"0.1.1","keywords":["signalk-node-server-plugin","signalk-category-hardware","signalk-category-ais","orca"],"author":{"name":"matztam"},"license":"AGPL-3.0-only","_id":"signalk-beluga-core@0.1.1","maintainers":[{"name":"matztam","email":"npm2026@afke.eu"}],"homepage":"https://github.com/matztam/signalk-beluga-core","bugs":{"url":"https://github.com/matztam/signalk-beluga-core/issues"},"dist":{"shasum":"e8e731e56a435baef7a7aea6fd28c3f26a18fe4b","tarball":"https://registry.npmjs.org/signalk-beluga-core/-/signalk-beluga-core-0.1.1.tgz","fileCount":10,"integrity":"sha512-lhGEhkc1pwsb57T/nhqN4XCzX3ex3ZAw1SX5sJXrQAtj50Mvz9HAIQyEKbaex5vZn5WMu1z4UKrRypqntFPjeA==","signatures":[{"sig":"MEQCIBKyH49CVrdJJFYhjJDg/W0v+n6HghH9EcnnaV3MloNgAiAUNIY8BSHx3SI9J2e2di9AUyv25R0bv0AZGmdsjltjPg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":90354},"main":"index.js","engines":{"node":">=18.0.0"},"gitHead":"45fbc05705abafffcfb79c0fc4e498834dc942a1","_npmUser":{"name":"matztam","email":"npm2026@afke.eu"},"repository":{"url":"git+https://github.com/matztam/signalk-beluga-core.git","type":"git"},"_npmVersion":"11.12.1","description":"ORCA Core emulator for SignalK — BLE advertisement, mDNS, REST API and WebSocket sensor stream compatible with the ORCA app","directories":{},"_nodeVersion":"24.15.0","dependencies":{"ws":"^8.14.2","express":"^4.18.2","bonjour-service":"^1.2.1"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/signalk-beluga-core_0.1.1_1777922839182_0.9639490982035701","host":"s3://npm-registry-packages-npm-production"},"signalk-plugin-enabled-by-default":false},"0.1.2":{"name":"signalk-beluga-core","version":"0.1.2","keywords":["signalk-node-server-plugin","signalk-category-hardware","signalk-category-ais","orca"],"author":{"name":"matztam"},"license":"AGPL-3.0-only","_id":"signalk-beluga-core@0.1.2","maintainers":[{"name":"matztam","email":"npm2026@afke.eu"}],"homepage":"https://github.com/matztam/signalk-beluga-core","bugs":{"url":"https://github.com/matztam/signalk-beluga-core/issues"},"dist":{"shasum":"85db96bf18cab12c8b3ffb7e75a88679f320864c","tarball":"https://registry.npmjs.org/signalk-beluga-core/-/signalk-beluga-core-0.1.2.tgz","fileCount":10,"integrity":"sha512-HFHdmAbYo+mseK16aHrxMPAJHqhwxEc2+r6sa6SRlKj0zMFYTD+s+B5l/Q5Se4Pu8my3yKlI6d/sw0DflwgKwg==","signatures":[{"sig":"MEUCIQDtEaW69vhe3ZTpcT43Wo0ytehYoxWPCM4Qk7fSZ9d0EgIgd2qoA0RcyY9g4NNBUfNmZ+5PjDMXFUl4PeqBdQtTuJ4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":91354},"main":"index.js","engines":{"node":">=18.0.0"},"gitHead":"6f3dd7770f2c7a1993e3bf1399e04da092b503c9","_npmUser":{"name":"matztam","email":"npm2026@afke.eu"},"repository":{"url":"git+https://github.com/matztam/signalk-beluga-core.git","type":"git"},"_npmVersion":"11.12.1","description":"ORCA Core emulator for SignalK — BLE advertisement, mDNS, REST API and WebSocket sensor stream compatible with the ORCA app","directories":{},"_nodeVersion":"24.15.0","dependencies":{"ws":"^8.14.2","express":"^4.18.2","bonjour-service":"^1.2.1"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/signalk-beluga-core_0.1.2_1777971585328_0.729753635897185","host":"s3://npm-registry-packages-npm-production"},"signalk-plugin-enabled-by-default":false},"0.2.2":{"name":"signalk-beluga-core","version":"0.2.2","description":"ORCA Core emulator for SignalK — BLE advertisement, mDNS, REST API and WebSocket sensor stream compatible with the ORCA app","main":"index.js","keywords":["signalk-node-server-plugin","signalk-category-hardware","signalk-category-ais","orca"],"author":{"name":"matztam"},"repository":{"type":"git","url":"git+https://github.com/matztam/signalk-beluga-core.git"},"homepage":"https://github.com/matztam/signalk-beluga-core","signalk-plugin-enabled-by-default":false,"license":"AGPL-3.0-only","engines":{"node":">=18.0.0"},"dependencies":{"@mongodb-js/zstd":"^7.0.0","@msgpack/msgpack":"^3.1.3","bonjour-service":"^1.2.1","express":"^4.18.2","protobufjs":"^8.5.0","ws":"^8.14.2"},"_id":"signalk-beluga-core@0.2.2","gitHead":"e93e30b2a28d7fb50ab79beb43ce691917678537","bugs":{"url":"https://github.com/matztam/signalk-beluga-core/issues"},"_nodeVersion":"23.7.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-0ctQw/w/rF5zDO2oAstDMkQ4xM8w4ZBoIbeyD/1EopctayqIV2OS25Errz2Vehs0sxkEJh+tg8PKR5leTBHEgg==","shasum":"e43b299ee48b8480bc1280b475b13a3aea88ab87","tarball":"https://registry.npmjs.org/signalk-beluga-core/-/signalk-beluga-core-0.2.2.tgz","fileCount":12,"unpackedSize":110542,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIG6gpSe+kTV1KDCHnA68mwGx/VcmJoZWX3KDBMsuMlJVAiBB35Z5/l8MUdOwKkIU8/7uXmBzVpKfonkNYoqLn2g2cQ=="}]},"_npmUser":{"name":"matztam","email":"npm2026@afke.eu"},"directories":{},"maintainers":[{"name":"matztam","email":"npm2026@afke.eu"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/signalk-beluga-core_0.2.2_1784987174396_0.40439082156547124"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-30T19:51:49.614Z","modified":"2026-07-25T13:46:14.677Z","0.1.0":"2026-04-30T19:51:49.760Z","0.1.1":"2026-05-04T19:27:19.363Z","0.1.2":"2026-05-05T08:59:45.446Z","0.2.0":"2026-07-25T09:31:21.547Z","0.2.1":"2026-07-25T13:23:28.384Z","0.2.2":"2026-07-25T13:46:14.546Z"},"bugs":{"url":"https://github.com/matztam/signalk-beluga-core/issues"},"author":{"name":"matztam"},"license":"AGPL-3.0-only","homepage":"https://github.com/matztam/signalk-beluga-core","keywords":["signalk-node-server-plugin","signalk-category-hardware","signalk-category-ais","orca"],"repository":{"type":"git","url":"git+https://github.com/matztam/signalk-beluga-core.git"},"description":"ORCA Core emulator for SignalK — BLE advertisement, mDNS, REST API and WebSocket sensor stream compatible with the ORCA app","maintainers":[{"name":"matztam","email":"npm2026@afke.eu"}],"readme":"# signalk-beluga-core\n\nA [SignalK](https://signalk.org/) plugin that emulates an ORCA Core marine sensor hub.\nIt makes the ORCA app (`com.theorca.slate`) connect to your SignalK server.\n\n## What it does\n\n| Component | Port | Description |\n|-----------|------|-------------|\n| BLE advertisement | — | Announces the device so the ORCA app can find it for initial pairing |\n| mDNS | — | Publishes `_extractor-http._tcp` and `_extractor-ws._tcp` services for app discovery |\n| REST API | 8088 | Handles all ORCA app HTTP endpoints (`/v1/devices`, `/v1/sources`, `/v1/nmea2000/status`, …) |\n| UI stub | 8080 | Responds to `/info` so the app skips its boot delay |\n| WebSocket | 8089 | Streams sensor deltas (`/v1/sensors/delta`) and AIS deltas (`?ns=ais`) to the app |\n| Radar REST | 9081 | Handles `/v1/radars` and radar command/status endpoints _(only when mayara host is configured)_ |\n| Radar WebSocket | 9089 | Streams radar spoke frames (`/v1/spokes/:id/delta`) to the app _(only when mayara host is configured)_ |\n\nSignalK paths are read from the running server via `app.getSelfPath()` and translated into the flat key format the ORCA app expects.\n\n## Radar support\n\nRadar data is forwarded from a [mayara-server](https://github.com/keesverruijt/mayara) instance. Configure the mayara-server host and port in the plugin settings to enable radar. beluga-core connects directly to mayara's REST and WebSocket API — no mayara SignalK plugin required. Spokes are re-encoded and sent to the ORCA app once per antenna revolution. If no mayara host is configured, the radar ports are not opened. Discovery is retried every 15 seconds if the radar is not yet transmitting.\n\n## Requirements\n\n- **Linux with BlueZ** — required for BLE pairing (standard path); not needed when using Direct-AP mode\n- **mayara-server** — required only for radar support; must be reachable from the SignalK host over HTTP/WebSocket\n- **Python 3** (`python3` on `PATH`) — BLE is implemented via the `bless` library (Python), which talks to BlueZ over D-Bus; there is no viable Node.js alternative (bleno conflicts with bluetoothd at the HCI level)\n- Node.js ≥ 18\n- SignalK server\n\n## Installation\n\n```bash\ncd ~/.signalk\nnpm install /path/to/signalk-beluga-core\n```\n\nAfter any `npm install` in `~/.signalk/`, reinstall the plugin if it disappears from the plugin list:\n\n```bash\ncd ~/.signalk && npm install /path/to/signalk-beluga-core\n```\n\nPython dependencies (`bless`, `dbus-next`) are installed automatically into a plugin-local `.venv` on first start. No manual pip install needed.\n\n## Configuration\n\nOpen the SignalK plugin settings page and configure:\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `deviceId` | `orca01` | 6 alphanumeric characters — becomes `orca-<deviceId>` |\n| `wifiSsid` | `\"\"` | Must match the phone's current WiFi SSID for BLE pairing |\n| `firmwareVersion` | `2026.3.1` | Firmware version reported to the ORCA app |\n| `model` | `ORCA Core` | Model name shown in the app |\n| `enableBle` | `true` | Disable on systems without BlueZ |\n| `deltaIntervalMs` | `1000` | WebSocket update interval in milliseconds |\n| `mayaraHost` | `\"\"` | Hostname or IP of the mayara-server instance. Leave empty to disable radar. |\n| `mayaraPort` | `6502` | mayara-server REST/WebSocket port |\n\n## Pairing the ORCA app\n\n### Standard path (BLE + mDNS)\n\n1. Make sure the phone and the SignalK host are on the **same WiFi network**.\n2. Set `wifiSsid` in the plugin config to that network's SSID.\n3. Close the GNOME Bluetooth settings panel (or similar application) if it is open — it creates a persistent scan session in BlueZ that causes GATT connection timeouts (see [BLE troubleshooting](#ble-troubleshooting)).\n4. Start the plugin. The device appears in the ORCA app's pairing screen \".\n5. After BLE pairing the app switches to mDNS → REST → WebSocket automatically.\n\n### Alternative path: Direct-AP mode (no BLE, no mDNS required)\n\nIf the phone's current WiFi SSID matches the pattern **`orca-[a-zA-Z0-9]+`** (e.g. `orca-demo01`), the app skips BLE pairing and mDNS discovery entirely and connects directly to **`10.11.12.1`** on port 8088/8089.\n\n\n\nTo use this mode:\n\n1. Create a WiFi access point with an SSID matching `orca-XXXXXX` (e.g. `orca-demo01`).\n2. Assign the SignalK host the IP address **`10.11.12.1`** on that network.\n3. Connect the phone to that WiFi network.\n4. Open the ORCA app — it connects immediately without BLE or mDNS.\n\nThis is the most reliable setup for a dedicated boat network (e.g. Raspberry Pi as access point) and completely eliminates the BLE requirement.\n\n## BLE troubleshooting\n\n**Symptom:** The device appears in the BLE scanner but the ORCA app shows \"BleError: Device disconnected\" after ~5 seconds.\n\n**Cause:** BlueZ has a lingering scan session (most commonly left by the GNOME Bluetooth configuration panel). About 17 ms after the GATT connection is established, BlueZ sends an `LE Set Extended Scan Enable` command that triggers a supervision timeout (HCI error `0x08`) and drops the connection.\n\n**Diagnosis:**\n```bash\nsudo btmon 2>&1 | grep -E \"Connect|Disconn|Scan Enable|Error\"\n# Look for \"LE Set Extended Scan Enable\" shortly after \"LE Connection Complete\"\n```\n\nConfirm a foreign scan session:\n```bash\nbluetoothctl scan off\n# If it prints \"org.bluez.Error.Failed\" instead of \"Discovery stopped\", another process owns the scan\n```\n\n**Fix:**\n```bash\nsudo systemctl restart bluetooth\n```\n\nThis clears all stale BlueZ state. The ORCA app can then complete GATT pairing successfully.\n\n**Note:** `@abandonware/bleno` (Node.js) conflicts with `bluetoothd` at the HCI level and does **not** work alongside BlueZ. Use the included Python/bless approach instead.\n\n## SignalK → ORCA key mapping\n\nThe WebSocket mapper (`lib/mapper.js`) covers navigation, GNSS, COG/SOG, heading, attitude, depth, water speed, temperature, pressure, wind, propulsion, battery banks, fluid tanks, rudder, and autopilot. Data is sent event-driven — each incoming SignalK delta triggers an immediate forward to connected ORCA app clients, rate-limited to the interval the app requests via `?interval=`.\n\n## License\n\nGNU Affero General Public License v3.0 (AGPL-3.0-only).\n","readmeFilename":"README.md"}