signalk-cli 1.0.0__tar.gz → 1.2.0__tar.gz

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.
@@ -0,0 +1,418 @@
1
+ Metadata-Version: 2.4
2
+ Name: signalk-cli
3
+ Version: 1.2.0
4
+ Summary: Query the SignalK v2 History API and export data as CSV or Apache Arrow Feather
5
+ Keywords: signalk,sailing,marine,nmea,boating
6
+ Author: jey burrows
7
+ Author-email: jey burrows <jrb@rhizomatics.org.uk>
8
+ License-Expression: Apache-2.0
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Environment :: Console
11
+ Classifier: Natural Language :: English
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Topic :: Scientific/Engineering
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Requires-Dist: click>=8.3.3
18
+ Requires-Dist: niquests>=2.28
19
+ Requires-Dist: zeroconf>=0.149.16,<0.150.0
20
+ Requires-Dist: pyarrow>=17.0 ; extra == 'feather'
21
+ Requires-Python: >=3.13
22
+ Project-URL: Homepage, https://github.com/rhizomatics/signalk-cli
23
+ Project-URL: Repository, https://github.com/rhizomatics/signalk-cli
24
+ Project-URL: Issues, https://github.com/rhizomatics/signalk-cli/issues
25
+ Project-URL: Changelog, https://github.com/rhizomatics/signalk-cli/blob/main/CHANGELOG.md
26
+ Provides-Extra: feather
27
+ Description-Content-Type: text/markdown
28
+
29
+ # SignalK CLI
30
+
31
+ Query and explore SignalK APIs from the command line, and export data as CSV, Apache Arrow Feather, or JSON.
32
+
33
+ APIs supported:
34
+
35
+ * [SignalK v2 History API](https://signalk.org/https://demo.signalk.org/documentation/Developing/REST_APIs/History_API.html)
36
+
37
+ ## Installation
38
+
39
+ ### PyPi
40
+
41
+ ```pip install signalk-cli``` or ```uv pip install signalk-cli```
42
+
43
+ For Apache Arrow Feather export, use the optional dependency: ```pip install 'signalk-cli[feather]'```
44
+
45
+ ### Local Copy
46
+
47
+ Requires Python 3.13+ and [uv](https://docs.astral.sh/uv/).
48
+
49
+ ```bash
50
+ git clone https://github.com/rhizomatics/signalk-cli
51
+ cd signalk-cli
52
+ uv sync
53
+ ```
54
+
55
+ ## Temporary Installation
56
+
57
+ Use `uv` to run without installing the module permanently, for example:
58
+
59
+ ```bash
60
+ uv run --with signalk-cli signalk_cli.history list-providers
61
+ ```
62
+
63
+ ## Running
64
+
65
+ Run via `python -m signalk_cli.history <command>`.
66
+
67
+ ## Determining SignalK host name
68
+
69
+ If no host name is set as an argument, the CLI will look for a `SIGNALK_HOST` environment variable, and failing that attempt to automatically discover
70
+ the host using mDNS (aka Bonjour) and locally cached (see [Default Caching](#default-caching)).
71
+
72
+ ```bash
73
+ export SIGNALK_HOST=192.168.6.99 # http:// is added automatically if omitted
74
+ ```
75
+
76
+ ## Built-in Help
77
+
78
+ Run with no arguments to list available commands:
79
+
80
+ ```
81
+ $ python -m signalk_cli.history
82
+ Usage: signalk_cli.history [OPTIONS] COMMAND [ARGS]...
83
+
84
+ SignalK v2 history CLI.
85
+
86
+ Commands:
87
+ cardinality Compute per-path value statistics for the given time range.
88
+ list-contexts List contexts that have historical data for the given time range.
89
+ list-paths List paths that have data for the given time range.
90
+ list-providers List registered history providers.
91
+ query Query history and write results as CSV, Feather, or JSON.
92
+ ```
93
+
94
+ ## Commands
95
+
96
+
97
+ ### `query`
98
+
99
+ Fetch historical values for one or more paths and write to stdout (default) or a file. Aggregation can be controlled in the same way as the History API itself
100
+ or a default form where `min_value`,`avg_value` and `max_value` are returned for every period.
101
+
102
+ ```
103
+ python -m signalk_cli.history query [OPTIONS] PATH...
104
+ ```
105
+
106
+ **PATH** arguments may be:
107
+ - **Literal paths** — e.g. `navigation.speedOverGround`
108
+ - **Regex / glob patterns** — any argument containing metacharacters (`*`, `.`, `[`, `(`, etc.) is matched against the server's `/paths` endpoint. Bare `*` is treated as a glob wildcard.
109
+ - **Inline path specs** — `path:method` or `path:method:param`, e.g. `navigation.speedOverGround:sma:5`. These pass through to the server unchanged.
110
+
111
+ #### Options
112
+
113
+ | Option | Default | Description |
114
+ |---|---|---|
115
+ | `--host` | `$SIGNALK_HOST` | Server base URL. `http://` added if scheme omitted. |
116
+ | `--from DATETIME` | — | Start of range (ISO 8601, e.g. `2026-05-26T00:00:00Z`) |
117
+ | `--to DATETIME` | now | End of range (ISO 8601) |
118
+ | `--duration DURATION` | — | Duration as seconds (`3600`) or ISO 8601 duration (`PT1H`, `P1D`, `P1W`). Combined with `--from` or `--to`, or alone for a window ending now. |
119
+ | `--resolution RESOLUTION` | server default | Sample window size: seconds or time expression (`1s`, `1m`, `1h`, `1d`). |
120
+ | `-c, --context TEXT` | `vessels.self` | SignalK context |
121
+ | `--provider TEXT` | fetched & cached | History provider plugin name, for example `signalk-parquet` |
122
+ | `--no-cache` | — | Ignore the cached default provider |
123
+ | `--aggregation / --agg` | — | Aggregation method: `average`, `min`, `max`, `first`, `last`, `mid`, `middle_index`, `sma`, `ema`. Omit for wide mode (see below). |
124
+ | `--samples N` | server default | Sample count for `--agg sma` |
125
+ | `--alpha FLOAT` | server default | Alpha (0–1) for `--agg ema` |
126
+ | `--format [csv\|feather\|json\|raw]` | from extension, else csv | Output format. Auto-detected from `.feather`/`.arrow`/`.fea` and `.json` extensions. `feather` requires `pip install 'signalk-cli[feather]'`. |
127
+ | `--no-header` | — | Suppress the CSV header row |
128
+ | `-o / --output [FILE]` | stdout | Write to a file. Omit the filename (`--output` alone) to auto-name as `signalk-history-<server>-<timestamp>.<ext>`. Use `-` for stdout explicitly. Feather cannot be written to stdout. |
129
+ | `--pretty` | — | Pretty-print JSON output with indentation. **Warning:** disables streaming; the full response is buffered in memory before writing. |
130
+ | `--bare` | — | Print to stdout with **no informational messages** (server, provider, progress, row count). Ideal for piping to other tools. Not supported with feather. |
131
+
132
+ If no time range is given, the tool defaults to the hour ending now.
133
+
134
+ #### Duration normalisation
135
+
136
+ SignalK only accepts time-only ISO 8601 durations (`PT1H`, `PT30M`, etc.). Durations with date components (`P1D`, `P1W`, `P1Y`, `P1M`) are automatically expanded to explicit `--from`/`--to` timestamps:
137
+
138
+ - `--duration P1D` alone → `from = now − 1 day`, `to = now`
139
+ - `--from T --duration P1D` → `to = T + 1 day`
140
+ - `--to T --duration P1W` → `from = T − 1 week`
141
+
142
+ Integer seconds (`3600`) are passed through unchanged.
143
+
144
+ #### Output formats
145
+
146
+ **csv** (default): tabular output as comma-separated values.
147
+
148
+ **feather**: Apache Arrow Feather binary format, readable with pandas, Polars, R, pyarrow, etc. Requires `pip install 'signalk-cli[feather]'`. Cannot be written to stdout.
149
+
150
+ **json**: tabular records as JSON objects — same columns as CSV, formatted as a JSON array. Extension `.json` auto-selects this format.
151
+
152
+ **raw**: exact API response body as received from the server — no Python JSON parse/re-serialize. Streamed directly to stdout unless `--pretty` is used.
153
+
154
+ #### Output columns
155
+
156
+ **Wide mode** (default — no `--aggregation` and no inline specs): fetches `min`, `average`, and `max` for each scalar path and writes them as separate columns:
157
+
158
+ ```
159
+ timestamp, path, min_value, avg_value, max_value
160
+ ```
161
+
162
+ **Array-valued paths in wide mode**: paths whose values are arrays (non-scalar) cannot be meaningfully aggregated with min/max/average. They are requested with a single passthrough method instead and the array elements are expanded into named columns. The column names depend on the path:
163
+
164
+ | Path pattern | Array length | Columns |
165
+ |---|---|---|
166
+ | `navigation.*.position` or `navigation.position` | 2 | `longitude`, `latitude` |
167
+ | any other array path | N | `value_0`, `value_1`, …, `value_N-1` |
168
+
169
+ Example for `navigation.position`:
170
+
171
+ ```
172
+ timestamp, path, latitude, longitude
173
+ ```
174
+
175
+ **Narrow mode** (explicit `--aggregation` or inline path specs): single value column:
176
+
177
+ ```
178
+ timestamp, path, value
179
+ ```
180
+
181
+ Structured values (positions, arrays) are JSON-encoded in the value column.
182
+
183
+ #### Examples
184
+
185
+ ```bash
186
+ # Last hour of speed — wide mode (min/max/avg columns), printed to stdout
187
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
188
+ navigation.speedOverGround
189
+
190
+ # Write to auto-named file
191
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H --output \
192
+ navigation.speedOverGround
193
+
194
+ # Write to named file
195
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
196
+ --output may26.csv navigation.speedOverGround
197
+
198
+ # Last day (date-component duration, auto-expanded to from/to)
199
+ python -m signalk_cli.history query --host 10.36.10.21 --duration P1D \
200
+ navigation.speedOverGround
201
+
202
+ # Simple moving average (5 samples), narrowed to one value column
203
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
204
+ --agg sma --samples 5 \
205
+ navigation.speedOverGround
206
+
207
+ # EMA with alpha 0.2
208
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
209
+ --agg ema --alpha 0.2 \
210
+ navigation.speedOverGround
211
+
212
+ # Inline spec — path:method, multiple paths with different methods
213
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
214
+ 'navigation.speedOverGround:max' 'navigation.courseOverGroundTrue:average'
215
+
216
+ # Multiple literal paths, 1-minute resolution
217
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H --resolution 1m \
218
+ navigation.speedOverGround navigation.courseOverGroundTrue
219
+
220
+ # All navigation paths, specific date range, write to named file
221
+ python -m signalk_cli.history query --host 10.36.10.21 \
222
+ --from 2026-05-26T00:00:00Z --to 2026-05-27T00:00:00Z \
223
+ --output may26.csv \
224
+ 'navigation\..*'
225
+
226
+ # Glob wildcard — all paths for the last 30 minutes as Feather (auto-named)
227
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT30M \
228
+ --format feather --output '*'
229
+
230
+ # Extension auto-selects feather format
231
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
232
+ -o out.feather navigation.speedOverGround
233
+
234
+ # Exact API response body to stdout (streamed, no informational noise)
235
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H --format raw --bare \
236
+ navigation.speedOverGround
237
+
238
+ # Pretty-printed raw JSON (buffered — avoid for large responses)
239
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
240
+ --format raw --pretty navigation.speedOverGround
241
+
242
+ # Extension auto-selects JSON format
243
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
244
+ -o out.json navigation.speedOverGround
245
+
246
+ # Suppress header, pipe to another tool
247
+ python -m signalk_cli.history query --host 10.36.10.21 --duration 3600 --no-header \
248
+ navigation.speedOverGround | cut -d, -f1,3
249
+
250
+ # --bare: pure CSV output, no informational noise — pipe-friendly
251
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H --bare \
252
+ navigation.speedOverGround | awk -F, 'NR>1 {print $2, $3}'
253
+
254
+ # Different context
255
+ python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
256
+ -c vessels.urn:mrn:imo:mmsi:123456789 navigation.speedOverGround
257
+ ```
258
+
259
+ ---
260
+
261
+ ### `cardinality`
262
+
263
+ Fetch raw values for one or more paths and compute per-path statistics. Useful for exploring a dataset before querying it.
264
+
265
+ ```
266
+ python -m signalk_cli.history cardinality [OPTIONS] PATH...
267
+ ```
268
+
269
+ PATH arguments follow the same rules as `query` (literal paths, regex/glob patterns, inline specs).
270
+
271
+ #### Output columns
272
+
273
+ | Column | Description |
274
+ |---|---|
275
+ | `path` | SignalK path |
276
+ | `distinct_values` | Count of unique values (by string representation) |
277
+ | `min` | Minimum value (scalar numeric only; blank otherwise) |
278
+ | `max` | Maximum value (scalar numeric only; blank otherwise) |
279
+ | `average` | Mean value (scalar numeric only; blank otherwise) |
280
+ | `distinct_values_2_decimal_places` | Distinct count after rounding to 2 dp (scalar only; blank otherwise) |
281
+ | `nulls` | Count of null/missing values |
282
+
283
+ For non-scalar paths (e.g. `navigation.position` which returns a lat/lon pair), `min`, `max`, `average`, and `distinct_values_2_decimal_places` are left blank; `distinct_values` still counts unique array representations.
284
+
285
+ #### Options
286
+
287
+ Accepts the same `--host`, `--from`/`--to`/`--duration`, `--resolution`, `--context`, `--provider`/`--no-cache`, `--format [csv|json]`, `--no-header`, and `--bare` options as `query`.
288
+
289
+ ```bash
290
+ # Statistics for speed over the last hour
291
+ python -m signalk_cli.history cardinality --host 10.36.10.21 --duration PT1H \
292
+ navigation.speedOverGround
293
+
294
+ # All navigation paths, last 24 hours
295
+ python -m signalk_cli.history cardinality --host 10.36.10.21 --duration P1D \
296
+ 'navigation\..*'
297
+
298
+ # JSON output
299
+ python -m signalk_cli.history cardinality --host 10.36.10.21 --duration PT1H \
300
+ --format json navigation.speedOverGround navigation.position
301
+ ```
302
+
303
+ ---
304
+
305
+ ### `list-paths`
306
+
307
+ List all SignalK paths that have recorded data in a given time range.
308
+
309
+ ```
310
+ python -m signalk_cli.history list-paths [OPTIONS]
311
+ ```
312
+
313
+ Outputs one path per line to stdout by default. Defaults to the last hour if no time range is given. Accepts the same `--from`/`--to`/`--duration`, `--provider`/`--no-cache`, `-c/--context`, and `--bare` options as `query`.
314
+
315
+ #### Options
316
+
317
+ | Option | Default | Description |
318
+ |---|---|---|
319
+ | `--format [csv\|json\|raw]` | `csv` | `csv`: one item per line with `path` header. `json`: `[{"path": ...}]`. `raw`: exact API response body. |
320
+
321
+ ```bash
322
+ # Paths recorded in the last hour
323
+ python -m signalk_cli.history list-paths --host 10.36.10.21
324
+
325
+ # Paths available on a specific day
326
+ python -m signalk_cli.history list-paths --host 10.36.10.21 \
327
+ --from 2026-05-26T00:00:00Z --to 2026-05-27T00:00:00Z
328
+
329
+ # Pipe into grep
330
+ python -m signalk_cli.history list-paths --host 10.36.10.21 --duration PT24H | grep navigation
331
+
332
+ # Exact API response body, no informational noise
333
+ python -m signalk_cli.history list-paths --host 10.36.10.21 --format raw --bare
334
+ ```
335
+
336
+ ---
337
+
338
+ ### `list-providers`
339
+
340
+ List all registered history provider plugins and identify the default. Supports `--bare` to suppress the "Server:" and provider-count lines.
341
+
342
+ ```
343
+ python -m signalk_cli.history list-providers --host 10.36.10.21
344
+ ```
345
+
346
+ Example output:
347
+
348
+ ```
349
+ provider,isDefault
350
+ signalk-parquet,True
351
+ kip,False
352
+ 2 provider(s)
353
+ ```
354
+
355
+ The default provider is used automatically when `--provider` is not specified on other commands. It is fetched once and cached in `~/.cache/signalk-cli/`.
356
+
357
+ #### Options
358
+
359
+ | Option | Default | Description |
360
+ |---|---|---|
361
+ | `--format [csv\|json\|raw]` | `csv` | `csv`: `provider,isDefault` rows. `json`: `[{"provider": ..., "isDefault": ...}]`. `raw`: exact API response body. |
362
+
363
+ ```bash
364
+ # Exact API response body, no informational noise
365
+ python -m signalk_cli.history list-providers --host 10.36.10.21 --format raw --bare
366
+ ```
367
+
368
+ ---
369
+
370
+ ### `list-contexts`
371
+
372
+ List SignalK contexts (vessels, aircraft, etc.) that have recorded data in a given time range.
373
+
374
+ ```bash
375
+ python -m signalk_cli.history list-contexts [OPTIONS]
376
+ ```
377
+
378
+ Defaults to the last hour if no time range is given.
379
+
380
+ #### Options
381
+
382
+ | Option | Default | Description |
383
+ |---|---|---|
384
+ | `--format [csv\|json\|raw]` | `csv` | `csv`: one item per line with `context` header. `json`: `[{"context": ...}]`. `raw`: exact API response body. |
385
+
386
+ ```bash
387
+ python -m signalk_cli.history list-contexts --host 10.36.10.21
388
+
389
+ python -m signalk_cli.history list-contexts --host 10.36.10.21 \
390
+ --from 2026-05-26T00:00:00Z --to 2026-05-27T00:00:00Z
391
+
392
+ # Exact API response body, no informational noise
393
+ python -m signalk_cli.history list-contexts --host 10.36.10.21 --format raw --bare
394
+ ```
395
+
396
+ ---
397
+
398
+ ## Time range
399
+
400
+ All commands that query data accept the same three time parameters. At least one of `--from` or `--duration` must be provided (or the tool supplies a one-hour default).
401
+
402
+ | Parameter | Format | Examples |
403
+ |---|---|---|
404
+ | `--from` | ISO 8601 timestamp | `2026-05-26T00:00:00Z` |
405
+ | `--to` | ISO 8601 timestamp | `2026-05-27T00:00:00Z` |
406
+ | `--duration` | ISO 8601 duration or integer seconds | `PT1H`, `PT15M`, `P1D`, `P1W`, `3600` |
407
+
408
+ Typical combinations:
409
+
410
+ - `--duration PT1H` — last hour ending now
411
+ - `--from T --duration PT1H` — hour starting at T
412
+ - `--from T1 --to T2` — explicit range
413
+ - `--duration PT1H --to T` — hour ending at T
414
+ - `--duration P1D` — last 24 hours (expanded to from/to automatically)
415
+
416
+ ## Default caching
417
+
418
+ The default history provider is fetched from the server once and cached per host in `~/.cache/signalk-history-cli/`. Pass `--no-cache` to force a fresh lookup, or `--provider <id>` to target a specific provider explicitly.