signalk-cli 3.0.0__tar.gz → 3.0.1__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.
Files changed (23) hide show
  1. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/PKG-INFO +45 -7
  2. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/README.md +44 -6
  3. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/pyproject.toml +10 -4
  4. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/pyproject.toml.orig +9 -5
  5. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/_arrow.py +1 -1
  6. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/_cli.py +2 -2
  7. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/history/cli.py +2 -2
  8. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/__init__.py +0 -0
  9. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/__main__.py +0 -0
  10. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/errors.py +0 -0
  11. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/history/__init__.py +0 -0
  12. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/history/__main__.py +0 -0
  13. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/history/_results.py +0 -0
  14. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/history/_time.py +0 -0
  15. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/history/api.py +0 -0
  16. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/history/output.py +0 -0
  17. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/net.py +0 -0
  18. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/py.typed +0 -0
  19. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/stream/__init__.py +0 -0
  20. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/stream/__main__.py +0 -0
  21. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/stream/api.py +0 -0
  22. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/stream/cli.py +0 -0
  23. {signalk_cli-3.0.0 → signalk_cli-3.0.1}/src/signalk_cli/stream/output.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: signalk-cli
3
- Version: 3.0.0
3
+ Version: 3.0.1
4
4
  Summary: Query SignalK v2 APIs and export data as CSV, JSON or Apache Arrow Feather from command line or as a Python API
5
5
  Keywords: signalk,sailing,marine,boating,nmea,dataframe,cli,pyarrow,nanoarrow
6
6
  Author: jey burrows
@@ -30,6 +30,11 @@ Provides-Extra: arrow
30
30
  Provides-Extra: feather
31
31
  Description-Content-Type: text/markdown
32
32
 
33
+ ---
34
+ title: SignalK CLI
35
+ description: Command line access to SignalK APIs and streaming data, for piping within console, or export to CSV, JSON or Apache Arrow Feather for dataframe analysis.
36
+ ---
37
+
33
38
  # SignalK CLI
34
39
 
35
40
  [![Rhizomatics Open Source](https://img.shields.io/badge/rhizomatics%20open%20source-lightseagreen)](https://github.com/rhizomatics)
@@ -47,7 +52,31 @@ Description-Content-Type: text/markdown
47
52
 
48
53
  Query and explore NMEA and other boat data from SignalK APIs using the command line or the Python API. Export data as CSV, Apache Arrow Feather, or JSON or use as dataframes in scripts or data notebooks.
49
54
 
50
- APIs supported:
55
+ `signalk_cli` goes beyond raw API data extraction to automatically handle metrics and 'wide' tables that bring together aggregates like 'max' or 'avg' into separate columns for simpler queries. It also has an analysis tools to summarize data variability.
56
+
57
+ <!-- termynal -->
58
+ ```
59
+ $ uv run --with signalk-cli signalk_cli.history list-providers
60
+ provider,isDefault
61
+ kip,False
62
+ signalk-parquet,True
63
+
64
+ uv run --with signalk-cli signalk_cli.history query 'environment.outside.wind.gust:max' 'environment.wind.speedApparent:avg' --duration P7D --resolution 1m
65
+ timestamp,path,value
66
+ 2026-10-03T09:11:00Z,environment.wind.speedApparent,5.8
67
+ 2026-10-03T09:12:00Z,environment.outside.wind.gust,45.36699999999996
68
+ 2026-10-03T09:12:00Z,environment.wind.speedApparent,5.8
69
+ 2026-10-03T09:13:00Z,environment.outside.wind.gust,15.317000000000009
70
+
71
+ uv run --with signalk-cli signalk_cli.stream deltas 'environment.outside.wind.*' --follow
72
+ timestamp,context,source,path,value
73
+ 2026-10-03T09:08:21.042Z,vessels.urn:mrn:signalk:uuid:64f1567b-2fc2-474f-8b23-4e9c43b61ffb,simulator.0,environment.outside.wind.gust,44.29449999999997
74
+ 2026-10-03T09:08:23.042Z,vessels.urn:mrn:signalk:uuid:64f1567b-2fc2-474f-8b23-4e9c43b61ffb,simulator.0,environment.outside.wind.gust,45.29449999999997
75
+ ...
76
+
77
+ ```
78
+
79
+ ## APIs supported:
51
80
 
52
81
  ### [SignalK v2 History API](https://demo.signalk.org/documentation/Developing/REST_APIs/History_API.html).
53
82
 
@@ -98,7 +127,7 @@ cd signalk-cli
98
127
  uv sync
99
128
  ```
100
129
 
101
- ## Temporary Installation
130
+ ## Use without Installing
102
131
 
103
132
  Use `uv` to run without installing the module permanently, for example:
104
133
 
@@ -110,6 +139,12 @@ uv run --with signalk-cli signalk_cli.history list-providers
110
139
  uv run --with signalk-cli signalk_cli.stream deltas navigation.position --follow
111
140
  ```
112
141
 
142
+ Wildcards to follow multiple paths need to be quoted
143
+
144
+ ```bash
145
+ uv run --with signalk-cli signalk_cli.stream deltas 'environment.outside.wind.*' --follow
146
+ ```
147
+
113
148
  ## Python library
114
149
 
115
150
  Everything the CLI does is also available from Python, returning tables that load straight into polars, pandas, pyarrow or DuckDB:
@@ -154,6 +189,7 @@ Commands:
154
189
  query Query history and write results as CSV, Feather, or JSON.
155
190
  ```
156
191
 
192
+
157
193
  ## Commands
158
194
 
159
195
 
@@ -473,11 +509,9 @@ python -m signalk_cli.stream deltas [OPTIONS] [PATH...]
473
509
  ```
474
510
 
475
511
  By default, prints the next delta message and exits — useful for a quick check.
476
- Use `--follow` to keep tailing until interrupted with Ctrl-C, optionally capped
477
- with `--count`.
512
+ Use `--follow` to keep tailing until interrupted with Ctrl-C, optionally capped with `--count`.
478
513
 
479
- **PATH** arguments are sent verbatim to the server as an explicit subscription,
480
- one per path. They may be literal SignalK paths (e.g. `navigation.speedOverGround`)
514
+ **PATH** arguments are sent verbatim to the server as an explicit subscription, one per path. They may be literal SignalK paths (e.g. `navigation.speedOverGround`)
481
515
  or use the SignalK subscription wildcard `*`, matched server-side per the
482
516
  [Subscription Protocol](https://signalk.org/specification/1.8.2/doc/subscription_protocol.html)
483
517
  — unlike `history`'s PATH patterns, which the client resolves by matching
@@ -621,3 +655,7 @@ Typical combinations:
621
655
  ## Default caching
622
656
 
623
657
  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.
658
+
659
+ ## Too Much Streaming Data
660
+
661
+ If the data is too noisy, like GPS positions with dubious centimeter differences, then [signalk-delta-squelch-plugin](https://github.com/rhizomatics/signalk-delta-squelch-plugin) can cut this down hugely, and also filter out GPS glitches that suggest your boat moves at warp speed.
@@ -1,3 +1,8 @@
1
+ ---
2
+ title: SignalK CLI
3
+ description: Command line access to SignalK APIs and streaming data, for piping within console, or export to CSV, JSON or Apache Arrow Feather for dataframe analysis.
4
+ ---
5
+
1
6
  # SignalK CLI
2
7
 
3
8
  [![Rhizomatics Open Source](https://img.shields.io/badge/rhizomatics%20open%20source-lightseagreen)](https://github.com/rhizomatics)
@@ -15,7 +20,31 @@
15
20
 
16
21
  Query and explore NMEA and other boat data from SignalK APIs using the command line or the Python API. Export data as CSV, Apache Arrow Feather, or JSON or use as dataframes in scripts or data notebooks.
17
22
 
18
- APIs supported:
23
+ `signalk_cli` goes beyond raw API data extraction to automatically handle metrics and 'wide' tables that bring together aggregates like 'max' or 'avg' into separate columns for simpler queries. It also has an analysis tools to summarize data variability.
24
+
25
+ <!-- termynal -->
26
+ ```
27
+ $ uv run --with signalk-cli signalk_cli.history list-providers
28
+ provider,isDefault
29
+ kip,False
30
+ signalk-parquet,True
31
+
32
+ uv run --with signalk-cli signalk_cli.history query 'environment.outside.wind.gust:max' 'environment.wind.speedApparent:avg' --duration P7D --resolution 1m
33
+ timestamp,path,value
34
+ 2026-10-03T09:11:00Z,environment.wind.speedApparent,5.8
35
+ 2026-10-03T09:12:00Z,environment.outside.wind.gust,45.36699999999996
36
+ 2026-10-03T09:12:00Z,environment.wind.speedApparent,5.8
37
+ 2026-10-03T09:13:00Z,environment.outside.wind.gust,15.317000000000009
38
+
39
+ uv run --with signalk-cli signalk_cli.stream deltas 'environment.outside.wind.*' --follow
40
+ timestamp,context,source,path,value
41
+ 2026-10-03T09:08:21.042Z,vessels.urn:mrn:signalk:uuid:64f1567b-2fc2-474f-8b23-4e9c43b61ffb,simulator.0,environment.outside.wind.gust,44.29449999999997
42
+ 2026-10-03T09:08:23.042Z,vessels.urn:mrn:signalk:uuid:64f1567b-2fc2-474f-8b23-4e9c43b61ffb,simulator.0,environment.outside.wind.gust,45.29449999999997
43
+ ...
44
+
45
+ ```
46
+
47
+ ## APIs supported:
19
48
 
20
49
  ### [SignalK v2 History API](https://demo.signalk.org/documentation/Developing/REST_APIs/History_API.html).
21
50
 
@@ -66,7 +95,7 @@ cd signalk-cli
66
95
  uv sync
67
96
  ```
68
97
 
69
- ## Temporary Installation
98
+ ## Use without Installing
70
99
 
71
100
  Use `uv` to run without installing the module permanently, for example:
72
101
 
@@ -78,6 +107,12 @@ uv run --with signalk-cli signalk_cli.history list-providers
78
107
  uv run --with signalk-cli signalk_cli.stream deltas navigation.position --follow
79
108
  ```
80
109
 
110
+ Wildcards to follow multiple paths need to be quoted
111
+
112
+ ```bash
113
+ uv run --with signalk-cli signalk_cli.stream deltas 'environment.outside.wind.*' --follow
114
+ ```
115
+
81
116
  ## Python library
82
117
 
83
118
  Everything the CLI does is also available from Python, returning tables that load straight into polars, pandas, pyarrow or DuckDB:
@@ -122,6 +157,7 @@ Commands:
122
157
  query Query history and write results as CSV, Feather, or JSON.
123
158
  ```
124
159
 
160
+
125
161
  ## Commands
126
162
 
127
163
 
@@ -441,11 +477,9 @@ python -m signalk_cli.stream deltas [OPTIONS] [PATH...]
441
477
  ```
442
478
 
443
479
  By default, prints the next delta message and exits — useful for a quick check.
444
- Use `--follow` to keep tailing until interrupted with Ctrl-C, optionally capped
445
- with `--count`.
480
+ Use `--follow` to keep tailing until interrupted with Ctrl-C, optionally capped with `--count`.
446
481
 
447
- **PATH** arguments are sent verbatim to the server as an explicit subscription,
448
- one per path. They may be literal SignalK paths (e.g. `navigation.speedOverGround`)
482
+ **PATH** arguments are sent verbatim to the server as an explicit subscription, one per path. They may be literal SignalK paths (e.g. `navigation.speedOverGround`)
449
483
  or use the SignalK subscription wildcard `*`, matched server-side per the
450
484
  [Subscription Protocol](https://signalk.org/specification/1.8.2/doc/subscription_protocol.html)
451
485
  — unlike `history`'s PATH patterns, which the client resolves by matching
@@ -589,3 +623,7 @@ Typical combinations:
589
623
  ## Default caching
590
624
 
591
625
  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.
626
+
627
+ ## Too Much Streaming Data
628
+
629
+ If the data is too noisy, like GPS positions with dubious centimeter differences, then [signalk-delta-squelch-plugin](https://github.com/rhizomatics/signalk-delta-squelch-plugin) can cut this down hugely, and also filter out GPS glitches that suggest your boat moves at warp speed.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "signalk-cli"
3
- version = "3.0.0"
3
+ version = "3.0.1"
4
4
  description = "Query SignalK v2 APIs and export data as CSV, JSON or Apache Arrow Feather from command line or as a Python API"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -62,11 +62,12 @@ dev = [
62
62
  "pytest-xdist",
63
63
  "mypy",
64
64
  "coverage",
65
+ "bandit",
65
66
  "genbadge[all]",
66
67
  "icdiff",
67
68
  "codespell",
68
- "polars>=1.44.2,<2.0.0",
69
- "duckdb>=1.5.5,<2.0.0",
69
+ "polars>=1.44.2,<3.0.0",
70
+ "duckdb>=1.5.5,<3.0.0",
70
71
  "pandas>=3.0.6,<4.0.0",
71
72
  ]
72
73
  docs = [
@@ -77,8 +78,11 @@ docs = [
77
78
  "mkdocs-pagetree-plugin",
78
79
  "mkdocs-coverage",
79
80
  "pymdown-extensions",
81
+ "mkdocs-homepage-copier",
80
82
  "mkdocs-meta-descriptions-plugin",
81
83
  "pngquant",
84
+ "termynal",
85
+ "pillow>=13.0.0",
82
86
  "mkdocs-htmlproofer-plugin",
83
87
  "mkdocs-llmstxt>=0.5.0,<0.6.0",
84
88
  "mkdocstrings[python]>=1.0.6,<2.0.0",
@@ -143,6 +147,8 @@ exclude-newer = "7 days"
143
147
  add-bounds = "major"
144
148
 
145
149
  [tool.uv.exclude-newer-package]
150
+ certifi = false
151
+ pillow = false
146
152
  uv_build = "2 days"
147
153
 
148
154
  [tool.uv.build-backend]
@@ -150,5 +156,5 @@ module-root = "src"
150
156
  module-name = "signalk_cli"
151
157
 
152
158
  [build-system]
153
- requires = ["uv_build>=0.12.0,<0.13.0"]
159
+ requires = ["uv_build>=0.12.0"]
154
160
  build-backend = "uv_build"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "signalk-cli"
3
- version = "3.0.0"
3
+ version = "3.0.1"
4
4
  description = "Query SignalK v2 APIs and export data as CSV, JSON or Apache Arrow Feather from command line or as a Python API"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -47,11 +47,12 @@ dev = [
47
47
  "pytest-xdist",
48
48
  "mypy",
49
49
  "coverage",
50
+ "bandit",
50
51
  "genbadge[all]",
51
52
  "icdiff",
52
53
  "codespell",
53
- "polars>=1.44.2,<2.0.0",
54
- "duckdb>=1.5.5,<2.0.0",
54
+ "polars>=1.44.2,<3.0.0",
55
+ "duckdb>=1.5.5,<3.0.0",
55
56
  "pandas>=3.0.6,<4.0.0",
56
57
  ]
57
58
 
@@ -63,8 +64,11 @@ docs=[
63
64
  "mkdocs-pagetree-plugin",
64
65
  "mkdocs-coverage",
65
66
  "pymdown-extensions",
67
+ "mkdocs-homepage-copier",
66
68
  "mkdocs-meta-descriptions-plugin",
67
69
  "pngquant",
70
+ "termynal",
71
+ "pillow>=13.0.0",
68
72
  "mkdocs-htmlproofer-plugin",
69
73
  "mkdocs-llmstxt>=0.5.0,<0.6.0",
70
74
  "mkdocstrings[python]>=1.0.6,<2.0.0",
@@ -136,11 +140,11 @@ allowed-unresolved-imports = ["pyarrow", "pyarrow.**"]
136
140
  compile-bytecode = true
137
141
  managed = true
138
142
  exclude-newer = "7 days"
139
- exclude-newer-package = {"uv_build"="2 days"}
143
+ exclude-newer-package = {certifi=false, pillow=false,"uv_build"="2 days"}
140
144
  add-bounds = "major"
141
145
 
142
146
  [build-system]
143
- requires = ["uv_build>=0.12.0,<0.13.0"]
147
+ requires = ["uv_build>=0.12.0"]
144
148
  build-backend = "uv_build"
145
149
 
146
150
 
@@ -31,7 +31,7 @@ def _epoch_us(ts: str | datetime | None) -> int | None:
31
31
  return round(dt.timestamp() * 1_000_000)
32
32
 
33
33
 
34
- def infer_column(values: Sequence[Any]) -> tuple[list, Any]:
34
+ def infer_column(values: Sequence[Any]) -> tuple[list[str | float | bool | None], Any]:
35
35
  """Pick one Arrow type for a column of JSON values: float64, bool, or string.
36
36
 
37
37
  Numbers (and nulls) become float64, booleans stay bool, and anything else
@@ -3,7 +3,7 @@
3
3
  import contextlib
4
4
  import io
5
5
  import logging
6
- from collections.abc import Iterator
6
+ from collections.abc import Generator
7
7
 
8
8
  import click
9
9
 
@@ -38,7 +38,7 @@ def bare_option(f):
38
38
 
39
39
 
40
40
  @contextlib.contextmanager
41
- def stderr_ctx(bare: bool) -> Iterator[None]:
41
+ def stderr_ctx(bare: bool) -> Generator[None]:
42
42
  """Route library log messages to stderr for one command, or discard them all if bare."""
43
43
  handler = _ClickHandler()
44
44
  previous_level = logger.level
@@ -5,7 +5,7 @@ import csv
5
5
  import json
6
6
  import re
7
7
  import sys
8
- from collections.abc import Iterator
8
+ from collections.abc import Generator
9
9
  from datetime import UTC, datetime
10
10
  from pathlib import Path
11
11
  from urllib.parse import urlparse
@@ -92,7 +92,7 @@ def _client(
92
92
 
93
93
 
94
94
  @contextlib.contextmanager
95
- def _exit_on_error(doing: str) -> Iterator[None]:
95
+ def _exit_on_error(doing: str) -> Generator[None]:
96
96
  """Report a failed request as 'Error <doing>: <message>' and exit 1."""
97
97
  try:
98
98
  yield