signalk-webhook-bridge 2.0.0

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/README.md ADDED
@@ -0,0 +1,358 @@
1
+ # Webhook Bridge
2
+
3
+ Webhook Bridge is a Signal K server plugin for sending selected vessel data to an external HTTP webhook at a configurable interval.
4
+
5
+ Choose the Signal K data paths you want to send, assign simple field names, select your preferred output units, and Webhook Bridge will deliver them as a JSON payload to your endpoint.
6
+
7
+ If the webhook is unavailable, data is stored locally in a persistent queue and automatically delivered in order when the connection returns.
8
+
9
+ ## Features
10
+
11
+ - Send selected Signal K data to any HTTP webhook
12
+ - Choose from Signal K paths currently available on the server
13
+ - Assign custom field names for the outgoing payload
14
+ - Convert supported values into useful output units
15
+ - Configurable delivery interval
16
+ - Optional Bearer token authentication
17
+ - Persistent offline queue using SQLite
18
+ - FIFO delivery preserves the original order of queued updates
19
+ - Queued data survives Signal K and system restarts
20
+ - Automatic retry when the webhook becomes available again
21
+ - Manual **Retry Now** control
22
+ - Live delivery and queue status in the plugin configuration screen
23
+ - Values are sent at their available precision without artificial rounding
24
+
25
+ ## How it works
26
+
27
+ Webhook Bridge periodically takes a snapshot of the Signal K paths you have configured.
28
+
29
+ The snapshot is written to the local queue **before** delivery is attempted. This means the data is safely queued even if the network connection or receiving server is unavailable at the time of capture.
30
+
31
+ Webhook Bridge then attempts to deliver the oldest queued entry first.
32
+
33
+ An entry is removed from the queue only after the receiving webhook returns a successful HTTP response. If delivery fails, the entry remains in the queue and later entries wait behind it, preserving chronological order.
34
+
35
+ When connectivity returns, the backlog is automatically delivered oldest first.
36
+
37
+ ## Configuration
38
+
39
+ Open **Server → Plugin Config → Webhook Bridge** in the Signal K administration interface.
40
+
41
+ ### Webhook URL
42
+
43
+ Enter the HTTP or HTTPS endpoint that should receive the data.
44
+
45
+ For example:
46
+
47
+ ```text
48
+ https://example.com/api/vessel-data
49
+ ```
50
+
51
+ ### Authentication Key
52
+
53
+ An optional authentication key can be supplied.
54
+
55
+ When configured, Webhook Bridge sends it using the HTTP `Authorization` header as a Bearer token:
56
+
57
+ ```text
58
+ Authorization: Bearer YOUR_KEY
59
+ ```
60
+
61
+ ### Send Interval
62
+
63
+ Sets the interval, in minutes, between data snapshots.
64
+
65
+ Each snapshot is stored in the local queue before Webhook Bridge attempts to send it.
66
+
67
+ ### Signal K Data Paths
68
+
69
+ Add the Signal K values that you want to include in each webhook update.
70
+
71
+ For each path you can configure:
72
+
73
+ **Signal K Path**
74
+ The source value in Signal K, for example:
75
+
76
+ ```text
77
+ navigation.speedOverGround
78
+ ```
79
+
80
+ **Webhook Field Name**
81
+ The name that will be used for the value in the outgoing JSON, for example:
82
+
83
+ ```text
84
+ speed
85
+ ```
86
+
87
+ **Output Units**
88
+ Where supported, the Signal K value can be converted before transmission.
89
+
90
+ The available conversion options depend on the native units of the selected Signal K path.
91
+
92
+ ## Supported unit conversions
93
+
94
+ Webhook Bridge currently recognises the following native Signal K units:
95
+
96
+ | Native unit | Available output |
97
+ | --- | --- |
98
+ | `m/s` | Native, knots, km/h, mph |
99
+ | `rad` | Native, degrees |
100
+ | `m` | Native, metres, feet |
101
+ | `K` | Native, Celsius, Fahrenheit |
102
+ | `Pa` | Native, hPa, mbar |
103
+
104
+ Paths using other units can still be sent using their native value.
105
+
106
+ Webhook Bridge does not deliberately round converted values. This allows the receiving application to decide how much precision it requires.
107
+
108
+ ## Payload Format
109
+
110
+ Webhook Bridge sends data to the configured URL as an HTTP `POST` request with a JSON body.
111
+
112
+ Each Signal K path configured in the plugin becomes a top-level field in the JSON object. The field name is taken from the **Webhook Field Name** entered in the plugin configuration.
113
+
114
+ For example, if the following paths are configured:
115
+
116
+ | Signal K Path | Webhook Field Name | Output Units |
117
+ | --- | --- | --- |
118
+ | `navigation.speedOverGround` | `speed` | Knots |
119
+ | `environment.depth.belowTransducer` | `depth` | Native |
120
+
121
+ the webhook may receive:
122
+
123
+ ```json
124
+ {
125
+ "timestamp": "2026-09-13T10:15:00.000Z",
126
+ "speed": 5.649988373552611,
127
+ "depth": 12.8,
128
+ "units": {
129
+ "speed": "kn",
130
+ "depth": "m"
131
+ }
132
+ }
133
+ ```
134
+
135
+ ### Timestamp
136
+
137
+ Every request contains a `timestamp` field in ISO 8601 UTC format:
138
+
139
+ ```json
140
+ "timestamp": "2026-09-13T10:15:00.000Z"
141
+ ```
142
+
143
+ This is the time the snapshot was **captured and added to the local queue**, not necessarily the time it was delivered.
144
+
145
+ This distinction is important when a webhook has been unavailable. Queued updates retain their original capture timestamps when they are subsequently delivered.
146
+
147
+ ### Values
148
+
149
+ Values are sent as JSON values rather than Signal K value objects.
150
+
151
+ For example:
152
+
153
+ ```json
154
+ "speed": 5.649988373552611
155
+ ```
156
+
157
+ rather than:
158
+
159
+ ```json
160
+ "speed": {
161
+ "value": 5.649988373552611
162
+ }
163
+ ```
164
+
165
+ Webhook Bridge does **not round numeric values**. Converted values are sent at the precision produced by the conversion.
166
+
167
+ ### Units
168
+
169
+ Every payload contains a `units` object identifying the units used for each configured field:
170
+
171
+ ```json
172
+ "units": {
173
+ "speed": "kn",
174
+ "depth": "m"
175
+ }
176
+ ```
177
+
178
+ If **Native** is selected, the unit reported by Signal K metadata is used.
179
+
180
+ If another output unit is selected, Webhook Bridge converts the value before sending it and reports the selected output unit.
181
+
182
+ Common output labels include:
183
+
184
+ | Output unit | Payload label |
185
+ | --- | --- |
186
+ | Knots | `kn` |
187
+ | Kilometres per hour | `km/h` |
188
+ | Miles per hour | `mph` |
189
+ | Metres | `m` |
190
+ | Feet | `ft` |
191
+ | Degrees | `deg` |
192
+ | Celsius | `degC` |
193
+ | Fahrenheit | `degF` |
194
+ | Hectopascals | `hPa` |
195
+ | Millibars | `mbar` |
196
+
197
+ ### Authentication
198
+
199
+ If an **Authentication Key** is configured, Webhook Bridge sends it as a Bearer token in the HTTP `Authorization` header:
200
+
201
+ ```http
202
+ Authorization: Bearer your-authentication-key
203
+ ```
204
+
205
+ If no Authentication Key is configured, the `Authorization` header is omitted.
206
+
207
+ The request body is sent as JSON with:
208
+
209
+ ```http
210
+ Content-Type: application/json
211
+ ```
212
+
213
+ ### Successful Delivery
214
+
215
+ Your webhook should return an HTTP **2xx status code** when the payload has been successfully received and accepted.
216
+
217
+ Only after a successful response is the corresponding update removed from Webhook Bridge's local queue.
218
+
219
+ ### Failed Delivery
220
+
221
+ If the webhook cannot be reached, returns an unsuccessful HTTP response, or another delivery error occurs, the queued update is **not deleted**.
222
+
223
+ Webhook Bridge retains it locally and attempts delivery again later.
224
+
225
+ Queued updates are delivered in **FIFO order (oldest first)**. This means that after an outage, the receiving system may receive several requests in succession as Webhook Bridge works through the backlog.
226
+
227
+ Each request retains its original capture `timestamp`, allowing the receiving system to determine when the data was recorded rather than when it eventually arrived.
228
+
229
+ ### Receiving the Webhook
230
+
231
+ The receiving application only needs to:
232
+
233
+ 1. Accept HTTP `POST` requests at the configured URL.
234
+ 2. Parse the request body as JSON.
235
+ 3. Optionally validate the Bearer token if authentication is configured.
236
+ 4. Process or store the supplied values.
237
+ 5. Return a `2xx` HTTP response only when the payload has been successfully accepted.
238
+
239
+ Because field names are user-configurable, receiving applications should not assume particular names such as `speed` or `depth`. They should be written to handle the field names configured for that Webhook Bridge installation.
240
+
241
+ ## Offline operation and queueing
242
+
243
+ Webhook Bridge is designed for installations where internet connectivity may be intermittent.
244
+
245
+ This is particularly useful aboard vessels where Signal K may continue collecting data while the connection to a shore-based server is unavailable.
246
+
247
+ Every snapshot is written to a persistent SQLite queue before transmission is attempted.
248
+
249
+ If delivery fails:
250
+
251
+ 1. The snapshot remains in the queue.
252
+ 2. New snapshots continue to be added at the configured interval.
253
+ 3. Webhook Bridge periodically attempts delivery again.
254
+ 4. When the webhook becomes available, queued entries are delivered oldest first.
255
+ 5. An entry is deleted only after successful delivery.
256
+
257
+ The queue is persistent, so queued entries are retained if Signal K or the host system is restarted.
258
+
259
+ There is intentionally no configurable queue-size limit. The practical limit is the storage available on the host system.
260
+
261
+ ## Status
262
+
263
+ The configuration screen provides live information about the webhook connection and local queue, including:
264
+
265
+ - Current delivery state
266
+ - Number of entries waiting
267
+ - Last data capture
268
+ - Last successful delivery
269
+ - Last delivery error, when applicable
270
+
271
+ The status display updates automatically.
272
+
273
+ The **Retry Now** button can be used to immediately attempt delivery of the existing queue. It does **not** create an additional data snapshot.
274
+
275
+ ## HTTP responses
276
+
277
+ Webhook Bridge considers a request successfully delivered when the receiving server returns a successful HTTP response.
278
+
279
+ If the receiving server returns an error response, or the request cannot be completed, the queued entry is retained for another attempt.
280
+
281
+ Receivers should therefore return a successful HTTP status only once they have accepted the payload.
282
+
283
+ ## Requirements
284
+
285
+ - Signal K Server
286
+ - Node.js 22.5 or later
287
+
288
+ Node.js 22.5+ is required because Webhook Bridge uses the built-in `node:sqlite` module for persistent queue storage.
289
+
290
+ ## Installation
291
+
292
+ Install **Webhook Bridge** through the Signal K AppStore.
293
+
294
+ After installation:
295
+
296
+ 1. Enable the plugin.
297
+ 2. Open its configuration page.
298
+ 3. Enter your webhook URL.
299
+ 4. Add the Signal K paths you want to send.
300
+ 5. Choose field names and output units.
301
+ 6. Set the required send interval.
302
+ 7. Save the configuration.
303
+
304
+ The status panel can then be used to confirm that data is being captured and delivered.
305
+
306
+ ## Development
307
+
308
+ Clone the repository and install the dependencies:
309
+
310
+ ```bash
311
+ npm install
312
+ ```
313
+
314
+ Build the configuration interface:
315
+
316
+ ```bash
317
+ npm run build
318
+ ```
319
+
320
+ Run the automated tests:
321
+
322
+ ```bash
323
+ npm test
324
+ ```
325
+
326
+ Before publishing a release, it is also recommended to run:
327
+
328
+ ```bash
329
+ npm audit
330
+ npm pack --dry-run
331
+ ```
332
+
333
+ The built configuration interface is included with the published package; the plugin does not rely on an install-time build step.
334
+
335
+ ## Data storage
336
+
337
+ The persistent webhook queue is stored within the plugin's Signal K data directory using `app.getDataDirPath()`.
338
+
339
+ Webhook Bridge does not require a separate database server.
340
+
341
+ Authentication keys are configuration values and are not included in webhook status responses.
342
+
343
+ ## Licence
344
+
345
+ Copyright © 2026 Matt Barraud.
346
+
347
+ Webhook Bridge is free software licensed under the GNU General Public License v3.0 or later. See [LICENSE](LICENSE) for details.
348
+
349
+ ## Author
350
+
351
+ Developed by Matt Barraud.
352
+
353
+ ## Source
354
+
355
+ Source code, issues and releases:
356
+
357
+ [github.com/50North4West/signalk-webhook-bridge](https://github.com/50North4West/signalk-webhook-bridge)
358
+
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "signalk-webhook-bridge",
3
+ "version": "2.0.0",
4
+ "description": "Send selected Signal K data paths to an external webhook with unit conversion, persistent queueing and automatic retry.",
5
+ "main": "plugin/index.js",
6
+ "scripts": {
7
+ "build": "webpack --mode production",
8
+ "dev": "webpack --mode development --watch",
9
+ "test": "node --test",
10
+ "prepublishOnly": "npm run build && npm test"
11
+ },
12
+ "keywords": [
13
+ "signalk-node-server-plugin",
14
+ "signalk-plugin-configurator",
15
+ "signalk-category-utility",
16
+ "signalk",
17
+ "webhook"
18
+ ],
19
+ "signalk-plugin-enabled-by-default": false,
20
+ "engines": {
21
+ "node": ">=22.5.0"
22
+ },
23
+ "signalk": {
24
+ "displayName": "Webhook Bridge",
25
+ "appIcon": "./assets/icon-128.png",
26
+ "screenshots": [
27
+ "./docs/screenshots/config.png"
28
+ ]
29
+ },
30
+ "author": "Matt Barraud",
31
+ "license": "GPL-3.0-or-later",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/50North4West/signalk-webhook-bridge.git"
35
+ },
36
+ "homepage": "https://github.com/50North4West/signalk-webhook-bridge#readme",
37
+ "bugs": {
38
+ "url": "https://github.com/50North4West/signalk-webhook-bridge/issues"
39
+ },
40
+ "files": [
41
+ "plugin/",
42
+ "public/",
43
+ "assets/",
44
+ "docs/screenshots/",
45
+ "README.md",
46
+ "CHANGELOG.md",
47
+ "LICENSE"
48
+ ],
49
+ "dependencies": {
50
+ "@signalk/server-admin-ui-dependencies": "^2.23.0",
51
+ "node-fetch": "^2.6.1",
52
+ "react": "^19.3.0",
53
+ "react-dom": "^19.3.0"
54
+ },
55
+ "devDependencies": {
56
+ "@babel/core": "^7.29.7",
57
+ "@babel/preset-env": "^7.29.7",
58
+ "@babel/preset-react": "^7.29.7",
59
+ "babel-loader": "^9.2.1",
60
+ "webpack": "^5.110.3",
61
+ "webpack-cli": "^7.2.3"
62
+ }
63
+ }