sds200 0.8.2__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.
- sds200-0.8.2/.github/ISSUE_TEMPLATE/bug_report.yml +91 -0
- sds200-0.8.2/.github/ISSUE_TEMPLATE/config.yml +8 -0
- sds200-0.8.2/.github/ISSUE_TEMPLATE/feature_request.yml +54 -0
- sds200-0.8.2/.github/PULL_REQUEST_TEMPLATE.md +25 -0
- sds200-0.8.2/.github/dependabot.yml +15 -0
- sds200-0.8.2/.github/workflows/ci.yml +69 -0
- sds200-0.8.2/.gitignore +12 -0
- sds200-0.8.2/CHANGELOG.md +195 -0
- sds200-0.8.2/CODE_OF_CONDUCT.md +27 -0
- sds200-0.8.2/CONTRIBUTING.md +108 -0
- sds200-0.8.2/LICENSE +17 -0
- sds200-0.8.2/PKG-INFO +397 -0
- sds200-0.8.2/README.md +360 -0
- sds200-0.8.2/SECURITY.md +55 -0
- sds200-0.8.2/SUPPORT.md +62 -0
- sds200-0.8.2/contrib/udev/70-uniden-sds.rules +7 -0
- sds200-0.8.2/docs/audio.md +21 -0
- sds200-0.8.2/docs/discovery-and-profiles.md +107 -0
- sds200-0.8.2/docs/fallback-profiles.md +60 -0
- sds200-0.8.2/docs/releasing.md +117 -0
- sds200-0.8.2/docs/reliability.md +76 -0
- sds200-0.8.2/docs/supported-models.md +87 -0
- sds200-0.8.2/docs/transports.md +130 -0
- sds200-0.8.2/docs/udev.md +37 -0
- sds200-0.8.2/examples/basic_info.py +8 -0
- sds200-0.8.2/examples/handheld_battery.py +10 -0
- sds200-0.8.2/examples/health_check.py +5 -0
- sds200-0.8.2/examples/live_monitor.py +9 -0
- sds200-0.8.2/examples/network_discovery.py +4 -0
- sds200-0.8.2/examples/network_monitor.py +8 -0
- sds200-0.8.2/examples/raw_monitor.py +5 -0
- sds200-0.8.2/pyproject.toml +83 -0
- sds200-0.8.2/scanner.trace +291 -0
- sds200-0.8.2/scripts/check_docs.py +98 -0
- sds200-0.8.2/sdstest.py +27 -0
- sds200-0.8.2/src/sds200/__init__.py +145 -0
- sds200-0.8.2/src/sds200/audio.py +77 -0
- sds200-0.8.2/src/sds200/cli.py +946 -0
- sds200-0.8.2/src/sds200/commands.py +222 -0
- sds200-0.8.2/src/sds200/completion.py +96 -0
- sds200-0.8.2/src/sds200/device.py +83 -0
- sds200-0.8.2/src/sds200/discovery.py +264 -0
- sds200-0.8.2/src/sds200/events.py +37 -0
- sds200-0.8.2/src/sds200/exceptions.py +42 -0
- sds200-0.8.2/src/sds200/fallback.py +438 -0
- sds200-0.8.2/src/sds200/models.py +442 -0
- sds200-0.8.2/src/sds200/monitor.py +69 -0
- sds200-0.8.2/src/sds200/network.py +660 -0
- sds200-0.8.2/src/sds200/parser.py +141 -0
- sds200-0.8.2/src/sds200/profiles.py +479 -0
- sds200-0.8.2/src/sds200/py.typed +0 -0
- sds200-0.8.2/src/sds200/radio.py +810 -0
- sds200-0.8.2/src/sds200/reliability.py +190 -0
- sds200-0.8.2/src/sds200/scanner.py +88 -0
- sds200-0.8.2/src/sds200/state.py +83 -0
- sds200-0.8.2/src/sds200/trace.py +31 -0
- sds200-0.8.2/src/sds200/transport.py +453 -0
- sds200-0.8.2/src/sds200/xml_protocol.py +78 -0
- sds200-0.8.2/tests/__init__.py +0 -0
- sds200-0.8.2/tests/fakes.py +217 -0
- sds200-0.8.2/tests/test_audio.py +18 -0
- sds200-0.8.2/tests/test_cli.py +81 -0
- sds200-0.8.2/tests/test_commands.py +45 -0
- sds200-0.8.2/tests/test_completion.py +317 -0
- sds200-0.8.2/tests/test_device.py +42 -0
- sds200-0.8.2/tests/test_discovery.py +172 -0
- sds200-0.8.2/tests/test_fallback.py +159 -0
- sds200-0.8.2/tests/test_monitor.py +38 -0
- sds200-0.8.2/tests/test_network.py +330 -0
- sds200-0.8.2/tests/test_parser.py +79 -0
- sds200-0.8.2/tests/test_profiles.py +219 -0
- sds200-0.8.2/tests/test_psi.py +101 -0
- sds200-0.8.2/tests/test_radio.py +310 -0
- sds200-0.8.2/tests/test_reliability.py +106 -0
- sds200-0.8.2/tests/test_scanner.py +47 -0
- sds200-0.8.2/tests/test_state.py +36 -0
- sds200-0.8.2/tests/test_trace.py +16 -0
- sds200-0.8.2/tests/test_transport.py +100 -0
- sds200-0.8.2/tests/test_xml_protocol.py +47 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report reproducible incorrect behavior
|
|
3
|
+
title: "[Bug]: "
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for reporting a problem. Remove private scanner and network
|
|
9
|
+
information from logs before submitting.
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: summary
|
|
12
|
+
attributes:
|
|
13
|
+
label: What happened?
|
|
14
|
+
description: Describe the observed behavior and what you expected.
|
|
15
|
+
validations:
|
|
16
|
+
required: true
|
|
17
|
+
- type: input
|
|
18
|
+
id: version
|
|
19
|
+
attributes:
|
|
20
|
+
label: sds200-python version or commit
|
|
21
|
+
placeholder: "0.5.3 or commit SHA"
|
|
22
|
+
validations:
|
|
23
|
+
required: true
|
|
24
|
+
- type: input
|
|
25
|
+
id: python
|
|
26
|
+
attributes:
|
|
27
|
+
label: Python version
|
|
28
|
+
placeholder: "3.14.4"
|
|
29
|
+
validations:
|
|
30
|
+
required: true
|
|
31
|
+
- type: input
|
|
32
|
+
id: platform
|
|
33
|
+
attributes:
|
|
34
|
+
label: Operating system
|
|
35
|
+
placeholder: "Ubuntu 26.04"
|
|
36
|
+
validations:
|
|
37
|
+
required: true
|
|
38
|
+
- type: dropdown
|
|
39
|
+
id: model
|
|
40
|
+
attributes:
|
|
41
|
+
label: Scanner model
|
|
42
|
+
options:
|
|
43
|
+
- SDS100
|
|
44
|
+
- SDS150
|
|
45
|
+
- SDS200
|
|
46
|
+
- Other or unknown
|
|
47
|
+
validations:
|
|
48
|
+
required: true
|
|
49
|
+
- type: input
|
|
50
|
+
id: firmware
|
|
51
|
+
attributes:
|
|
52
|
+
label: Scanner firmware
|
|
53
|
+
placeholder: "1.26.01"
|
|
54
|
+
validations:
|
|
55
|
+
required: true
|
|
56
|
+
- type: dropdown
|
|
57
|
+
id: transport
|
|
58
|
+
attributes:
|
|
59
|
+
label: Connection
|
|
60
|
+
options:
|
|
61
|
+
- USB serial
|
|
62
|
+
- SDS200 Ethernet UDP
|
|
63
|
+
- USB and SDS200 Ethernet
|
|
64
|
+
- Not applicable
|
|
65
|
+
validations:
|
|
66
|
+
required: true
|
|
67
|
+
- type: textarea
|
|
68
|
+
id: reproduce
|
|
69
|
+
attributes:
|
|
70
|
+
label: Reproduction steps
|
|
71
|
+
description: Include the exact command or a minimal Python example.
|
|
72
|
+
render: shell
|
|
73
|
+
validations:
|
|
74
|
+
required: true
|
|
75
|
+
- type: textarea
|
|
76
|
+
id: output
|
|
77
|
+
attributes:
|
|
78
|
+
label: Error output or sanitized trace
|
|
79
|
+
description: Redact private IPs, system names, channel names, and unit identifiers.
|
|
80
|
+
render: text
|
|
81
|
+
- type: checkboxes
|
|
82
|
+
id: checks
|
|
83
|
+
attributes:
|
|
84
|
+
label: Checklist
|
|
85
|
+
options:
|
|
86
|
+
- label: I searched existing issues.
|
|
87
|
+
required: true
|
|
88
|
+
- label: I tested the latest default branch or release.
|
|
89
|
+
required: true
|
|
90
|
+
- label: I removed sensitive scanner and network information.
|
|
91
|
+
required: true
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Support and troubleshooting
|
|
4
|
+
url: https://github.com/stevenboyd78/sds200-python/blob/main/SUPPORT.md
|
|
5
|
+
about: Review the support guide before opening a bug.
|
|
6
|
+
- name: Security vulnerability
|
|
7
|
+
url: https://github.com/stevenboyd78/sds200-python/blob/main/SECURITY.md
|
|
8
|
+
about: Do not disclose vulnerabilities in a public issue.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose a focused addition or improvement
|
|
3
|
+
title: "[Feature]: "
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: Problem or use case
|
|
9
|
+
description: What limitation are you trying to solve?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed behavior
|
|
16
|
+
description: Describe the API, CLI, protocol, or documentation change.
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: dropdown
|
|
20
|
+
id: area
|
|
21
|
+
attributes:
|
|
22
|
+
label: Area
|
|
23
|
+
options:
|
|
24
|
+
- Python API
|
|
25
|
+
- CLI
|
|
26
|
+
- USB transport
|
|
27
|
+
- Ethernet transport
|
|
28
|
+
- Protocol parsing
|
|
29
|
+
- Discovery and profiles
|
|
30
|
+
- Monitoring and events
|
|
31
|
+
- Documentation
|
|
32
|
+
- Testing and tooling
|
|
33
|
+
- Other
|
|
34
|
+
validations:
|
|
35
|
+
required: true
|
|
36
|
+
- type: textarea
|
|
37
|
+
id: alternatives
|
|
38
|
+
attributes:
|
|
39
|
+
label: Alternatives considered
|
|
40
|
+
description: Describe current workarounds or other designs.
|
|
41
|
+
- type: textarea
|
|
42
|
+
id: hardware
|
|
43
|
+
attributes:
|
|
44
|
+
label: Hardware or firmware considerations
|
|
45
|
+
description: Include relevant scanner or firmware behavior without private data.
|
|
46
|
+
- type: checkboxes
|
|
47
|
+
id: checks
|
|
48
|
+
attributes:
|
|
49
|
+
label: Checklist
|
|
50
|
+
options:
|
|
51
|
+
- label: I searched existing issues and the roadmap.
|
|
52
|
+
required: true
|
|
53
|
+
- label: This request does not expose private scanner or network information.
|
|
54
|
+
required: true
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What changed and why? -->
|
|
4
|
+
|
|
5
|
+
## Validation
|
|
6
|
+
|
|
7
|
+
- [ ] `ruff check .`
|
|
8
|
+
- [ ] `mypy src/sds200`
|
|
9
|
+
- [ ] `pytest`
|
|
10
|
+
- [ ] `python scripts/check_docs.py`
|
|
11
|
+
- [ ] Documentation and changelog updated when needed
|
|
12
|
+
|
|
13
|
+
## Hardware validation
|
|
14
|
+
|
|
15
|
+
<!-- Optional. Include scanner firmware and transport; redact private data. -->
|
|
16
|
+
|
|
17
|
+
- Scanner firmware:
|
|
18
|
+
- Python version:
|
|
19
|
+
- Operating system:
|
|
20
|
+
- Transport:
|
|
21
|
+
- Commands or workflows tested:
|
|
22
|
+
|
|
23
|
+
## Compatibility and security
|
|
24
|
+
|
|
25
|
+
<!-- Note public API, protocol, transport, privacy, or security implications. -->
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
test:
|
|
16
|
+
name: Python ${{ matrix.python-version }}
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
strategy:
|
|
19
|
+
fail-fast: false
|
|
20
|
+
matrix:
|
|
21
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
22
|
+
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v7
|
|
25
|
+
|
|
26
|
+
- uses: actions/setup-python@v7
|
|
27
|
+
with:
|
|
28
|
+
python-version: ${{ matrix.python-version }}
|
|
29
|
+
cache: pip
|
|
30
|
+
|
|
31
|
+
- name: Install project
|
|
32
|
+
run: |
|
|
33
|
+
python -m pip install --upgrade pip
|
|
34
|
+
python -m pip install -e ".[dev]"
|
|
35
|
+
|
|
36
|
+
- name: Ruff
|
|
37
|
+
run: ruff check .
|
|
38
|
+
|
|
39
|
+
- name: MyPy
|
|
40
|
+
run: mypy src/sds200
|
|
41
|
+
|
|
42
|
+
- name: Pytest
|
|
43
|
+
run: pytest --cov=sds200 --cov-report=term-missing
|
|
44
|
+
|
|
45
|
+
package:
|
|
46
|
+
name: Documentation and package
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@v7
|
|
51
|
+
|
|
52
|
+
- uses: actions/setup-python@v7
|
|
53
|
+
with:
|
|
54
|
+
python-version: "3.14"
|
|
55
|
+
cache: pip
|
|
56
|
+
|
|
57
|
+
- name: Install build tools
|
|
58
|
+
run: |
|
|
59
|
+
python -m pip install --upgrade pip
|
|
60
|
+
python -m pip install -e ".[dev]"
|
|
61
|
+
|
|
62
|
+
- name: Check documentation links
|
|
63
|
+
run: python scripts/check_docs.py
|
|
64
|
+
|
|
65
|
+
- name: Build distributions
|
|
66
|
+
run: python -m build
|
|
67
|
+
|
|
68
|
+
- name: Check distributions
|
|
69
|
+
run: python -m twine check dist/*
|
sds200-0.8.2/.gitignore
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format is based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project aims
|
|
5
|
+
to follow [Semantic Versioning](https://semver.org/) as the public API matures.
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
### Planned
|
|
10
|
+
|
|
11
|
+
- Validated SDS200 network audio transport after control reliability work
|
|
12
|
+
- Optional preferred-transport recovery without connection flapping
|
|
13
|
+
|
|
14
|
+
## [0.8.2] - 2026-07-24
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- Optional SDS100 battery telemetry through the documented `GSI`/`PSI` `Property.Battery` attribute
|
|
19
|
+
- Immediate `CommandRejectedError` handling for generic scanner `ERR` and `NG` replies
|
|
20
|
+
- Extended `scanner-info` output for RSSI, optional battery, recording, and mute state
|
|
21
|
+
- Opt-in Uniden SDS-series udev rule for desktop ACLs and ModemManager exclusion
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Corrected SDS100 capabilities after firmware 1.26.01 hardware testing showed
|
|
26
|
+
that `GCS` returns `ERR`
|
|
27
|
+
- Kept SDS150 detailed `GCS` charge status as specification-based and hardware unverified
|
|
28
|
+
- Package version advanced to 0.8.2
|
|
29
|
+
|
|
30
|
+
## [0.8.1] - 2026-07-24
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- Replaced the model-specific `sds200` executable with the model-neutral `sdsctl` command
|
|
35
|
+
- Updated CLI help, shell completion, documentation, support guidance, and tests for `sdsctl`
|
|
36
|
+
- Kept the distribution, Python import package, configuration directory, and repository named `sds200`
|
|
37
|
+
- Package version advanced to 0.8.1
|
|
38
|
+
|
|
39
|
+
## [0.8.0] - 2026-07-24
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- USB serial control support for the Uniden SDS100 and SDS150
|
|
44
|
+
- Model-neutral `SDSScanner` API while retaining the historical `SDS200` alias
|
|
45
|
+
- Scanner capability metadata and model-specific volume and squelch limits
|
|
46
|
+
- SDS100/SDS150 `GCS` battery and charge-status parsing and CLI output
|
|
47
|
+
- Model-aware USB discovery, selection, profiles, repair, and completions
|
|
48
|
+
- SDS150 `SDS150GBT` and Uniden internal model-name normalization
|
|
49
|
+
- LF, CR, and CRLF serial response framing for shared SDS-series commands
|
|
50
|
+
- Multi-model protocol, profile, discovery, and command regression tests
|
|
51
|
+
|
|
52
|
+
### Changed
|
|
53
|
+
|
|
54
|
+
- Network discovery and UDP profiles are explicitly restricted to the SDS200
|
|
55
|
+
- Profile documents advance to version 3 and can retain the scanner model
|
|
56
|
+
- Documentation distinguishes protocol support from physical-hardware validation
|
|
57
|
+
- Package version advanced to 0.8.0
|
|
58
|
+
|
|
59
|
+
## [0.7.0] - 2026-07-23
|
|
60
|
+
|
|
61
|
+
### Added
|
|
62
|
+
|
|
63
|
+
- Configurable exponential reconnect backoff with finite or unlimited attempts
|
|
64
|
+
- Structured `RadioEvent` notifications and `events --json` JSON Lines output
|
|
65
|
+
- Bounded health history with latency, error-rate, reconnect, and failover summaries
|
|
66
|
+
- Health thresholds for healthy, degraded, unhealthy, and disconnected states
|
|
67
|
+
- Discovery-based profile repair for stale USB paths and changed network addresses
|
|
68
|
+
- Detailed failover telemetry including previous and active endpoints
|
|
69
|
+
- Reliability regression tests for backoff, history, events, and profile repair
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
|
|
73
|
+
- Serial, UDP, and fallback reconnect loops now share one recovery policy
|
|
74
|
+
- `health --history` can include historical metrics in human or JSON output
|
|
75
|
+
- Network audio remains deferred and documented as future work
|
|
76
|
+
- Package version advanced to 0.7.0
|
|
77
|
+
|
|
78
|
+
## [0.6.0] - 2026-07-23
|
|
79
|
+
|
|
80
|
+
### Added
|
|
81
|
+
|
|
82
|
+
- Discovery-driven serial, network, or fallback profile creation
|
|
83
|
+
- Configurable serial/network preference with runtime transport failover
|
|
84
|
+
- One-time command retry after a successful failover
|
|
85
|
+
- Continuous `health --watch` output and JSON health reports
|
|
86
|
+
- Connection, response, state, serial, network, and failover diagnostics
|
|
87
|
+
- Independent `AudioTransport`, `AudioStream`, and `AudioChunk` API groundwork
|
|
88
|
+
|
|
89
|
+
### Changed
|
|
90
|
+
|
|
91
|
+
- Profile files now use version 2 and can store both control endpoints
|
|
92
|
+
- Package version advanced to 0.6.0
|
|
93
|
+
|
|
94
|
+
## [0.5.3] - 2026-07-23
|
|
95
|
+
|
|
96
|
+
First planned GitHub prerelease.
|
|
97
|
+
|
|
98
|
+
### Added
|
|
99
|
+
|
|
100
|
+
- Reliable active LAN discovery with isolated per-host UDP sockets
|
|
101
|
+
- Bounded discovery parallelism and configurable worker count
|
|
102
|
+
- USB and network connection profiles stored as TOML
|
|
103
|
+
- Network health checks, statistics, diagnostics, and XML retry limits
|
|
104
|
+
- User-focused README and project documentation
|
|
105
|
+
- Contribution, support, security, and conduct guidance
|
|
106
|
+
- GitHub issue forms, pull-request template, and Dependabot configuration
|
|
107
|
+
- Package metadata, typed-package marker, build verification, and release checklist
|
|
108
|
+
|
|
109
|
+
### Changed
|
|
110
|
+
|
|
111
|
+
- CI now uses Node 24-based GitHub Actions majors
|
|
112
|
+
- CI verifies documentation links and built distribution metadata
|
|
113
|
+
- LAN discovery uses per-host timeouts and bounded concurrency
|
|
114
|
+
|
|
115
|
+
### Fixed
|
|
116
|
+
|
|
117
|
+
- `/24` discovery could miss a scanner because unrelated UDP errors, ARP delays,
|
|
118
|
+
and shared-socket behavior interfered with valid replies
|
|
119
|
+
- Network XML handling now supports bare and fragmented `GSI`/`PSI` responses
|
|
120
|
+
- Strict MyPy narrowing in network XML decoding
|
|
121
|
+
|
|
122
|
+
## [0.5.2]
|
|
123
|
+
|
|
124
|
+
- Continued discovery after transient UDP refusal, reset, host-unreachable, and
|
|
125
|
+
network-unreachable errors.
|
|
126
|
+
|
|
127
|
+
## [0.5.1]
|
|
128
|
+
|
|
129
|
+
- Improved discovery timeout placement, batching, and response draining.
|
|
130
|
+
|
|
131
|
+
## [0.5.0]
|
|
132
|
+
|
|
133
|
+
- Added LAN discovery, profiles, health checks, UDP counters, diagnostics, and
|
|
134
|
+
bounded XML retries.
|
|
135
|
+
|
|
136
|
+
## [0.4.2]
|
|
137
|
+
|
|
138
|
+
- Completed strict typing for bare network XML response handling.
|
|
139
|
+
|
|
140
|
+
## [0.4.1]
|
|
141
|
+
|
|
142
|
+
- Added command-aware handling for bare `ScannerInfo` XML over UDP.
|
|
143
|
+
|
|
144
|
+
## [0.4.0]
|
|
145
|
+
|
|
146
|
+
- Added native SDS200 UDP control, multi-datagram XML reassembly, and network
|
|
147
|
+
support across the existing command, state, trace, and monitor APIs.
|
|
148
|
+
|
|
149
|
+
## [0.3.1]
|
|
150
|
+
|
|
151
|
+
- Correctly handled the SDS200 `PSI` acknowledgment followed by streamed XML.
|
|
152
|
+
|
|
153
|
+
## [0.3.0]
|
|
154
|
+
|
|
155
|
+
- Added continuous `PSI` monitoring, state-difference events, live terminal
|
|
156
|
+
display, traffic timestamps, and the public transport abstraction.
|
|
157
|
+
|
|
158
|
+
## [0.2.4]
|
|
159
|
+
|
|
160
|
+
- Added Ruff- and MyPy-clean shell completion integration.
|
|
161
|
+
|
|
162
|
+
## [0.2.3]
|
|
163
|
+
|
|
164
|
+
- Added Bash and Zsh completion for commands, flags, ports, profiles, and common
|
|
165
|
+
scanner protocol commands.
|
|
166
|
+
|
|
167
|
+
## [0.2.2]
|
|
168
|
+
|
|
169
|
+
- Completed strict PySerial factory and write-return typing.
|
|
170
|
+
|
|
171
|
+
## [0.2.1]
|
|
172
|
+
|
|
173
|
+
- Fixed a serial-reader shutdown race and added regression coverage.
|
|
174
|
+
|
|
175
|
+
## [0.2.0]
|
|
176
|
+
|
|
177
|
+
- Added typed command objects, structured scanner XML, synchronized radio state,
|
|
178
|
+
state events, traffic tracing, and the `scanner-info` command.
|
|
179
|
+
|
|
180
|
+
## [0.1.2]
|
|
181
|
+
|
|
182
|
+
- Established a Ruff-, MyPy-, and Pytest-clean transport baseline.
|
|
183
|
+
|
|
184
|
+
## [0.1.0]
|
|
185
|
+
|
|
186
|
+
- Added serial discovery, transport, packet framing, core responses, CLI tools,
|
|
187
|
+
examples, tests, and CI.
|
|
188
|
+
|
|
189
|
+
[Unreleased]: https://github.com/stevenboyd78/sds200-python/compare/v0.8.2...HEAD
|
|
190
|
+
[0.8.2]: https://github.com/stevenboyd78/sds200-python/compare/v0.8.1...v0.8.2
|
|
191
|
+
[0.8.1]: https://github.com/stevenboyd78/sds200-python/compare/v0.8.0...v0.8.1
|
|
192
|
+
[0.8.0]: https://github.com/stevenboyd78/sds200-python/compare/v0.7.0...v0.8.0
|
|
193
|
+
[0.7.0]: https://github.com/stevenboyd78/sds200-python/compare/v0.6.0...v0.7.0
|
|
194
|
+
[0.6.0]: https://github.com/stevenboyd78/sds200-python/compare/v0.5.3...v0.6.0
|
|
195
|
+
[0.5.3]: https://github.com/stevenboyd78/sds200-python/releases/tag/v0.5.3
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our standard
|
|
4
|
+
|
|
5
|
+
Project participation should be respectful, constructive, and focused on making
|
|
6
|
+
the software and documentation better.
|
|
7
|
+
|
|
8
|
+
Examples of welcome behavior include:
|
|
9
|
+
|
|
10
|
+
- Giving specific, actionable technical feedback
|
|
11
|
+
- Assuming good faith while asking for clarification
|
|
12
|
+
- Respecting differing experience levels and communication styles
|
|
13
|
+
- Protecting private information found in scanner traces or diagnostics
|
|
14
|
+
- Accepting maintainer decisions about project scope and safety
|
|
15
|
+
|
|
16
|
+
Unacceptable behavior includes harassment, personal attacks, discriminatory
|
|
17
|
+
language, deliberate disruption, publishing another person's private
|
|
18
|
+
information, or pressuring contributors to disclose sensitive radio or network
|
|
19
|
+
details.
|
|
20
|
+
|
|
21
|
+
## Enforcement
|
|
22
|
+
|
|
23
|
+
Report conduct concerns privately to the maintainer through the GitHub profile.
|
|
24
|
+
Do not use a public issue when doing so would expose the affected person.
|
|
25
|
+
|
|
26
|
+
The maintainer may edit or remove contributions, lock discussions, or restrict
|
|
27
|
+
participation when necessary to protect the project community.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thank you for helping improve `sds200-python`.
|
|
4
|
+
|
|
5
|
+
The project is hardware-facing alpha software, so contributions should preserve
|
|
6
|
+
a clear separation between transport behavior, protocol parsing, scanner state,
|
|
7
|
+
and user interfaces.
|
|
8
|
+
|
|
9
|
+
## Before opening an issue
|
|
10
|
+
|
|
11
|
+
Search existing issues and review [SUPPORT.md](SUPPORT.md). Include the project
|
|
12
|
+
version, Python version, operating system, scanner firmware, connection type,
|
|
13
|
+
and a minimal reproduction.
|
|
14
|
+
|
|
15
|
+
Remove private or location-sensitive information from traces before posting.
|
|
16
|
+
Scanner output can contain system names, channel names, IP addresses, and unit
|
|
17
|
+
identifiers.
|
|
18
|
+
|
|
19
|
+
Security vulnerabilities should follow [SECURITY.md](SECURITY.md), not a public
|
|
20
|
+
issue.
|
|
21
|
+
|
|
22
|
+
## Development setup
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
git clone https://github.com/stevenboyd78/sds200-python.git
|
|
26
|
+
cd sds200-python
|
|
27
|
+
|
|
28
|
+
python3 -m venv .venv
|
|
29
|
+
source .venv/bin/activate
|
|
30
|
+
|
|
31
|
+
python -m pip install --upgrade pip
|
|
32
|
+
python -m pip install -e ".[dev]"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Required checks
|
|
36
|
+
|
|
37
|
+
Run these before submitting a pull request:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
ruff check .
|
|
41
|
+
mypy src/sds200
|
|
42
|
+
pytest
|
|
43
|
+
python scripts/check_docs.py
|
|
44
|
+
python -m build
|
|
45
|
+
python -m twine check dist/*
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The automated test suite must run without scanner hardware.
|
|
49
|
+
|
|
50
|
+
## Project structure
|
|
51
|
+
|
|
52
|
+
- `src/sds200/transport.py`: transport contract and USB serial transport
|
|
53
|
+
- `src/sds200/network.py`: UDP transport and network XML datagram handling
|
|
54
|
+
- `src/sds200/fallback.py`: ordered control-transport activation and failover
|
|
55
|
+
- `src/sds200/audio.py`: control-independent audio lifecycle contracts
|
|
56
|
+
- `src/sds200/scanner.py`: model names, aliases, capabilities, and limits
|
|
57
|
+
- `src/sds200/commands.py`: typed command objects
|
|
58
|
+
- `src/sds200/parser.py`: CR-delimited response parsing
|
|
59
|
+
- `src/sds200/xml_protocol.py`: scanner-information XML parsing
|
|
60
|
+
- `src/sds200/state.py`: synchronized state and change detection
|
|
61
|
+
- `src/sds200/cli.py`: command-line interface
|
|
62
|
+
- `tests/`: hardware-independent regression tests
|
|
63
|
+
- `examples/`: focused usage examples
|
|
64
|
+
- `docs/`: architecture and operational guidance
|
|
65
|
+
|
|
66
|
+
## Adding protocol support
|
|
67
|
+
|
|
68
|
+
When adding or changing a scanner command:
|
|
69
|
+
|
|
70
|
+
1. Preserve the raw protocol response in a trace or sanitized fixture.
|
|
71
|
+
2. Add a typed command or response model when practical.
|
|
72
|
+
3. Keep transport-specific framing out of high-level command code.
|
|
73
|
+
4. Add positive, malformed-response, timeout, and validation tests.
|
|
74
|
+
5. Document hardware validation separately from simulated tests.
|
|
75
|
+
6. Avoid assuming that USB and UDP return identical framing.
|
|
76
|
+
|
|
77
|
+
Do not add tests that require a live scanner or a specific LAN.
|
|
78
|
+
|
|
79
|
+
## Hardware validation
|
|
80
|
+
|
|
81
|
+
A pull request may include optional manual validation notes:
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
Scanner: SDS100 / SDS150 / SDS200
|
|
85
|
+
Firmware: ...
|
|
86
|
+
Python: 3.14.x
|
|
87
|
+
Transport: USB / UDP (SDS200 only)
|
|
88
|
+
Commands tested: ...
|
|
89
|
+
Observed result: ...
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Sanitize system, department, channel, unit, and network information before
|
|
93
|
+
sharing logs publicly.
|
|
94
|
+
|
|
95
|
+
## Pull requests
|
|
96
|
+
|
|
97
|
+
Keep pull requests focused. Describe:
|
|
98
|
+
|
|
99
|
+
- What changed
|
|
100
|
+
- Why it changed
|
|
101
|
+
- Tests added or updated
|
|
102
|
+
- Local check results
|
|
103
|
+
- Hardware validation, when applicable
|
|
104
|
+
- Compatibility or security implications
|
|
105
|
+
|
|
106
|
+
Update documentation and `CHANGELOG.md` when behavior or public APIs change.
|
|
107
|
+
|
|
108
|
+
By participating, you agree to follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
|
sds200-0.8.2/LICENSE
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Steven Boyd
|
|
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.
|