6.8 KiB
XGRIDS / LixelKity K1 plugin
This directory is the package boundary for the first Mission Core device
plugin. It now owns the canonical v1alpha2 manifest
plugin.manifest.json. The statically linked frontend
contribution lives in frontend/ beside the manifest and profiles;
its provisioning, acquisition/replay, diagnostics and metrics are separate
plugin-owned components. The
verified backend implementation is physically isolated in
src/k1link/device_plugins/xgrids_k1/.
The v1alpha2 catalog can describe one or more independently profiled models.
This manifest currently exposes only xgrids.lixelkity-k1, and the transitional
runtime still owns one active model/session at a time. Concurrent model/session
routing remains a later supervisor milestone.
The plugin owns:
- the exact firmware/topology compatibility profiles under
profiles/, with strict evidence flags and a fail-closed loader; - BLE discovery hints and K1 GATT metadata;
- Bridge and Direct Connect through the reviewed firmware-3 BLE Wi-Fi provisioning frame, plus a one-shot macOS CoreWLAN Quick Connect adapter;
- K1 LAN status and private-address validation;
- subscribe-only data MQTT transport plus a separately bounded canonical application-control transport;
- native
.k1mqttcapture; - firmware-scoped protobuf/LZ4 and legacy codecs;
- normalization of K1 point cloud and pose, plus raw-only preservation of the still-undecoded status and heartbeat channels;
- exact-profile left/right RTSP producer selection, H.264 copy-remux preview and the handoff of acquisition-owned init/fMP4/index evidence to the host archive;
- K1-specific operator instructions and compatibility tests.
- the scoped React
device.connectioncontribution and its BLE/Wi-Fi and acquisition pipeline UI. - the interactive canonical application-control session: one socket owner, one operator launch intent, response-gated workspace/project/START stages, a separate explicit STOP action, live status gates and no automatic retry.
The plugin does not own:
- Mission Core navigation, fleet, missions, users, roles, or audit;
- the generic spatial scene or Rerun Web Viewer;
- the host observation catalog, RRD preparation/cache, recorded-camera player, workspace layout, platform storage, remote transport, or other devices.
The k1link distribution and CLI names remain compatibility names. All
device-specific implementation behind them is plugin-owned, and every change
must preserve replay and real-device acceptance.
Mission Core imports this plugin only from
apps/control-station/src/composition/devicePlugins.ts. The generic shell never
branches on this plugin ID or reads k1_ip, BLE candidates, MQTT topics, or
other vendor state. The frontend contribution imports the host only through
@mission-core/plugin-sdk; its CSS is scoped below .xgrids-k1-plugin.
Backend startup loads the reviewed factory declared by backendEntrypoint, then
cross-checks the runtime-owned plugin ID, version, supported host API and exact
action set against this manifest. The runtime must complete the versioned
control-plane handshake and report ready before any action is admitted.
Actions enter through the host dispatcher and the transitional facade
src/k1link/device_plugins/xgrids_k1/facade.py. The old flat routes live in the plugin's
legacy router; both paths now cross the same runtime transport and delegate to the proven
XgridsK1CompatibilityService methods. Synchronous capture/runtime operations
run outside the FastAPI event loop.
Model switching calls the plugin deactivation hook. It is rejected while the
canonical K1 control socket is open, so navigation can never become an implicit
device STOP. Operator-manual acquisition uses semantic acquisition.stop in
capture-only mode; replay and pre-v1alpha2 sessions retain the legacy
stream.stop shim. BLE, MQTT, codec,
archive discovery and RRD export modules now live under the plugin package
after replay parity and physical K1 regression. The current transport remains
in-process and its health is lifecycle-only; process isolation, crash/restart
containment and signed deployment remain later supervisor gates.
The compatibility profile is descriptive and cannot itself authorize a vendor
write. The UI selects the exact firmware 3.0.2 local-network profile and an
exact topology for Bridge, Quick Connect or Direct Connect; the
canonical bootstrap then requires a correlated live DeviceInfo match for
model LixelKity K1, platform type A4, activation and firmware before START.
Validate the current exact-match profile without device I/O with:
uv run python plugins/xgrids-k1/profile_loader.py
Plugin v0.6.0 retains the physically accepted v0.5.0 control transport and adds
the connection matrix behind the existing explicit network.provision action.
Bridge remains the default. Direct Connect sends the same single reviewed
99-byte frame with credentials for an already-running controller hotspot. Quick
Connect sends no BLE write: a short-lived Swift/CoreWLAN helper receives the
operator-entered K1 AP credentials only over stdin, performs at most one scan
and one association, and never receives an automatic retry. Mission Core then
uses the observed K1 AP data-plane address. Automatic extraction of AP
credentials from undocumented BLE data is deliberately not implemented.
Plugin v0.5.0 installed the reviewed application-control transport behind
explicit plugin actions.
The normal UI accepts the project name and one explicit launch confirmation.
It then performs operations 1–6, operation 7 and operations 8–10 only after the
previous response barrier succeeds, prepares local reception, and emits one
START carrying the project name. Local state polling controls only when the
next reviewed action may be requested; it never schedules a device command by
elapsed time. START waits for bound SCANNING + project + init_ready before
operations 13–14. STOP is separately permitted, never retried, and keeps the same socket until K1
reports unbound READY. That protocol state automatically completes local sealing;
stable green is physical corroboration rather than a second UI gate. The
admin CLI still provisions the fixed Keychain item through Apple's hidden
prompt without accepting the private value as an argument. No physical command
is emitted merely by loading the plugin, opening the page, navigating, polling
state or running repository tests. The full v0.5.0 START/live/STOP/save path is
physically accepted on the reviewed K1/A4/FW 3.0.2 unit.
The optional owner-controlled iPhone/LixelGO observation tool lives under
lab/iphone-capture/. It pins pymobiledevice3 in a
separate uv environment, writes only ignored evidence sessions, and remains a
lab subprocess rather than a plugin/runtime dependency. The first capture is
gated by ADR 0004 and ADR 0005.