v3.5.1
3.5.1 is a stabilization and quality release. Headline themes: auto-pairing for 1↔1 Inverse3 + grip setups, fresh GET /devices/{id} motion state without an open WebSocket session, an end to the force/position mode-flip screech, and a self-tuning service tick scheduler under sustained load.
Highlights
- Auto-pairing for 1↔1 Inverse3 + grip installs. When one Inverse3 and one grip are ready, the SDK registers a pairing automatically —
pen_attachedand Minverse calibration unlock stop misrouting in multi-device setups. - Fresh
GET /devices/{id}snapshots without an open session. Inverse3 / Inverse3x / Minverse on firmware v7.5+ now have motion state polled at 20 Hz regardless of WebSocket activity. Pre-v7.5 firmware skips the poll and warns once. - Force/Position swap no longer screeches. Switching
set_cursor_force↔set_cursor_positionis slot-exclusive — only the latest per device survives between ticks. HARP's 200 ms idle-gap workaround is obsolete. - Self-tuning tick scheduler. The main loop adapts its dispatch rate under load so a slow tick can't grow the command queue without bound.
- 1-in-1-out streaming replies under load. Per-WS-message streaming replies are capped at 1/ms per session; the previous buffer is replayed when the cap denies, so sim loops never block on
recv().
Internal improvements
Devices
- Per-device Inverse3 ↔ VerseGrip pairing registry.
GET|POST|DELETE /devices/{sel}/paired_withis a per-device 1:1 map.POSTevicts conflicts on either side;DELETEclears the selected entry; selector must resolve to one ID. - 20 Hz motion-state poll on firmware v7.5+.
GET /devices/{id}returns freshcursor_position,cursor_velocity,angular_position,angular_velocityevery 50 ms; transparent to active sessions. - Wireless VerseGrip
set_extension_datarate-controlled. Drop-older / repeat-on-idle pipeline drained on the service tick — over-sending no longer saturates the radio link, under-sending no longer leaves a stale value.
Sessions
- New WS-receive fast-path for control-only batches (force/position) skips the configure-aware pipeline;
configure/set_profile/ custom commands still go through the race-fix.
Observability
- Detection log cadence is per-port and chronicity-aware. Each blacklisted port is gated independently; the recurring
"...blacklisted: skipping"line now carries(×N)for ticks silenced between fires. - Wireless VerseGrip detection no longer floods the log when a non-WVG device is probed.
Fixes
POST /device.config.presetwithdefaultsorarm_frontnow resets the device's mount to the factory preset (was a silent no-op).basisis preserved so app-configured bases survive mount preset changes.force_render_full_stateno longer returns a snapshot with a missingconfigblock when the matching configure landed in the same WS message — the configure path drains synchronously before the snapshot.- Cross-session
force_render_full_statereturns the target's full snapshot. Both A and B now see a full payload (was: A received streaming-only). - Cross-session commands with an unknown
target_session_idno longer hang the request-reply loop. Requester receives its own snapshot + asession-command-droppedevent (cross-session-unknown-target). - Minverse multi-device calibration unlocks no longer misroute. Calibrating Minverse A no longer unlocks Minverse B; same fix for the inkwell-success heading broadcast.
- HTTP device selector accepts
#1234and1234as device ID; selector classes (inverse3,verse_grip) work alongside index; 404 messages preserve the original selector expression. - Wireless VerseGrip
readyflag is now gated on the initial device-info handshake — previously possible to flip before the device fully announced itself on certain re-attach paths. - Runtime changes to keyed-rate-gate-backed settings now take effect on the next hit (was: frozen at first emplace; only new sessions picked up the change).
Potential breaking changes
- HTTP 404 strings unified across
basis,preset,mount,transform,force_gate:"{type} device #{id} not found"→"no device matches selector '{expr}'". Session 404 likewise. - Settings glob
devices/inverse*/...→devices/*inverse/...for force-scale gain, force-gate gain, control timeout,safeties/expose_in_snapshot. 3.5.0 settings files using the old literal will fail to bind. - Settings: serialization globals moved to
session/serialization/*(explicit_fields,force_complete_transforms,preview/*). Oldserialization/*paths still resolve via deprecated aliases; removal at 4.0. - Behaviour: clients using the per-message WS reply as a tick-sync handshake see at most one reply per ms per session under sustained traffic. Full snapshots on config change are unaffected.
Deprecations
None in 3.5.1. The preview master switch is the deprecation plumbing for the upcoming 3.6 silent-to-warn pipeline; the first deprecation pass is scheduled for 3.5.2.