Application Architecture
The HausBots tablet app is a React Native presentation layer over a native Ethernet discovery and HB2 command session. Responsibilities are deliberately split so a UI refactor cannot grow the robot command surface:
| Layer | Responsibility |
|---|---|
| Go robot-agent | Read-only /api/v1/identity and /api/v1/health; merges local ROS health with a bounded loopback probe. |
| Go simulator | Laptop-only HTTP + rosbridge test double with deterministic deadlines and command logs. |
| Kotlin discovery | Chooses TRANSPORT_ETHERNET, scans bounded IPv4 CIDRs, validates identity/health, and probes rosbridge on that Network. |
| Kotlin HB2 session | Owns rosbridge envelopes, lease/heartbeat, sequences, readiness, input liveness, exact command allowlist, and neutral/release stop. |
| TypeScript | Renders Launchpad/Control, stores user intent, binds joystick/HID input, and preserves camera/capture UI. |
Discovery and launch
Section titled “Discovery and launch”Launchpad scans HTTP first, then health, then the identity’s rosbridge port.
Each request uses the selected Android Ethernet Network, no proxy, bounded
response bytes, shared concurrency, and one total scan deadline. A candidate
launches only when this scan reached the robot over rosbridge and the robot
reports ready health with a ready controller; a valid identity with degraded
health or an unavailable rosbridge stays visible as degraded for
diagnostics. The robot’s observedAt is reported as a diagnostic and is never
compared with the tablet clock: an isolated switch gives the two devices no
shared time source, so drift must not hide a healthy robot or block launch.
The tablet’s own address, network address, and broadcast address are excluded;
CIDR overrides over 1,024 hosts are rejected rather than truncated.
sequenceDiagram
participant UI as Launchpad
participant N as Kotlin discovery
participant A as Robot-agent :8080
participant R as Rosbridge :9090
UI->>N: scan(saved/detected CIDR)
N->>A: GET /api/v1/identity (Ethernet Network)
N->>A: GET /api/v1/health (Ethernet Network)
N->>R: WebSocket readiness probe (Ethernet Network)
N-->>UI: verified/degraded candidate + health + latency
UI->>N: Launch verified candidate
HB2 control lifecycle
Section titled “HB2 control lifecycle”Control opens without acquiring a lease. Start waits for fresh
TabletStatus, controller readiness, and HTTP health, then calls
/hb2/app/acquire_control with the persisted device client_id. An accepted
lease enters awaiting-fan; only an explicitly accepted fan command enables
drive. Drive uses a native latest-value scheduler at the persisted 5–50 Hz
rate (default 20 Hz). The local source lease is touched at 10 Hz and expires
at 250 ms; it is not the ROS heartbeat. Heartbeat cadence is derived from the
returned lease timeout and runs only while foreground input is valid.
Every command is one of the five publish topics in the public contract. A single writer allocates command sequences; heartbeat has its own counter. Command results are correlated by sequence and command and rejected reasons are shown to the operator. Attachments are limited to MIRA, PUNDIT, and LIFTER with the documented action pairs. Stop freezes new work, sends neutral drive, then performs bounded release; fan output is intentionally retained.
Video and capture
Section titled “Video and capture”The camera URL is derived from the robot’s own address (port 8554, fixed /ptz
path), not carried by identity. The robot-side setup for both feeds is in
Camera Streams with MediaMTX. RTSP playback remains a
native view and camera-only capture continues to use the existing native
coordinator/storage pipeline. The RTSP stack must use the selected Ethernet
Network; if a dependency cannot accept a socket factory, that limitation is
an explicit release check with Wi-Fi enabled. Capture finalization remains
independent of ROS stop semantics and follows its existing foreground,
disconnect, route, and surface lifecycles.
The native Kotlin HB2 session is the sole production ROS transport. TypeScript owns presentation and user intent; no JavaScript ROS client is shipped.
