rtls-sdk 0.2.0__tar.gz → 0.4.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.
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/CHANGELOG.md +155 -1
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/PKG-INFO +2 -1
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/prompts/README.md +6 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/pyproject.toml +2 -1
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/__init__.py +56 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/_client.py +10 -0
- rtls_sdk-0.4.0/src/rtls_sdk/_ws.py +390 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/errors.py +53 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/__init__.py +11 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/lsb.py +129 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/network.py +43 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/node_params.py +51 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/schedule.py +30 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/ws/__init__.py +76 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/ws/_base.py +53 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/ws/alarm.py +34 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/ws/notify.py +29 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/ws/ota.py +23 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/ws/param_p.py +25 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/ws/position.py +41 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/ws/sensor.py +23 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/ws/user_msg.py +28 -0
- rtls_sdk-0.4.0/src/rtls_sdk/models/ws/zone_event.py +30 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/__init__.py +10 -0
- rtls_sdk-0.4.0/src/rtls_sdk/resources/lsb.py +373 -0
- rtls_sdk-0.4.0/src/rtls_sdk/resources/network.py +54 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/nodes.py +53 -1
- rtls_sdk-0.4.0/src/rtls_sdk/resources/schedules.py +92 -0
- rtls_sdk-0.4.0/src/rtls_sdk/resources/user_messages.py +76 -0
- rtls_sdk-0.4.0/src/rtls_sdk/resources/ws.py +133 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/.gitignore +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/LICENSE +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/README.md +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/_auth.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/_envelope.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/_http.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/_logging.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/_pagination.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/_query.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/_time.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/compounds/__init__.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/compounds/auth.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/compounds/context.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/compounds/groups.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/compounds/nodes.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/compounds/reports.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/compounds/system.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/compounds/tags.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/compounds/users.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/compounds/zones.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/_base.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/alarm.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/anchor.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/area.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/association.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/bulk.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/company.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/csv_blob.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/floorplan.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/group.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/heatmap.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/import_result.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/node.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/notification.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/position.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/project.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/pws.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/report.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/session_context.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/site.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/subscriber.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/system.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/system_health.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/tag.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/tag_template.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/user.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/zone.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/models/zone_event.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/py.typed +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/_base.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/alarms.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/anchors.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/areas.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/associations.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/auth.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/companies.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/context.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/events.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/floorplans.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/groups.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/logger.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/messaging.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/notifications.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/projects.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/reports.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/sites.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/subscribers.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/system.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/tags.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/users.py +0 -0
- {rtls_sdk-0.2.0 → rtls_sdk-0.4.0}/src/rtls_sdk/resources/zones.py +0 -0
|
@@ -7,7 +7,161 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
## [0.
|
|
10
|
+
## [0.4.0] — 2026-05-19
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
#### Schedules, LSB, Network resources (ported from desktop site-plan)
|
|
15
|
+
|
|
16
|
+
- `client.schedules` — CRUD on `/api/v2/tdoa/schedules/`: `list`,
|
|
17
|
+
`get`, `create`, `update`, `delete`. The per-slot table is carried
|
|
18
|
+
as an opaque `content` blob so callers can round-trip both v1 and
|
|
19
|
+
v2 schedule wire formats without an SDK release. New
|
|
20
|
+
`rtls_sdk.Schedule` model.
|
|
21
|
+
- `client.lsb` — read/write the Location Synchronization Bus
|
|
22
|
+
settings on `/api/v2/tdoa/settings/`: `get`, `update`. Settings
|
|
23
|
+
include the active-schedule pointer, autostart flag, and per-anchor
|
|
24
|
+
sync roles (master / distributor / client). The server upserts on
|
|
25
|
+
POST keyed by `project_uid` in the body. The `values` payload is
|
|
26
|
+
exposed as `dict[str, Any]` to support both `lsb_version=1` (`sfd`,
|
|
27
|
+
`autostart_devices`) and `lsb_version=2` (`masters`,
|
|
28
|
+
`distributors`) shapes side-by-side. The SDK also merges the
|
|
29
|
+
top-level `tdoa_version` / `lsb_version` fields from the response
|
|
30
|
+
into the model. New `rtls_sdk.LsbSettings` model.
|
|
31
|
+
- `client.network` — `/api/v2/network_settings/` read/update for the
|
|
32
|
+
per-project service-mode toggle (`enabled`, `duration`,
|
|
33
|
+
`devices_in_service_mode`). New `rtls_sdk.NetworkSettings` and
|
|
34
|
+
`rtls_sdk.ServiceMode` models; null device lists coerce to `[]`.
|
|
35
|
+
- Live tests under `tests/live/test_schedules.py`,
|
|
36
|
+
`tests/live/test_lsb.py`, `tests/live/test_network.py`. The
|
|
37
|
+
service-mode toggle test is guarded by
|
|
38
|
+
`RTLS_LIVE_ALLOW_SERVICE_MODE_TOGGLE=1` because it affects real
|
|
39
|
+
hardware.
|
|
40
|
+
- Docs: `docs/entities/schedules.md`, `lsb.md`, `network.md`.
|
|
41
|
+
|
|
42
|
+
#### LSB start/stop orchestration
|
|
43
|
+
|
|
44
|
+
- `client.lsb.start(masters, *, bcs=1, tdoas=0, timeout=9.0,
|
|
45
|
+
resend_interval=3.0, check_interval=0.7)` — push `sync_slot` + `sf`
|
|
46
|
+
to each master and poll `hw_params` until every node echoes back
|
|
47
|
+
the configured values. Raises `LsbConvergenceError` (with the
|
|
48
|
+
unresolved MAC list) on timeout. Faithful port of the desktop
|
|
49
|
+
site-plan's start flow.
|
|
50
|
+
- `client.lsb.stop(macs, *, timeout=15.0, …)` — send the all-zero
|
|
51
|
+
`sf` "stop trick" to each master and poll until every node reports
|
|
52
|
+
`sf.value.sfd == 0` (or `addr` empty / `"0000"`).
|
|
53
|
+
- New `LsbMasterSpec` dataclass (`mac`, `addr`, `slot`, `sfd`) for
|
|
54
|
+
the `start()` argument.
|
|
55
|
+
- New `LsbConvergenceError` exception carrying `unresolved: list[str]`.
|
|
56
|
+
|
|
57
|
+
#### LSB settings accessors and configured-start convenience
|
|
58
|
+
|
|
59
|
+
- `LsbSettings.masters()` and `LsbSettings.distributors()` — typed
|
|
60
|
+
views over the opaque `values` dict that smooth the v1/v2 fork.
|
|
61
|
+
Return frozen `LsbMasterEntry` / `LsbDistributorEntry` dataclasses
|
|
62
|
+
(also exported at the top level). The wire shape of `values` stays
|
|
63
|
+
an opaque dict for forward-compatibility.
|
|
64
|
+
- `client.lsb.start_configured(*, tdoas, bcs=None, …)` — convenience
|
|
65
|
+
start: reads LSB settings, joins anchors + nodes, derives each
|
|
66
|
+
master's MAC and 4-char hex addr (from `node.node_id`), then
|
|
67
|
+
delegates to `client.lsb.start([...])`. Raises `RuntimeError` with
|
|
68
|
+
a clear message when resolution fails (no masters configured, no
|
|
69
|
+
registered node for an anchor's MAC, etc.). `bcs` defaults to
|
|
70
|
+
`max(slot) + 1` matching site-plan.
|
|
71
|
+
|
|
72
|
+
#### Node parameter primitives
|
|
73
|
+
|
|
74
|
+
- `client.nodes.send_param(mac, **plist)` — POSTs to
|
|
75
|
+
`/api/v2/win_message_que/create.json/`. Accepts any plist keys
|
|
76
|
+
(`sf`, `sync_slot`, `nwk_cfg`, `srv_mode`, `tdoa_schedule`,
|
|
77
|
+
`tdoa_schd`, `p`). Multiple keys per call supported. MAC is
|
|
78
|
+
normalised.
|
|
79
|
+
- `client.nodes.read_params(macs, fields, *, force_update=False)` —
|
|
80
|
+
GETs `/api/v2/hw_params.json` with repeated `mac=` and `fields=`
|
|
81
|
+
query parameters (matching the desktop client's wire format).
|
|
82
|
+
Returns `list[NodeParams]`. Server-side `"pending"` strings on
|
|
83
|
+
each field coerce to `None` so callers always see `dict | None`.
|
|
84
|
+
- New `rtls_sdk.NodeParams` model.
|
|
85
|
+
|
|
86
|
+
## [0.3.0] — 2026-05-13
|
|
87
|
+
|
|
88
|
+
### Documentation
|
|
89
|
+
|
|
90
|
+
- New `entities/streaming.md` documenting `client.ws`, the eight
|
|
91
|
+
typed channel models, reconnects, heartbeats, backpressure, and a
|
|
92
|
+
REST → WS round-trip recipe. Reference pages (`resources.md`,
|
|
93
|
+
`models.md`, `errors.md`) now list the WS surface. Catalog and
|
|
94
|
+
quickstart link to the new page.
|
|
95
|
+
|
|
96
|
+
### Added
|
|
97
|
+
|
|
98
|
+
#### Typed WS channel models (M18)
|
|
99
|
+
|
|
100
|
+
- `rtls_sdk.models.ws` — new sub-package with one pydantic model per
|
|
101
|
+
decoded channel: `PositionMessage` (pos), `NotifyMessage` (notify),
|
|
102
|
+
`AlarmMessage` (alarm), `ZoneEventMessage` (zone_event),
|
|
103
|
+
`SensorMessage` (sensor), `OtaMessage` (ota), `ParamPMessage`
|
|
104
|
+
(param_p), `UserMsgMessage` (user_msg). All eight inherit from
|
|
105
|
+
`WsChannelEnvelope` and carry the full wire dict on `.raw` for
|
|
106
|
+
forward-compat field access.
|
|
107
|
+
- `client.ws.subscribe(...)` now yields typed messages instead of the
|
|
108
|
+
M17 untyped envelope; iteration patterns like
|
|
109
|
+
`match msg: case PositionMessage(x=x, y=y): ...` work directly. The
|
|
110
|
+
yield type narrowed from `WsChannelMessage` to `WsChannelEnvelope`.
|
|
111
|
+
- Unknown channels and decode failures fall back to
|
|
112
|
+
`WsChannelMessage` (now a pydantic model, was a frozen dataclass) so
|
|
113
|
+
the iterator never dies on a single bad frame. Validation errors
|
|
114
|
+
log at WARNING with the channel name.
|
|
115
|
+
- New `include_heartbeats: bool = False` kwarg on
|
|
116
|
+
`client.ws.subscribe(...)`. By default, `notify` frames with
|
|
117
|
+
`action == "HB"` are dropped at the reader; opt-in callers receive
|
|
118
|
+
them as `NotifyMessage(action="HB")`. Heartbeat drops do not count
|
|
119
|
+
toward `session.messages_dropped` — that counter remains
|
|
120
|
+
backpressure-only.
|
|
121
|
+
|
|
122
|
+
### Changed
|
|
123
|
+
|
|
124
|
+
- `WsChannelMessage` moved from `rtls_sdk._ws` to
|
|
125
|
+
`rtls_sdk.models.ws`; the import path under the top-level package
|
|
126
|
+
(`from rtls_sdk import WsChannelMessage`) is unchanged.
|
|
127
|
+
|
|
128
|
+
#### WebSocket subscription scaffold (M17)
|
|
129
|
+
|
|
130
|
+
- `client.ws` — new `WsAPI` sub-client wrapping the JSON-RPC 2.0
|
|
131
|
+
subscriptions-manager. `ws.list_channels()` returns the server's
|
|
132
|
+
advertised channel inventory in a one-shot dial (no auth required).
|
|
133
|
+
`ws.subscribe(channels, *, project_uid=None, reconnect=True,
|
|
134
|
+
queue_max=1024)` opens a long-lived session that is both a context
|
|
135
|
+
manager and a blocking iterator of `WsChannelMessage` envelopes.
|
|
136
|
+
Naming is transport-specific on purpose — future streaming
|
|
137
|
+
protocols (MQTT, Kafka) would land as siblings (`client.mqtt`,
|
|
138
|
+
`client.kafka`) rather than crowd a generic `client.stream`
|
|
139
|
+
namespace.
|
|
140
|
+
- `WsChannelMessage(channel, raw)` — untyped pass-through for any
|
|
141
|
+
channel; typed channel models land in M18.
|
|
142
|
+
- Reader runs on a daemon thread behind a bounded queue. Backpressure
|
|
143
|
+
drops the oldest message and bumps `session.messages_dropped`.
|
|
144
|
+
Auto-reconnect with capped exponential backoff
|
|
145
|
+
`(1, 2, 4, 8, 15, 30, 30, 30)` seconds on unclean disconnects;
|
|
146
|
+
re-subscribes the current channel set. Auth failure during reconnect
|
|
147
|
+
surfaces as `WsAuthError` from the iterator and stops further
|
|
148
|
+
attempts.
|
|
149
|
+
- New error classes `WsError`, `WsAuthError`, and `WsProtocolError`
|
|
150
|
+
(all subclasses of `RtlsError`).
|
|
151
|
+
- New dependency: `websockets >= 12.0`.
|
|
152
|
+
|
|
153
|
+
#### User messages REST (M16)
|
|
154
|
+
|
|
155
|
+
- `client.user_messages.send(tag_uid, hex)` — new `UserMessagesAPI`
|
|
156
|
+
sub-client; sends a hex payload to a tag's badge over the WIN
|
|
157
|
+
gateway. Wire endpoint: `POST /api/v2/user_msg/`. Independent of
|
|
158
|
+
`client.messaging` (which targets the inbox endpoint at
|
|
159
|
+
`/api/v2/messaging`); the two surfaces stay separate because the
|
|
160
|
+
endpoints serve different features on the wire (UDP frame vs. inbox
|
|
161
|
+
row) and share no storage. Client-side validation rejects malformed
|
|
162
|
+
hex before any network I/O.
|
|
163
|
+
|
|
164
|
+
## [0.2.0] — 2026-05-13
|
|
11
165
|
|
|
12
166
|
### Added
|
|
13
167
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rtls-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Python SDK for the RTLS REST API
|
|
5
5
|
Project-URL: Homepage, https://github.com/rpplabs/rtls-sdk
|
|
6
6
|
Project-URL: Documentation, https://github.com/rpplabs/rtls-sdk/tree/master/docs
|
|
@@ -21,6 +21,7 @@ Classifier: Typing :: Typed
|
|
|
21
21
|
Requires-Python: >=3.10
|
|
22
22
|
Requires-Dist: httpx>=0.27
|
|
23
23
|
Requires-Dist: pydantic>=2.5
|
|
24
|
+
Requires-Dist: websockets>=12.0
|
|
24
25
|
Provides-Extra: dev
|
|
25
26
|
Requires-Dist: mypy>=1.8; extra == 'dev'
|
|
26
27
|
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
|
|
@@ -17,6 +17,12 @@ These prompts implement the design in `/Users/yzhbankov/rtls/rtls-sdk/DESIGN.md`
|
|
|
17
17
|
| 13 | `13-m11-entity-docs.md` | M11 | Docs-only: reorganize user documentation around **entities**. New `docs/entities/` tree (one page per entity + catalog index) replaces the workflow-oriented guides. Answers "what can I do with X?" on one page. |
|
|
18
18
|
| 14 | `14-m12-schema-audit-mac-fix.md` | M12 | Schema-correctness audit. Fix three real bugs caught by reading the server's Joi schemas directly: MAC format is bare 12-hex (not colon-separated); `tags.create` does not accept `mac_address` (server silently strips); add live MAC round-trip test as a regression gate. |
|
|
19
19
|
| 15 | `15-m13-final-audit.md` | M13 | **Check-only.** Full ship-readiness audit across code quality, documentation site, internal consistency, wire-shape correctness, deep doc-quality analysis (with persona-driven proposals), and release artifacts. Produces `AUDIT.md` at the repo root with a verdict (ready / not ready), itemised blockers, repo-wide markdown link validation, and a prioritised list of documentation improvement proposals. Does not modify code or docs — a separate milestone applies any accepted fixes. |
|
|
20
|
+
| 16 | `16-m14-e2e-live-test.md` | M14 | Full-stack live E2E test (`tests/live/test_m14_full_stack.py`). Builds the entity tree top-down, lists, updates each kind, deletes bottom-up. Fix-test-retry discipline — surfaces SDK bugs and fixes them in-flight. |
|
|
21
|
+
| 17 | `17-m15-user-msg-websocket-research.md` | M15 | **Research-only.** Investigates the server-side `user_msg` REST endpoint and the JSON-RPC WebSocket protocol (subscriptions-manager). Produces `prompts/17-m15-research.md` with wire shapes, channel inventory, discrepancies, and concrete SDK extension signatures. |
|
|
22
|
+
| 18 | `18-m16-user-msg-rest.md` | M16 | `messaging.send_to_tag(tag_uid, hex)` — POST `/api/v2/user_msg/` sends a hex payload to a tag's badge over the WIN gateway. Unit + integration + live test. |
|
|
23
|
+
| 19 | `19-m17-ws-scaffold.md` | M17 | WebSocket sub-client `client.stream`: connect, list channels, subscribe / unsubscribe, blocking-iterator over `RawChannelMessage`, heartbeat passthrough, reconnect with backoff. Dependency: `websockets`. |
|
|
24
|
+
| 20 | `20-m18-ws-typed-models.md` | M18 | Typed channel models (`PositionMessage`, `AlarmMessage`, `NotifyMessage`, `ZoneEventMessage`, `SensorMessage`, `OtaMessage`, `ParamPMessage`, `UserMsgMessage`) + discriminated-union decode dispatch + `include_heartbeats` flag (default off). |
|
|
25
|
+
| 21 | `21-m19-ws-live-gate.md` | M19 | End-to-end live gate: REST `send_to_tag` → WS `user_msg` notify round-trip. Five-consecutive-pass stability requirement. |
|
|
20
26
|
|
|
21
27
|
## Inputs each prompt reads
|
|
22
28
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rtls-sdk"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "Python SDK for the RTLS REST API"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -24,6 +24,7 @@ classifiers = [
|
|
|
24
24
|
dependencies = [
|
|
25
25
|
"httpx>=0.27",
|
|
26
26
|
"pydantic>=2.5",
|
|
27
|
+
"websockets>=12.0",
|
|
27
28
|
]
|
|
28
29
|
|
|
29
30
|
[project.optional-dependencies]
|
|
@@ -18,6 +18,7 @@ from .errors import (
|
|
|
18
18
|
AuthenticationError,
|
|
19
19
|
Conflict,
|
|
20
20
|
ConnectionError,
|
|
21
|
+
LsbConvergenceError,
|
|
21
22
|
NotFound,
|
|
22
23
|
PartialFailureError,
|
|
23
24
|
PermissionDenied,
|
|
@@ -28,6 +29,9 @@ from .errors import (
|
|
|
28
29
|
RtlsError,
|
|
29
30
|
ServerError,
|
|
30
31
|
ValidationError,
|
|
32
|
+
WsAuthError,
|
|
33
|
+
WsError,
|
|
34
|
+
WsProtocolError,
|
|
31
35
|
)
|
|
32
36
|
from .models import (
|
|
33
37
|
Alarm,
|
|
@@ -43,7 +47,12 @@ from .models import (
|
|
|
43
47
|
Group,
|
|
44
48
|
Host,
|
|
45
49
|
ImportResult,
|
|
50
|
+
LsbDistributorEntry,
|
|
51
|
+
LsbMasterEntry,
|
|
52
|
+
LsbSettings,
|
|
53
|
+
NetworkSettings,
|
|
46
54
|
Node,
|
|
55
|
+
NodeParams,
|
|
47
56
|
NotificationProfile,
|
|
48
57
|
NotificationType,
|
|
49
58
|
Position,
|
|
@@ -51,6 +60,8 @@ from .models import (
|
|
|
51
60
|
Report,
|
|
52
61
|
ReportType,
|
|
53
62
|
Role,
|
|
63
|
+
Schedule,
|
|
64
|
+
ServiceMode,
|
|
54
65
|
Site,
|
|
55
66
|
Subscriber,
|
|
56
67
|
SubscriberAddresses,
|
|
@@ -66,14 +77,49 @@ from .models import (
|
|
|
66
77
|
Zone,
|
|
67
78
|
ZoneEvent,
|
|
68
79
|
)
|
|
80
|
+
from .models.ws import (
|
|
81
|
+
AlarmMessage,
|
|
82
|
+
NotifyMessage,
|
|
83
|
+
OtaMessage,
|
|
84
|
+
ParamPMessage,
|
|
85
|
+
PositionMessage,
|
|
86
|
+
SensorMessage,
|
|
87
|
+
UserMsgMessage,
|
|
88
|
+
WsChannelEnvelope,
|
|
89
|
+
WsChannelMessage,
|
|
90
|
+
ZoneEventMessage,
|
|
91
|
+
)
|
|
92
|
+
from .resources import LsbAPI, NetworkAPI, SchedulesAPI, UserMessagesAPI, WsAPI
|
|
93
|
+
from .resources.lsb import LsbMasterSpec
|
|
94
|
+
from .resources.ws import WsSession
|
|
69
95
|
|
|
70
96
|
__all__ = [ # noqa: RUF022 — grouped logically, not alphabetically
|
|
71
97
|
# Client
|
|
72
98
|
"RtlsClient",
|
|
99
|
+
# Resource sub-clients
|
|
100
|
+
"LsbAPI",
|
|
101
|
+
"LsbMasterSpec",
|
|
102
|
+
"NetworkAPI",
|
|
103
|
+
"SchedulesAPI",
|
|
104
|
+
"UserMessagesAPI",
|
|
105
|
+
"WsAPI",
|
|
106
|
+
# WebSocket types
|
|
107
|
+
"AlarmMessage",
|
|
108
|
+
"NotifyMessage",
|
|
109
|
+
"OtaMessage",
|
|
110
|
+
"ParamPMessage",
|
|
111
|
+
"PositionMessage",
|
|
112
|
+
"SensorMessage",
|
|
113
|
+
"UserMsgMessage",
|
|
114
|
+
"WsChannelEnvelope",
|
|
115
|
+
"WsChannelMessage",
|
|
116
|
+
"WsSession",
|
|
117
|
+
"ZoneEventMessage",
|
|
73
118
|
# Errors
|
|
74
119
|
"AuthenticationError",
|
|
75
120
|
"Conflict",
|
|
76
121
|
"ConnectionError",
|
|
122
|
+
"LsbConvergenceError",
|
|
77
123
|
"NotFound",
|
|
78
124
|
"PartialFailureError",
|
|
79
125
|
"PermissionDenied",
|
|
@@ -84,6 +130,9 @@ __all__ = [ # noqa: RUF022 — grouped logically, not alphabetically
|
|
|
84
130
|
"RtlsError",
|
|
85
131
|
"ServerError",
|
|
86
132
|
"ValidationError",
|
|
133
|
+
"WsAuthError",
|
|
134
|
+
"WsError",
|
|
135
|
+
"WsProtocolError",
|
|
87
136
|
# Models
|
|
88
137
|
"Alarm",
|
|
89
138
|
"Anchor",
|
|
@@ -98,7 +147,12 @@ __all__ = [ # noqa: RUF022 — grouped logically, not alphabetically
|
|
|
98
147
|
"Group",
|
|
99
148
|
"Host",
|
|
100
149
|
"ImportResult",
|
|
150
|
+
"LsbDistributorEntry",
|
|
151
|
+
"LsbMasterEntry",
|
|
152
|
+
"LsbSettings",
|
|
153
|
+
"NetworkSettings",
|
|
101
154
|
"Node",
|
|
155
|
+
"NodeParams",
|
|
102
156
|
"NotificationProfile",
|
|
103
157
|
"NotificationType",
|
|
104
158
|
"Position",
|
|
@@ -106,6 +160,8 @@ __all__ = [ # noqa: RUF022 — grouped logically, not alphabetically
|
|
|
106
160
|
"Report",
|
|
107
161
|
"ReportType",
|
|
108
162
|
"Role",
|
|
163
|
+
"Schedule",
|
|
164
|
+
"ServiceMode",
|
|
109
165
|
"Site",
|
|
110
166
|
"Subscriber",
|
|
111
167
|
"SubscriberAddresses",
|
|
@@ -30,16 +30,21 @@ from .resources import (
|
|
|
30
30
|
FloorplansAPI,
|
|
31
31
|
GroupsAPI,
|
|
32
32
|
LoggerAPI,
|
|
33
|
+
LsbAPI,
|
|
33
34
|
MessagingAPI,
|
|
35
|
+
NetworkAPI,
|
|
34
36
|
NodesAPI,
|
|
35
37
|
NotificationsAPI,
|
|
36
38
|
ProjectsAPI,
|
|
37
39
|
ReportsAPI,
|
|
40
|
+
SchedulesAPI,
|
|
38
41
|
SitesAPI,
|
|
39
42
|
SubscribersAPI,
|
|
40
43
|
SystemAPI,
|
|
41
44
|
TagsAPI,
|
|
45
|
+
UserMessagesAPI,
|
|
42
46
|
UsersAPI,
|
|
47
|
+
WsAPI,
|
|
43
48
|
ZonesAPI,
|
|
44
49
|
)
|
|
45
50
|
|
|
@@ -178,8 +183,13 @@ class RtlsClient:
|
|
|
178
183
|
self.system = SystemAPI(self)
|
|
179
184
|
self.auth = AuthAPI(self)
|
|
180
185
|
self.messaging = MessagingAPI(self)
|
|
186
|
+
self.user_messages = UserMessagesAPI(self)
|
|
187
|
+
self.ws = WsAPI(self)
|
|
181
188
|
self.logger = LoggerAPI(self)
|
|
182
189
|
self.context = ContextAPI(self)
|
|
190
|
+
self.schedules = SchedulesAPI(self)
|
|
191
|
+
self.lsb = LsbAPI(self)
|
|
192
|
+
self.network = NetworkAPI(self)
|
|
183
193
|
|
|
184
194
|
# -- public scope helpers --------------------------------------------
|
|
185
195
|
|