SDK Test Bench

SDK Test Bench is a standalone managed Application for whole-robot hardware acceptance. It serves a loopback-only browser dashboard, exercises only public Python SDK domains, and never opens a device connection of its own. The sdk_media_lab directory and Application id remain stable for compatibility.

Version 1.1.0 is ready for distribution through the Watcher Desktop Application Marketplace. The dashboard starts in English and provides an EN / 中文 switch in the header. Its icon, web assets, and PCM sample are all contained inside this directory; generated photos and recordings stay under the ignored artifacts/ directory and are never included in a published source snapshot.

Start the Runtime, then run:

watcherobot app run .\examples\sdk_media_lab

The Application opens its http://127.0.0.1:<port> dashboard automatically and the watcherobot app run terminal echoes the startup log containing the exact URL. Set WATCHER_MEDIA_LAB_NO_BROWSER=1 to suppress automatic browser launch; the URL is still printed so it can be opened manually.

When no device is connected, enter the six-digit code shown on the Watcher in the dashboard's Connect robot panel. The local Application sends that code only to the SDK Daemon management endpoint; it does not store the code or route it through an Application business channel. A device paired before launch is reused automatically. If the LAN suppresses broadcast discovery, the optional device IPv4 field sends the same pairing request directly to that same-subnet address while the normal broadcast discovery remains enabled.

The dashboard tests motion, lights, host-to-device PCM playback, one-shot JPEG capture, decoded microphone recording, animation switching, capability discovery, artifacts, diagnostic events, a live camera preview, full-duplex RTC audio, and one combined audio/video RTC session. The live preview uses watcher-rtc/1 only for signaling through the current Application's Device channel; MJPEG frames travel directly from the Watcher to the browser over an unordered, partially-reliable WebRTC data channel named mjpeg-data.

Live preview requires firmware that advertises rtc.video.mjpeg.v1. It keeps a heartbeat while the page is open, uses latest-frame-wins rendering, and releases camera resources when stopped, disconnected, or when the page closes. Full-duplex audio requires rtc.audio.full_duplex.v1, requests the computer microphone only after the user starts the call, enables browser echo cancellation, and releases all local tracks on stop, failure, disconnect, or page close. Its healthy verdict also requires non-silent capture reported by the device, non-silent audio decoded by the browser, and an active remote player; this verifies the robot-to-browser path. The browser-to-robot path additionally requires device receive, decode, I2S output, and non-silent playback evidence with no renderer errors. The operator still confirms the selected OS output device and physical earphones. Packet counters alone do not prove that the robot microphone is audible. Camera and microphone actions capture the surrounding environment; obtain consent before use and handle generated artifacts appropriately.

Controls are arbitrated by hardware resource rather than by one page-wide busy flag. Motion, body lights, and animation each have an independent lease, so all three remain available during live video, full-duplex audio, or combined AV. Camera, microphone, and speaker also have separate leases. Audio-only RTC owns the microphone and speaker but leaves one-shot camera capture available. Video-only RTC owns the camera but leaves either standalone speaker playback or standalone microphone recording available. Combined AV owns all three media leases. A standalone speaker action still excludes another speaker action, and the same rule applies independently to camera and microphone. Combined AV is one firmware session (mode=av), not two peer connections competing for the same codec, camera, network, and teardown resources.

The animation selector is populated from the connected device's evt.sdk.ready.data.animations catalog, so every animation actually installed on the current SD resource set is available without a hard-coded browser list. Start random cycles through that catalog at the selected interval, avoids an immediate repeat, and prefetches the next animation when the firmware advertises animation.prefetch.v1. Random playback remains available during live video, full-duplex audio, and combined AV, and its timers are released on stop, disconnect, or page close.

Current full-duplex firmware negotiates mono Opus with a 48 kHz WebRTC clock while the robot microphone, speaker, and device-side AEC remain at 16 kHz. The browser never attaches its local microphone track to the local audio player. When the computer microphone is heard again in the headphones, inspect the robot's acoustic echo path: healthy playback makes audio_aec_chunks advance, keeps audio_aec_reference_drops at zero, and leaves audio_render_errors/audio_queue_dropped at zero. With no far-end playback, audio_aec_bypass_chunks advances so AEC nonlinear processing does not color near-end robot speech.

The resource panel is backed by the public Robot.resource_baseline, Robot.resource_rtc_baseline, Robot.resource_snapshot, and Robot.resource_history properties. Compare the idle baseline, the snapshot immediately before RTC starts, and the post-stop snapshots when checking for a resource leak. The dashboard checks free bytes, minimum free bytes, and largest contiguous blocks independently for internal RAM, DMA RAM, and PSRAM; this keeps fragmentation visible even when total free RAM still looks healthy. A stable reusable high/low range is acceptable; four monotonically declining post-stop samples across repeated start/stop cycles are reported as a fragmentation trend. The live-video panel also shows source/target/sent FPS, transport latency, browser congestion, and animation FPS/underrun/late-frame pressure so a smooth idle animation cannot hide contention that appears only under AV load.