signalk-data-connector 1.0.0-beta.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/dependabot.yml +11 -0
- package/.prettierignore +13 -0
- package/LICENSE +21 -0
- package/README.md +536 -0
- package/doc/dataconnectorconcept.jpg +0 -0
- package/doc/datarate.jpg +0 -0
- package/index.js +642 -0
- package/lib/CircularBuffer.js +35 -0
- package/lib/constants.js +65 -0
- package/lib/crypto.js +98 -0
- package/lib/metrics.js +229 -0
- package/lib/pathDictionary.js +483 -0
- package/lib/pipeline.js +285 -0
- package/lib/routes.js +393 -0
- package/package.json +75 -0
- package/public/277.7c32327dcd875a824b16.js +15 -0
- package/public/277.7c32327dcd875a824b16.js.LICENSE.txt +18 -0
- package/public/277.7c32327dcd875a824b16.js.map +1 -0
- package/public/540.3572ec18e3cabaecbfaf.js +3 -0
- package/public/540.3572ec18e3cabaecbfaf.js.LICENSE.txt +14 -0
- package/public/540.3572ec18e3cabaecbfaf.js.map +1 -0
- package/public/831.f990723e0e1340495c1f.js +3 -0
- package/public/831.f990723e0e1340495c1f.js.LICENSE.txt +1 -0
- package/public/831.f990723e0e1340495c1f.js.map +1 -0
- package/public/icons/icon-72x72.png +0 -0
- package/public/index.html +1 -0
- package/public/main.5d54244033b773c1441a.css +890 -0
- package/public/main.5d54244033b773c1441a.css.map +1 -0
- package/public/main.8bacb33c1e765118b841.js +3 -0
- package/public/main.8bacb33c1e765118b841.js.LICENSE.txt +1 -0
- package/public/main.8bacb33c1e765118b841.js.map +1 -0
- package/public/remoteEntry.js +2 -0
- package/public/remoteEntry.js.map +1 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# To get started with Dependabot version updates, you'll need to specify which
|
|
2
|
+
# package ecosystems to update and where the package manifests are located.
|
|
3
|
+
# Please see the documentation for all configuration options:
|
|
4
|
+
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
|
5
|
+
|
|
6
|
+
version: 2
|
|
7
|
+
updates:
|
|
8
|
+
- package-ecosystem: "npm" # See documentation for possible values
|
|
9
|
+
directory: "/" # Location of package manifests
|
|
10
|
+
schedule:
|
|
11
|
+
interval: "weekly"
|
package/.prettierignore
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Karl-Erik Gustafsson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
# Signal K Data Connector
|
|
2
|
+
|
|
3
|
+
Secure, encrypted UDP data transmission between Signal K servers with advanced bandwidth optimization.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/KEGustafsson/signalk-data-connector)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Table of Contents
|
|
14
|
+
|
|
15
|
+
- [Overview](#overview)
|
|
16
|
+
- [Getting Started](#getting-started)
|
|
17
|
+
- [Installation](#installation)
|
|
18
|
+
- [Quick Start](#quick-start)
|
|
19
|
+
- [Configuration](#configuration)
|
|
20
|
+
- [Server Mode](#server-mode-receiver)
|
|
21
|
+
- [Client Mode](#client-mode-sender)
|
|
22
|
+
- [Web Dashboard](#web-dashboard)
|
|
23
|
+
- [Configuration Files](#configuration-files)
|
|
24
|
+
- [Network Monitoring](#network-monitoring)
|
|
25
|
+
- [Performance](#performance)
|
|
26
|
+
- [Bandwidth Comparison](#bandwidth-comparison)
|
|
27
|
+
- [Smart Batching](#smart-batching)
|
|
28
|
+
- [Optimization Tips](#optimization-tips)
|
|
29
|
+
- [Security](#security)
|
|
30
|
+
- [Encryption](#encryption)
|
|
31
|
+
- [Secret Key Requirements](#secret-key-requirements)
|
|
32
|
+
- [Best Practices](#best-practices)
|
|
33
|
+
- [Troubleshooting](#troubleshooting)
|
|
34
|
+
- [Development](#development)
|
|
35
|
+
- [Architecture](#architecture)
|
|
36
|
+
- [Project Structure](#project-structure)
|
|
37
|
+
- [Build Commands](#build-commands)
|
|
38
|
+
- [Testing](#testing)
|
|
39
|
+
- [Technical Reference](#technical-reference)
|
|
40
|
+
- [Contributing](#contributing)
|
|
41
|
+
- [License](#license)
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Overview
|
|
46
|
+
|
|
47
|
+
Signal K Data Connector is a Signal K Node Server plugin that enables real-time data sharing between vessels or shore stations over UDP. It combines AES-256-GCM authenticated encryption with Brotli compression to deliver secure, bandwidth-efficient transmission — achieving up to **97% bandwidth reduction** compared to raw data.
|
|
48
|
+
|
|
49
|
+
**Key capabilities:**
|
|
50
|
+
|
|
51
|
+
| Feature | Description |
|
|
52
|
+
|---------|-------------|
|
|
53
|
+
| Encrypted transport | AES-256-GCM authenticated encryption with per-message unique IV |
|
|
54
|
+
| Brotli compression | Quality-10 compression with 85–97% reduction on typical data |
|
|
55
|
+
| Binary protocol | Zero JSON overhead in the wire format |
|
|
56
|
+
| Path dictionary | 170+ Signal K paths mapped to numeric IDs (10–20% savings) |
|
|
57
|
+
| MessagePack | Optional binary serialization (15–25% additional savings) |
|
|
58
|
+
| Smart batching | Adaptive packet sizing that prevents UDP fragmentation |
|
|
59
|
+
| Sentence filtering | Exclude NMEA sentences (GSV, GSA, etc.) to reduce bandwidth |
|
|
60
|
+
| Network monitoring | TCP ping with RTT measurement published to Signal K |
|
|
61
|
+
| Web dashboard | Real-time bandwidth, compression, and path analytics |
|
|
62
|
+
| Hot-reload config | Configuration files reload automatically on change |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Getting Started
|
|
67
|
+
|
|
68
|
+
### Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cd ~/.signalk/node_modules/
|
|
72
|
+
git clone https://github.com/KEGustafsson/signalk-data-connector.git
|
|
73
|
+
cd signalk-data-connector
|
|
74
|
+
npm install
|
|
75
|
+
npm run build
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Restart your Signal K server after installation.
|
|
79
|
+
|
|
80
|
+
### Quick Start
|
|
81
|
+
|
|
82
|
+
1. Open **Admin UI → Plugin Config → Signal K Data Connector**
|
|
83
|
+
2. Choose an operation mode:
|
|
84
|
+
- **Server** — receives data from remote clients
|
|
85
|
+
- **Client** — sends data to a remote server
|
|
86
|
+
3. Set the **UDP port** (must match between client and server)
|
|
87
|
+
4. Enter a **32-character encryption key** (must be identical on both ends)
|
|
88
|
+
5. For client mode, enter the **server IP address**
|
|
89
|
+
6. Enable the plugin and verify data flow in the web dashboard
|
|
90
|
+
|
|
91
|
+
> **Tip:** Start with the default settings. Enable path dictionary and MessagePack later for additional bandwidth savings.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Configuration
|
|
96
|
+
|
|
97
|
+
The plugin provides a custom React-based configuration UI that dynamically adapts to the selected operation mode, showing only relevant settings.
|
|
98
|
+
|
|
99
|
+
**Access:** Admin UI → Plugin Config → Signal K Data Connector
|
|
100
|
+
|
|
101
|
+
### Server Mode (Receiver)
|
|
102
|
+
|
|
103
|
+
| Setting | Description |
|
|
104
|
+
|---------|-------------|
|
|
105
|
+
| Operation Mode | Server/Client selector |
|
|
106
|
+
| UDP Port | Port to listen on (1024–65535) |
|
|
107
|
+
| Encryption Key | 32-character secret key |
|
|
108
|
+
| MessagePack | Enable binary serialization |
|
|
109
|
+
| Path Dictionary | Enable path encoding |
|
|
110
|
+
|
|
111
|
+
### Client Mode (Sender)
|
|
112
|
+
|
|
113
|
+
| Setting | Description |
|
|
114
|
+
|---------|-------------|
|
|
115
|
+
| Operation Mode | Server/Client selector |
|
|
116
|
+
| UDP Port | Port to send to |
|
|
117
|
+
| Encryption Key | 32-character secret key (must match server) |
|
|
118
|
+
| Destination Address | Server IP or hostname |
|
|
119
|
+
| Heartbeat Interval | Keep-alive message frequency (seconds) |
|
|
120
|
+
| Connectivity Test Target | Address to ping for network monitoring |
|
|
121
|
+
| Connectivity Test Port | Port to test (80, 443, etc.) |
|
|
122
|
+
| Check Interval | How often to test connectivity (minutes) |
|
|
123
|
+
| MessagePack | Enable binary serialization |
|
|
124
|
+
| Path Dictionary | Enable path encoding |
|
|
125
|
+
|
|
126
|
+
Additional client settings are available in the web dashboard:
|
|
127
|
+
- **Delta timer** — collection interval (100–10000 ms)
|
|
128
|
+
- **Subscription paths** — Signal K paths to transmit
|
|
129
|
+
- **Sentence filter** — NMEA sentences to exclude (e.g., `GSV, GSA, VTG`)
|
|
130
|
+
|
|
131
|
+
### Web Dashboard
|
|
132
|
+
|
|
133
|
+
**Access:** `http://[signalk-server]:3000/plugins/signalk-data-connector`
|
|
134
|
+
|
|
135
|
+
The dashboard provides real-time monitoring and configuration controls.
|
|
136
|
+
|
|
137
|
+
**Client mode:**
|
|
138
|
+
- Delta timer and subscription management
|
|
139
|
+
- Sentence filter configuration
|
|
140
|
+
- Upload/download bandwidth with compression ratio
|
|
141
|
+
- Bandwidth savings display (actual bytes saved)
|
|
142
|
+
- Path analytics with per-path data volume breakdown
|
|
143
|
+
- Performance metrics (errors, uptime, deltas sent)
|
|
144
|
+
- Rate history chart (last 150 seconds)
|
|
145
|
+
|
|
146
|
+
**Server mode:**
|
|
147
|
+
- Download bandwidth and packet rate
|
|
148
|
+
- Bandwidth savings display
|
|
149
|
+
- Incoming path analytics
|
|
150
|
+
- Performance metrics (deltas received, errors)
|
|
151
|
+
- Compression effectiveness tracking
|
|
152
|
+
|
|
153
|
+
### Configuration Files
|
|
154
|
+
|
|
155
|
+
These JSON files are stored in the plugin data directory and support hot-reload — changes take effect automatically without restarting.
|
|
156
|
+
|
|
157
|
+
| File | Purpose | Default |
|
|
158
|
+
|------|---------|---------|
|
|
159
|
+
| `delta_timer.json` | Collection interval in ms | `{"deltaTimer": 1000}` |
|
|
160
|
+
| `subscription.json` | Signal K paths to subscribe | `{"context": "*", "subscribe": [...]}` |
|
|
161
|
+
| `sentence_filter.json` | NMEA sentences to exclude | `{"sentences": []}` |
|
|
162
|
+
|
|
163
|
+
### API Endpoints
|
|
164
|
+
|
|
165
|
+
All endpoints are rate-limited to 20 requests per minute per IP.
|
|
166
|
+
|
|
167
|
+
| Method | Endpoint | Description |
|
|
168
|
+
|--------|----------|-------------|
|
|
169
|
+
| GET | `/plugins/signalk-data-connector/config/:filename` | Read a configuration file |
|
|
170
|
+
| POST | `/plugins/signalk-data-connector/config/:filename` | Update a configuration file |
|
|
171
|
+
| GET | `/plugins/signalk-data-connector/metrics` | Real-time statistics and performance data |
|
|
172
|
+
| GET | `/plugins/signalk-data-connector/paths` | Path dictionary information |
|
|
173
|
+
| GET | `/plugins/signalk-data-connector/plugin-config` | Current plugin configuration |
|
|
174
|
+
| POST | `/plugins/signalk-data-connector/plugin-config` | Update plugin configuration |
|
|
175
|
+
| GET | `/plugins/signalk-data-connector/plugin-schema` | Plugin schema definition |
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Network Monitoring
|
|
180
|
+
|
|
181
|
+
In client mode, the plugin measures **Round Trip Time (RTT)** using TCP ping to monitor connectivity and latency.
|
|
182
|
+
|
|
183
|
+
**How it works:**
|
|
184
|
+
1. TCP ping is sent to the configured test address and port at the configured interval
|
|
185
|
+
2. RTT is published to local Signal K at `networking.modem.rtt` (value in seconds)
|
|
186
|
+
3. If subscribed, RTT data is transmitted to the remote server with other data
|
|
187
|
+
|
|
188
|
+
**To enable RTT transmission:** Add `networking.modem.rtt` to your subscription paths.
|
|
189
|
+
|
|
190
|
+
**Use cases:**
|
|
191
|
+
- Monitor cellular or satellite modem latency
|
|
192
|
+
- Track connection quality over time
|
|
193
|
+
- Trigger alerts on high latency
|
|
194
|
+
- Analyze network performance trends
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Performance
|
|
199
|
+
|
|
200
|
+
### Bandwidth Comparison
|
|
201
|
+
|
|
202
|
+

|
|
203
|
+
|
|
204
|
+
| Mode | Bandwidth | Reduction vs. WebSocket |
|
|
205
|
+
|------|-----------|------------------------|
|
|
206
|
+
| 1000 ms collection | ~44.1 kb/s | ~70% |
|
|
207
|
+
| 100 ms collection | ~107.7 kb/s | ~28% |
|
|
208
|
+
| WebSocket real-time | ~149.5 kb/s | — |
|
|
209
|
+
|
|
210
|
+
Typical compression results on Signal K data:
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
Original: 19,293 bytes → Encrypted + Compressed: 622 bytes (96.78% reduction)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Smart Batching
|
|
217
|
+
|
|
218
|
+
The plugin uses adaptive smart batching to keep UDP packets under the MTU limit (1400 bytes), preventing fragmentation that can cause data loss.
|
|
219
|
+
|
|
220
|
+
1. **Rolling average** — tracks bytes-per-delta using exponential smoothing
|
|
221
|
+
2. **Dynamic batch sizing** — calculates optimal deltas per packet based on recent sizes
|
|
222
|
+
3. **Early send trigger** — sends immediately when a batch reaches the predicted size limit
|
|
223
|
+
4. **Self-learning** — continuously adapts as data patterns change
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
Example: Initial estimate 5 deltas/batch → After learning: 11 deltas/batch
|
|
227
|
+
All packets stay well under 1400 bytes
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Optimization Tips
|
|
231
|
+
|
|
232
|
+
For the best bandwidth efficiency:
|
|
233
|
+
|
|
234
|
+
1. **Increase delta timer** — 1000 ms gives optimal compression; lower values increase bandwidth
|
|
235
|
+
2. **Enable path dictionary** — saves 10–20% by replacing path strings with numeric IDs
|
|
236
|
+
3. **Enable MessagePack** — saves 15–25% with binary serialization
|
|
237
|
+
4. **Filter NMEA sentences** — exclude GSV, GSA, VTG to remove unnecessary data
|
|
238
|
+
5. **Review subscriptions** — subscribe only to paths you need
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Security
|
|
243
|
+
|
|
244
|
+
### Encryption
|
|
245
|
+
|
|
246
|
+
All data is encrypted with **AES-256-GCM**, providing authenticated encryption in a single operation.
|
|
247
|
+
|
|
248
|
+
| Property | Detail |
|
|
249
|
+
|----------|--------|
|
|
250
|
+
| Algorithm | AES-256-GCM |
|
|
251
|
+
| IV | 12 bytes, unique per message |
|
|
252
|
+
| Auth tag | 16 bytes, tamper detection |
|
|
253
|
+
| Wire format | `[IV (12 bytes)][Encrypted Data][Auth Tag (16 bytes)]` |
|
|
254
|
+
| Overhead | 28 bytes per packet |
|
|
255
|
+
|
|
256
|
+
**Security features:**
|
|
257
|
+
- Tamper detection — any modification causes decryption failure
|
|
258
|
+
- Rate-limited API endpoints (20 req/min/IP)
|
|
259
|
+
- Input validation on all parameters
|
|
260
|
+
- Key entropy checking — rejects weak keys
|
|
261
|
+
- XSS protection in the web UI
|
|
262
|
+
- Stateless UDP — no session state to compromise
|
|
263
|
+
|
|
264
|
+
### Secret Key Requirements
|
|
265
|
+
|
|
266
|
+
- Exactly **32 characters** (256 bits)
|
|
267
|
+
- Minimum **8 unique characters**
|
|
268
|
+
- Must match on both client and server
|
|
269
|
+
|
|
270
|
+
Generate a secure key:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
openssl rand -base64 32 | cut -c1-32
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Valid examples:**
|
|
277
|
+
```
|
|
278
|
+
Abc123!@#XYZ456$%^uvw789&*()pqr0
|
|
279
|
+
K9#mP2$nQ7@rS4%tU6^vW8*xY3!zA5&
|
|
280
|
+
abcdefgh12345678901234567890abcd
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Invalid examples:**
|
|
284
|
+
```
|
|
285
|
+
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa # All same character
|
|
286
|
+
abababababababababababababababab # Insufficient diversity
|
|
287
|
+
MySecretKey123 # Too short
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Best Practices
|
|
291
|
+
|
|
292
|
+
1. Use strong, randomly generated keys (`openssl rand` recommended)
|
|
293
|
+
2. Never commit keys to version control
|
|
294
|
+
3. Rotate keys periodically (every 6–12 months)
|
|
295
|
+
4. Monitor logs for decryption failures (may indicate attacks or key mismatch)
|
|
296
|
+
5. Restrict UDP access with firewall rules to known IP addresses
|
|
297
|
+
6. Test configuration in a safe environment before production deployment
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Troubleshooting
|
|
302
|
+
|
|
303
|
+
### Plugin Not Loading
|
|
304
|
+
|
|
305
|
+
- Verify `npm install` completed successfully
|
|
306
|
+
- Check Signal K server logs for errors
|
|
307
|
+
- Ensure plugin directory is `~/.signalk/node_modules/signalk-data-connector`
|
|
308
|
+
- Verify Node.js version ≥ 14.0.0
|
|
309
|
+
|
|
310
|
+
### Web UI Not Accessible
|
|
311
|
+
|
|
312
|
+
- Run `npm run build` to generate UI files
|
|
313
|
+
- Verify `public/` directory exists with built files
|
|
314
|
+
- Clear browser cache and refresh
|
|
315
|
+
|
|
316
|
+
### No Data Transmission
|
|
317
|
+
|
|
318
|
+
**Client side:**
|
|
319
|
+
1. Confirm encryption keys match on both ends
|
|
320
|
+
2. Verify UDP port and destination address
|
|
321
|
+
3. Check firewall allows UDP traffic on the configured port
|
|
322
|
+
4. Confirm subscription paths are valid Signal K paths
|
|
323
|
+
5. Verify delta timer is running (check metrics in web dashboard)
|
|
324
|
+
|
|
325
|
+
**Server side:**
|
|
326
|
+
1. Verify UDP port is not blocked by firewall
|
|
327
|
+
2. Confirm encryption key matches the client
|
|
328
|
+
3. Check Signal K logs for decryption errors
|
|
329
|
+
4. Verify client is sending data (check client metrics)
|
|
330
|
+
|
|
331
|
+
**Common error messages:**
|
|
332
|
+
|
|
333
|
+
| Message | Cause |
|
|
334
|
+
|---------|-------|
|
|
335
|
+
| `Unsupported state or unable to authenticate data` | Mismatched encryption keys |
|
|
336
|
+
| `Invalid packet size` | Corrupted data or network issues |
|
|
337
|
+
| `Secret key must be exactly 32 characters` | Invalid key length |
|
|
338
|
+
|
|
339
|
+
### Poor Performance
|
|
340
|
+
|
|
341
|
+
- Increase delta timer for better compression (1000 ms recommended)
|
|
342
|
+
- Enable path dictionary and MessagePack
|
|
343
|
+
- Filter unnecessary NMEA sentences
|
|
344
|
+
- Check network latency with the ping monitor
|
|
345
|
+
- Monitor CPU usage (Brotli compression at quality 10 is CPU-intensive)
|
|
346
|
+
|
|
347
|
+
### Debug Logging
|
|
348
|
+
|
|
349
|
+
Enable in Signal K plugin settings to see:
|
|
350
|
+
- Connection monitor status and ping results
|
|
351
|
+
- Configuration file changes (automatic reload)
|
|
352
|
+
- Delta transmission statistics
|
|
353
|
+
- Compression ratios and packet sizes
|
|
354
|
+
- Error messages with full context
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Development
|
|
359
|
+
|
|
360
|
+
### Architecture
|
|
361
|
+
|
|
362
|
+
**Data pipeline:**
|
|
363
|
+
|
|
364
|
+
```
|
|
365
|
+
Client (Sender):
|
|
366
|
+
Signal K Deltas → Filter → [Path Encode] → [MessagePack] → Brotli → AES-256-GCM → UDP
|
|
367
|
+
|
|
368
|
+
Server (Receiver):
|
|
369
|
+
UDP → AES-256-GCM → Brotli → [MessagePack] → [Path Decode] → Signal K
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
The plugin core is decomposed into focused modules:
|
|
373
|
+
|
|
374
|
+
| Module | Responsibility |
|
|
375
|
+
|--------|---------------|
|
|
376
|
+
| `index.js` | Plugin entry point, shared state, file watchers, lifecycle |
|
|
377
|
+
| `lib/constants.js` | Shared constants and batch size calculation |
|
|
378
|
+
| `lib/CircularBuffer.js` | Fixed-size circular buffer for O(1) metrics history |
|
|
379
|
+
| `lib/crypto.js` | AES-256-GCM encryption and decryption |
|
|
380
|
+
| `lib/metrics.js` | Bandwidth tracking, path analytics, error recording |
|
|
381
|
+
| `lib/pathDictionary.js` | Signal K path encoding (170+ paths) |
|
|
382
|
+
| `lib/pipeline.js` | Compress → encrypt → send / receive → decrypt → decompress |
|
|
383
|
+
| `lib/routes.js` | HTTP route handlers, rate limiting, config file I/O |
|
|
384
|
+
|
|
385
|
+
Modules are wired together via factory functions that receive a shared `state` object by reference, enabling cross-module state access without globals.
|
|
386
|
+
|
|
387
|
+
### Project Structure
|
|
388
|
+
|
|
389
|
+
```
|
|
390
|
+
signalk-data-connector/
|
|
391
|
+
├── index.js # Plugin entry, state, watchers, lifecycle
|
|
392
|
+
├── lib/
|
|
393
|
+
│ ├── CircularBuffer.js # Fixed-size circular buffer
|
|
394
|
+
│ ├── constants.js # Shared constants and utilities
|
|
395
|
+
│ ├── crypto.js # AES-256-GCM encryption module
|
|
396
|
+
│ ├── metrics.js # Metrics, bandwidth, path analytics
|
|
397
|
+
│ ├── pathDictionary.js # Signal K path encoding (170+ paths)
|
|
398
|
+
│ ├── pipeline.js # Pack/unpack pipeline (compress, encrypt, UDP)
|
|
399
|
+
│ └── routes.js # HTTP routes and rate limiting
|
|
400
|
+
├── src/
|
|
401
|
+
│ ├── webapp/
|
|
402
|
+
│ │ ├── index.js # Web dashboard (vanilla JS)
|
|
403
|
+
│ │ └── styles.css
|
|
404
|
+
│ └── components/
|
|
405
|
+
│ └── PluginConfigurationPanel.jsx # React config panel
|
|
406
|
+
├── __tests__/ # 209 tests across 9 files
|
|
407
|
+
│ ├── crypto.test.js
|
|
408
|
+
│ ├── pathDictionary.test.js
|
|
409
|
+
│ ├── compression.test.js
|
|
410
|
+
│ ├── full-pipeline.test.js
|
|
411
|
+
│ ├── smartBatching.test.js
|
|
412
|
+
│ ├── config.test.js
|
|
413
|
+
│ ├── index.test.js
|
|
414
|
+
│ ├── webapp.test.js
|
|
415
|
+
│ └── integration-pipe.test.js
|
|
416
|
+
└── public/ # Built UI files (generated)
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Build Commands
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
npm run dev # Development build with watch mode
|
|
423
|
+
npm run build # Production build
|
|
424
|
+
npm test # Run all 209 tests
|
|
425
|
+
npm run test:watch # Run tests in watch mode
|
|
426
|
+
npm run test:coverage # Generate coverage report
|
|
427
|
+
npm run lint # Check code style
|
|
428
|
+
npm run lint:fix # Auto-fix linting issues
|
|
429
|
+
npm run format # Format code with Prettier
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Testing
|
|
433
|
+
|
|
434
|
+
The test suite covers all critical paths with 209 tests across 9 files:
|
|
435
|
+
|
|
436
|
+
| Test file | Scope |
|
|
437
|
+
|-----------|-------|
|
|
438
|
+
| `crypto.test.js` | Encryption, decryption, key validation |
|
|
439
|
+
| `pathDictionary.test.js` | Path encoding and decoding |
|
|
440
|
+
| `compression.test.js` | Brotli compression effectiveness |
|
|
441
|
+
| `full-pipeline.test.js` | End-to-end compression + encryption round-trip |
|
|
442
|
+
| `smartBatching.test.js` | Rolling average, batch limits, size verification |
|
|
443
|
+
| `config.test.js` | Configuration file creation, loading, hot-reload |
|
|
444
|
+
| `index.test.js` | Plugin lifecycle, schema validation |
|
|
445
|
+
| `webapp.test.js` | Web UI metrics and API endpoints |
|
|
446
|
+
| `integration-pipe.test.js` | Full input → backend → frontend data flow |
|
|
447
|
+
|
|
448
|
+
Run a specific test suite:
|
|
449
|
+
|
|
450
|
+
```bash
|
|
451
|
+
npm test -- crypto.test.js
|
|
452
|
+
npm test -- full-pipeline.test.js
|
|
453
|
+
npm test -- --coverage
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Technical Reference
|
|
457
|
+
|
|
458
|
+
**Packet format:**
|
|
459
|
+
|
|
460
|
+
```
|
|
461
|
+
[IV (12 bytes)][Encrypted Data][Auth Tag (16 bytes)]
|
|
462
|
+
Total overhead: 28 bytes per packet
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
**Compression pipeline (detailed):**
|
|
466
|
+
|
|
467
|
+
```
|
|
468
|
+
Client side:
|
|
469
|
+
JSON.stringify(delta) → Serialization
|
|
470
|
+
→ [pathDictionary.encode()] → Optional: numeric path IDs
|
|
471
|
+
→ [msgpack.encode()] → Optional: binary format
|
|
472
|
+
→ brotli.compress(quality=10) → Maximum compression
|
|
473
|
+
→ encryptBinary(key) → AES-256-GCM
|
|
474
|
+
→ UDP send
|
|
475
|
+
|
|
476
|
+
Server side:
|
|
477
|
+
UDP receive
|
|
478
|
+
→ decryptBinary(key) → Verify + decrypt
|
|
479
|
+
→ brotli.decompress()
|
|
480
|
+
→ [msgpack.decode()]
|
|
481
|
+
→ [pathDictionary.decode()]
|
|
482
|
+
→ JSON.parse()
|
|
483
|
+
→ Signal K handleMessage()
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
**Smart batching constants:**
|
|
487
|
+
|
|
488
|
+
| Constant | Value | Purpose |
|
|
489
|
+
|----------|-------|---------|
|
|
490
|
+
| Safety margin | 85% | Target 85% of MTU (1190 bytes effective) |
|
|
491
|
+
| Smoothing factor | 0.2 | Rolling average weight (20% new, 80% old) |
|
|
492
|
+
| Initial estimate | 200 bytes | Starting bytes-per-delta assumption |
|
|
493
|
+
| Min deltas | 1 | Always send at least 1 delta |
|
|
494
|
+
| Max deltas | 50 | Cap to prevent excessive batching latency |
|
|
495
|
+
|
|
496
|
+
**Performance characteristics:**
|
|
497
|
+
|
|
498
|
+
| Metric | Value |
|
|
499
|
+
|--------|-------|
|
|
500
|
+
| Compression ratio | 85–97% on typical Signal K data |
|
|
501
|
+
| Packet latency | 20–30 ms (serialize → compress → encrypt) |
|
|
502
|
+
| Throughput | 10–100 Hz update rates |
|
|
503
|
+
| Memory | Constant O(1) with circular buffers |
|
|
504
|
+
|
|
505
|
+
### Contributing
|
|
506
|
+
|
|
507
|
+
1. Fork the repository
|
|
508
|
+
2. Create a feature branch: `git checkout -b feature/name`
|
|
509
|
+
3. Make changes and add tests
|
|
510
|
+
4. Run `npm test` and `npm run lint` (all must pass)
|
|
511
|
+
5. Run `npm run build` (must succeed)
|
|
512
|
+
6. Commit with clear messages using conventional format
|
|
513
|
+
7. Submit a pull request
|
|
514
|
+
|
|
515
|
+
**Requirements for all contributions:**
|
|
516
|
+
- All 209 tests pass
|
|
517
|
+
- No ESLint errors or warnings
|
|
518
|
+
- Code formatted with Prettier
|
|
519
|
+
- Test coverage for new features
|
|
520
|
+
- README updated if adding features
|
|
521
|
+
|
|
522
|
+
**Commit message format:**
|
|
523
|
+
|
|
524
|
+
```
|
|
525
|
+
type: description
|
|
526
|
+
|
|
527
|
+
Types: feat, fix, docs, style, refactor, perf, test, chore
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## License
|
|
533
|
+
|
|
534
|
+
MIT License — Copyright (c) 2024 Karl-Erik Gustafsson
|
|
535
|
+
|
|
536
|
+
See [LICENSE](LICENSE) file for details.
|
|
Binary file
|
package/doc/datarate.jpg
ADDED
|
Binary file
|