depz-sensor-viewer
A local, standalone launcher for the DEPZ sensor web viewer. It runs a tiny
localhost web server that serves the viewer SPA and talks to your DEPZ
sensors over pyserial — so the UI never
touches the browser WebSerial API.
Why
The hosted viewer uses the browser's WebSerial API, which means:
- a port-picker prompt every time you connect,
- Chrome-only support, and
- failures under some enterprise / managed-Chrome policies that disable WebSerial entirely.
This launcher sidesteps all of that. The Python process opens the serial port
locally with pyserial and pipes raw bytes to the SPA over a WebSocket. No
prompt, no WebSerial, works in any browser pointed at localhost.
Install & run
pipx install depz-sensor-viewer
depz-sensor-viewer
This starts the server on http://127.0.0.1:8765 (or a random free port if
8765 is taken) and opens your browser. Options:
depz-sensor-viewer --port 9000 # pick a port (0 = random free)
depz-sensor-viewer --host 127.0.0.1 # bind address (localhost by default)
depz-sensor-viewer --no-browser # just start the server
depz-sensor-viewer --keep-alive # don't stop the server when the viewer window closes
Press Ctrl-C to stop.
Linux: serial permissions
On Linux, opening /dev/ttyACM* requires membership in the dialout group.
If devices don't open, add yourself and re-login:
sudo usermod -aG dialout $USER
# then log out and back in (or: newgrp dialout)
The viewer diagnoses this for you at GET /api/permissions and shows the fix in
the UI.
HTTP / WebSocket contract
The bundled SPA detects standalone mode and drives devices through this fixed
interface (served by depz_sensor_viewer.server):
| Endpoint | Response |
|---|---|
GET /api/health |
{"standalone": true, "version": "<pkg>"} |
GET /api/devices |
{"devices": [{path, usb_vid, usb_pid, serial, sensor_type, usb_model_hint}]} |
GET /api/permissions |
{ok, os, issues, fix: {command, explanation}} |
GET /api/recordings |
{"recordings": [{name, size_bytes, mtime}], "dir": "<path>"} |
GET /api/recordings/{name} |
dataset bytes (404 unknown, 400 unsafe name) |
POST /api/recordings/{name} |
save dataset bytes → 201 {name, size_bytes, dir} (collision suffixes, never overwrites) |
WS /ws/serial?path=<port>&baud=<n> |
raw byte pipe (see below) |
Recordings live on disk like the camera viewer's: <repo>/recordings/ in a dev
checkout, else <Documents>/DEPZ/recordings/ (--recordings-dir overrides). In
standalone mode the SPA's Record button saves there and the Player button lists
the directory inline; the hosted (WebSerial) viewer keeps standard browser
downloads and the file picker.
/api/devices enumerates only ports whose USB identity is a known DEPZ device
(via the SDK's USB table); it does not open the ports. baud defaults to
115200 and is nominal for the CDC-ACM devices.
/ws/serial framing:
- client → server binary frame →
serial.write(bytes) - server → client binary frame ← bytes read from the serial port
- text frames carry JSON control/status:
- server:
{"opened": true, "path": ..., "baud": ...}right after open - server:
{"error": "...", "code": "...", "fix": {...}}on failure (permission errors include the per-OSfix) - client:
{"cmd": "set_baud", "baud": <int>}(optional)
- server:
The port is closed when the WebSocket closes.
Building the bundled SPA
The wheel ships the built SPA under depz_sensor_viewer/_static/. To (re)build
it from the repo's TypeScript viewer:
python packages/depz-sensor-viewer/scripts/bundle_spa.py
This runs bun run build:spa at the repo root and copies dist-spa/client/**
into _static/, materialising index.html from the prerendered SPA shell.
Pass --skip-build to copy an existing dist-spa/client/ without rebuilding.
Until you run it, / serves a plaintext placeholder that points here — the API
endpoints above are live regardless.
The SPA build (vite.config.spa.ts) is deliberately not the default
bun run build: that one targets Cloudflare and emits an SSR worker
(dist/server/server.js + dist/client/) with no index.html, which the
plain-file launcher cannot serve. The SSR dist/ build is left untouched, so
the Cloudflare deploy keeps working.
License
MIT
Metadata
Release files for depz-sensor-viewer 0.4.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| depz_sensor_viewer-0.4.2.tar.gz | 670.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| depz_sensor_viewer-0.4.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.3 MB
Release files / depz_sensor_viewer-0.4.2.tar.gz
| Download URL | depz_sensor_viewer-0.4.2.tar.gz |
|---|---|
| Size | 670.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0e347fe14fba75ff9c4276f89bd65bd7b0da9f9b4a4a4991ea9c08b360849c2d
|
|
BLAKE2b-256 checksum How to use checksums |
5b551b063ae7566d53bae4615e55601f6f95f386f56ff984ff7c95f2f1fb6401
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / depz_sensor_viewer-0.4.2-py3-none-any.whl
| Download URL | depz_sensor_viewer-0.4.2-py3-none-any.whl |
|---|---|
| Size | 653.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
362378f475e31c0a55e9b4a6a7e8c6a5cb6be754e6c2c0c69aa3f74eb9c53e70
|
|
BLAKE2b-256 checksum How to use checksums |
e9961f60cca29ad2a391bb62dabed053023299e15bbd8c27f771c07e6a3ea5b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency log