Skip to content

Releases: plexus-oss/plexus-python

0.5.2 — DX hardening for hardware engineers

22 May 03:52

Choose a tag to compare

[0.5.2] - 2026-05-21 - DX hardening for hardware engineers

Fixed

  • Error messages now reference plexus init instead of the non-existent plexus start.
  • close() now attempts to flush any buffered points before tearing down the transport,
    preventing silent data loss on graceful shutdown.
  • persistent_buffer default changed from False to True — store-and-forward is now
    on by default, matching the ~/.plexus/config.json default and the right choice for
    field hardware. Pass persistent_buffer=False to opt out (e.g. in test fixtures).

Added

  • send_batch() now accepts 3-tuples (metric, value, timestamp) alongside the existing
    2-tuple form. Per-point timestamps let sensors on different interrupt timers share a
    single batch call. 2-tuples continue to use the shared timestamp argument.
  • on_command() now warns immediately via stderr if called after the WebSocket has already
    authenticated, making the "register before first send()" ordering requirement visible
    rather than silently broken.
  • source_id is validated against ^[a-z0-9][a-z0-9_-]{1,62}$ at construction time.
    Invalid names now raise ValueError with a clear message instead of failing obscurely
    at the gateway.

Changed

  • _say() / _QUIET consolidated into a new internal plexus/_log.py module.
    Previously duplicated verbatim between client.py and ws.py.

0.5.1 — Binary video frames + non-blocking send

20 May 03:55

Choose a tag to compare

[0.5.1] - 2026-05-19 - Binary video frames + non-blocking send

Performance

  • send_video_frame() now sends a compact binary WebSocket frame instead of
    JSON+base64. The binary header encodes source_id, camera_id, width, height,
    and timestamp_ms; the JPEG payload follows raw. Eliminates the 33% base64
    wire overhead, reducing per-frame bandwidth by ~25% and raising the
    sustainable FPS ceiling from ~15–20 fps to ~20–25 fps at 1280×720 quality 85.
  • Gateway decodes the binary header and re-encodes as JSON+base64 before
    relaying to browsers — no changes required in the frontend, data_api, or any
    other consumer.

Reliability

  • send_video_frame() is now non-blocking. Frames are placed into a
    queue.Queue(maxsize=2) drained by a dedicated plexus-video daemon thread.
    When the queue is full (sender backlogged) frames are dropped rather than
    blocking the capture pipeline, preventing deadlocks at any FPS.
  • stop() / close() now exits cleanly within 0.5 s regardless of in-flight
    sends. Previously a slow or hung WebSocket write could stall shutdown
    indefinitely.

Changed

  • Removed import base64 from client.py (no longer needed on the send path).
  • send_video_frame() calls ws.send_video_frame_async() instead of the
    internal ws._send_frame().

Wire protocol

  • Gateway handles both binary frames (SDK ≥ 0.5.1) and legacy JSON text frames
    transparently — older SDKs continue to work unchanged.

0.5.0 — Security hardening, dep cleanup, Python 3.10+ only

19 May 21:03

Choose a tag to compare

[0.5.0] - 2026-05-19 - Security hardening, dep cleanup, Python 3.10+ only

Security

  • Removed requests (and its transitive deps urllib3, idna) entirely —
    replaced with stdlib urllib.request. Closes 6 Dependabot alerts (#6, #9,
    #10, #11, #12, #13, #19) by eliminating the vulnerability surface rather than
    patching it.
  • Bumped Pillow>=12.2.0 (fixes #14, #15, #16, #17, #18, #20 — OOB write,
    FITS decompression bomb, font integer overflow, PDF parsing DoS, and related
    CVEs).
  • Bumped pytest>=9.0.3 in dev deps (fixes #7).

Changed

  • Dropped Python 3.8 and 3.9 support — both are past EOL and the patched
    versions of Pillow and pytest all require >=3.10. requires-python is now
    >=3.10.
  • CI matrix: removed 3.8/3.9 runners, added 3.13.

0.4.9 — Video input broadening and wire safety

19 May 18:13
c38afce

Choose a tag to compare

[0.4.9] - 2026-05-19 - Video input broadening and wire safety

Added

  • send_video_frame now accepts raw bytes/bytearray: JPEG bytes are passed
    through without re-encoding (zero CPU cost on hardware that outputs JPEG
    natively); other formats (PNG, BMP, WebP) are decoded via Pillow and
    re-encoded as JPEG. Install plexus-python[video] for Pillow support.
  • stream_camera(url, camera_id, fps, quality) — streams from any
    FFmpeg-supported source (RTSP, video file, capture device). Requires FFmpeg
    on $PATH. Returns a threading.Event; call .set() to stop.
  • read_mjpeg_frames(pipe) — public generator that parses raw MJPEG byte
    streams (e.g. FFmpeg stdout) into individual JPEG frames by SOI/EOI markers.
    Useful for custom FFmpeg pipelines before handing off to send_video_frame.
  • Optional video extras group: pip install plexus-python[video] installs
    Pillow for non-JPEG input decoding and automatic oversized-frame downsampling.

Changed

  • Frames that would exceed the gateway's 1 MB wire limit are automatically
    re-encoded at a proportionally lower quality. A one-time warning is printed
    to stderr; subsequent frames are silently clamped.
  • stream_camera raises PlexusError synchronously (before spawning a thread)
    when FFmpeg is not found, rather than silently dying in the background.
  • Minimum requests bumped to >=2.32.4 (fixes CVE in extract_zipped_paths).
  • Minimum Pillow bumped to >=11.2.1 (fixes OOB write, FITS decompression bomb,
    font integer overflow, PDF parsing DoS).
  • Dropped Python 3.8 support (EOL October 2024); minimum is now Python 3.9.

0.4.8 — Video input broadening and wire safety

19 May 17:49
247bcf9

Choose a tag to compare

v0.4.8: video input broadening and wire safety (#7)

## What does this PR do?

<!-- Brief description of the change -->

## Why?

<!-- What problem does this solve? Link to issue if applicable. -->

Closes #

## Checklist

- [ ] Tests pass (`pytest`)
- [ ] Linting passes (`ruff check .`)
- [ ] New code has type hints
- [ ] Updated CHANGELOG.md (if user-facing change)
- [ ] Tested on target hardware (if applicable)

v0.4.7: video streaming API

15 May 03:27

Choose a tag to compare

See CHANGELOG.md

v0.4.6

06 May 15:17

Choose a tag to compare

Clock QA improvements

v0.4.5 — Stderr status output

27 Apr 20:33

Choose a tag to compare

Same code as the failed v0.4.4 (which 4xx'd in CI on a stray f-prefix), now lint-clean.

Added

[plexus] … status lines on stderr at every meaningful state change so scripts that don't configure the logging module still tell the user what's going on. Set PLEXUS_QUIET=1 to suppress.

  • ✓ Connected to gateway as <source_id> on first WS auth
  • ✓ Reconnected as <source_id> after a drop
  • ✓ First N points landed (via ws|http) on first successful send
  • ⚠ WebSocket unavailable, falling back to POST /ingest on WS failure
  • ✗ Auth rejected by gateway: … / ✗ Gateway rejected the API key (401) on auth failures, with a plexus whoami hint
  • ⏸ Send failed, buffering points locally (N queued) when offline
  • ✓ Sending again (drained the local buffer) on recovery

v0.4.4 — Stderr status output

27 Apr 20:31

Choose a tag to compare

Added

[plexus] … status lines on stderr at every meaningful state change so scripts that don't configure the logging module still tell the user what's going on. Set PLEXUS_QUIET=1 to suppress.

  • ✓ Connected to gateway as <source_id> on first WS auth
  • ✓ Reconnected as <source_id> after a drop
  • ✓ First N points landed (via ws|http) on first successful send
  • ⚠ WebSocket unavailable, falling back to POST /ingest on WS failure
  • ✗ Auth rejected by gateway: … / ✗ Gateway rejected the API key (401) on auth failures, with a plexus whoami hint
  • ⏸ Send failed, buffering points locally (N queued) when offline
  • ✓ Sending again (drained the local buffer) on recovery

Why

Users running python my_script.py saw nothing — by default Python's logging module emits at WARNING and above only on the console, so a silent SDK was indistinguishable from "everything's working" until they checked the dashboard. This makes the trip from python my_script.py to "first row visible in the UI" auditable in one terminal.

v0.4.3 — Re-release of 0.4.2 with correct __version__

27 Apr 19:05

Choose a tag to compare

Re-release of 0.4.2. The 0.4.2 wheel shipped with plexus.__version__ == "0.4.1" because the tag was cut one commit before the __init__.py bump landed. 0.4.3 is the same code with the version metadata correct. 0.4.2 has been yanked.

See the 0.4.2 release notes for the actual changes (branded CLI auth success page + 10s auto-redirect to the app).