--- title: Reachy Mini Remote Control App emoji: 🎤 colorFrom: red colorTo: blue sdk: static pinned: false short_description: Remote control Reachy Mini ! hf_oauth: true hf_oauth_expiration_minutes: 480 hf_oauth_scopes: - contribute-repos - manage-repos - write-repos tags: - reachy_mini - reachy_mini_python_app --- # Reachy Mini Remote Control App A standalone app that connects Reachy Mini robot to a remote server for WebSocket-based control. The robot acts as a WebSocket **client** connecting to a remote server (e.g., Hugging Face Space), enabling remote control, video streaming, and bidirectional audio. ## 🚀 Quick Start - Setup Your Control Space This Space provides a beautiful web interface for setting up remote control: ### Option 1: Public Shared Space (Instant) Just copy this URI and configure it on your robot: ``` wss://huggingfacem4-reachy-mini-remote-control.hf.space ``` ### Option 2: Private Space (Recommended) 1. Click "Sign in with Hugging Face" below 2. Clone your own private control space 3. Get your custom URI: `wss://your-username-reachy-mini-remote-control.hf.space` 4. Create a Hugging Face access token with `read` permissions at https://huggingface.co/settings/tokens 5. Configure both the URI and token on your robot (see "Connecting to Private Spaces" below) **👉 Visit the web interface above to get started!** ## Features - **WebSocket Client Architecture**: Robot connects to remote server (works behind NAT/firewalls) - **Profile-Based Configuration**: Easily switch between different remote servers - **Bidirectional Streaming**: Video (robot → server) and Audio (robot ↔ server) - **Movement Control**: Receive movement commands from remote server - **Connection Monitoring**: Track latency, frames, and connection health - **Optional REST API**: Query status and manage profiles via HTTP endpoints ## Architecture ``` Remote Server Robot (this app) Reachy Mini Daemon (Hugging Face Space) WebSocket Server ←────── WebSocket Clients ←────── ReachyMini SDK - /robot - robot_control.py (Zenoh protocol) - /video_stream - video_stream.py - /audio_stream - audio_stream.py ``` The app connects TO a remote server as a client, not the other way around. This simplifies network setup since the robot only needs outbound connections. ## Installation ### From Source ```bash cd reachy_mini_remote_control_app pip install -e . ``` ### Requirements - Python >= 3.10 - Reachy Mini daemon running (`reachy-mini-daemon`) - Remote server running (e.g., [reachy_mini_remote_control/app.py](../reachy_mini_remote_control/app.py)) ## Usage ### 1. Start the Remote Server First, start the remote server that the robot will connect to: ```bash cd ../reachy_mini_remote_control python app.py # Server starts on ws://localhost:8000 ``` ### 2. Start the Reachy Mini Daemon ```bash reachy-mini-daemon --mockup-sim ``` ### 3. Start the Remote Control App ```bash reachy-mini-remote-control-app --profile default ``` The app will: - Connect to the remote server at `ws://localhost:8000` - Stream video and audio - Receive and execute movement commands ### Command Line Options ```bash reachy-mini-remote-control-app [OPTIONS] Options: --profile PROFILE Profile to use (default: from .env) --websocket-uri URI WebSocket URI to connect to (overrides profile) --robot-name NAME Robot name (default: reachy_mini) --log-level LEVEL Logging level (DEBUG, INFO, WARNING, ERROR) --no-rest-api Disable REST API for status endpoints ``` ## Configuration ### Profiles Profiles are stored in `src/reachy_mini_remote_control_app/profiles/`. Each profile is a directory with a `config.txt` file. **Default Profile** (`profiles/default/config.txt`): ``` WEBSOCKET_URI=ws://localhost:8000 VIDEO_JPEG_QUALITY=80 VIDEO_WITH_TIMESTAMP=false VIDEO_FPS=25 AUDIO_WITH_TIMESTAMP=false AUDIO_BATCH_SIZE=4096 ENABLE_METRICS_LOGGING=true METRICS_LOG_INTERVAL_SEC=5 ``` **Example Remote Profile** (`profiles/example_remote/config.txt`): ``` WEBSOCKET_URI=wss://YOUR-SPACE.hf.space VIDEO_JPEG_QUALITY=75 VIDEO_WITH_TIMESTAMP=true VIDEO_FPS=25 AUDIO_WITH_TIMESTAMP=true AUDIO_BATCH_SIZE=4096 ENABLE_METRICS_LOGGING=true METRICS_LOG_INTERVAL_SEC=10 ``` ### Connecting to Private Spaces If you're using a private Hugging Face Space, you need to authenticate with a Hugging Face token: 1. **Create a Hugging Face Access Token**: - Go to https://huggingface.co/settings/tokens - Create a new token with `read` permissions - Copy the token 2. **Configure the Token**: **Option A: Via Profile Configuration** (Recommended) Add the token to your profile's `config.txt`: ``` WEBSOCKET_URI=wss://your-username-reachy-mini-remote-control.hf.space HF_TOKEN=hf_your_token_here ``` **Option B: Via Environment Variable** Add to your `.env` file: ``` HF_TOKEN=hf_your_token_here ``` 3. **Run the app** - it will automatically use the token for authentication when connecting to the private space. ### Environment Variables Create a `.env` file (copy from `.env.example`): ```bash REMOTE_CONTROL_PROFILE=default ROBOT_NAME=reachy_mini LOG_LEVEL=INFO VIDEO_JPEG_QUALITY=80 LATENCY_WARNING_MS=200 ENABLE_REST_API=true REST_API_HOST=0.0.0.0 REST_API_PORT=7860 # Optional: HF_TOKEN for private Hugging Face Spaces # HF_TOKEN=hf_your_token_here ``` ## REST API (Optional) If `ENABLE_REST_API=true`, the app provides HTTP endpoints: ### Get Status ```bash curl http://localhost:7860/status ``` Response: ```json { "robot_connected": true, "control": { "connected": true, "commands_received": 42, "last_command_type": "movement", "last_activity": 1705123456.78 }, "video": { "connected": true, "frames_sent": 1234, "frames_dropped": 5, "fps": 24.8, "latency_ms": 45.2, "latency_avg_ms": 42.1, "latency_min_ms": 38.5, "latency_max_ms": 52.3, "last_activity": 1705123456.78 }, "audio": { "connected": true, "chunks_sent": 567, "chunks_received": 234, "latency_avg_ms": 38.5, "last_activity": 1705123456.78 } } ``` ### List Profiles ```bash curl http://localhost:7860/profiles ``` Response: ```json { "profiles": ["default", "example_remote"], "current": "default" } ``` ### Switch Profile ```bash curl -X POST http://localhost:7860/profile/example_remote ``` **Note**: Requires app restart to take effect. ### Health Check ```bash curl http://localhost:7860/health ``` ## Integration with Reachy Mini Dashboard This app integrates with the Reachy Mini dashboard as a `ReachyMiniApp`: 1. Install the app: `pip install -e reachy_mini_remote_control_app` 2. The app will appear in the dashboard 3. Start from the dashboard UI 4. The dashboard provides the `ReachyMini` instance and `stop_event` ## HuggingFace OAuth This Space uses OAuth for seamless authentication. The metadata above enables OAuth with: - `hf_oauth: true` - Enables OAuth flow - `hf_oauth_expiration_minutes: 480` - Tokens valid for 8 hours - `hf_oauth_scopes: openid, profile` - Access to user info ### How OAuth Works 1. **User clicks "Sign in with Hugging Face"** in the web interface 2. **HuggingFace OAuth flow** - User authorizes the app 3. **Access token returned** - Stored securely in session storage 4. **Space cloning** - User can duplicate the remote control server to their account 5. **Private URI generated** - Custom WebSocket URI for their private space The OAuth implementation uses the `@huggingface/hub` JavaScript library for client-side authentication. See [hf-auth.js](hf-auth.js) for implementation details. ### For Robot Users The robot doesn't need OAuth - it just connects to the WebSocket URI. OAuth is only used in the web interface for space management. ## Deployment to Production ### Hugging Face Space Setup 1. Deploy the remote server ([reachy_mini_remote_control/app.py](../reachy_mini_remote_control/app.py)) to Hugging Face Space 2. Note the Space URL: `wss://YOUR-SPACE.hf.space` 3. Create a new profile: ```bash mkdir -p src/reachy_mini_remote_control_app/profiles/production ``` Edit `profiles/production/config.txt`: ``` WEBSOCKET_URI=wss://YOUR-SPACE.hf.space VIDEO_JPEG_QUALITY=75 VIDEO_WITH_TIMESTAMP=true VIDEO_FPS=25 AUDIO_WITH_TIMESTAMP=true AUDIO_BATCH_SIZE=4096 ENABLE_METRICS_LOGGING=true METRICS_LOG_INTERVAL_SEC=10 ``` 4. Set environment variable: ```bash export REMOTE_CONTROL_PROFILE=production ``` 5. Run the app: ```bash reachy-mini-remote-control-app --profile production ``` ### Network Requirements - **Robot side**: Only **outbound** connections needed (no port forwarding required) - **Server side**: WebSocket server must be publicly accessible - **Protocol**: Use WSS (WebSocket Secure) for production ### Security Considerations - Use WSS (not WS) for encrypted connections - Consider implementing authentication tokens - Monitor connection logs for suspicious activity - Rate limiting on the server side ## Troubleshooting ### Robot fails to connect to daemon ``` Failed to connect to robot: Connection timeout ``` **Solution**: Make sure the daemon is running: ```bash reachy-mini-daemon --mockup-sim ``` ### WebSocket connection fails ``` [Robot Control] Connection failed: Cannot connect to host ``` **Solutions**: 1. Verify the remote server is running and accessible 2. Check the `WEBSOCKET_URI` in your profile 3. Test connectivity: `curl http://YOUR-SERVER:8000/health` (if server has health endpoint) 4. Check firewall rules ### No video/audio streaming **Solutions**: 1. Ensure media is started: check daemon logs 2. Verify WebSocket connections are established: check `/status` endpoint 3. Check frame/audio publisher threads are running (look for log messages) ### High latency Check the `/status` endpoint for latency metrics: ```bash curl http://localhost:7860/status | jq '.video.latency_avg_ms' ``` **Solutions**: - Reduce `VIDEO_JPEG_QUALITY` in profile (e.g., from 80 to 60) - Lower `VIDEO_FPS` (e.g., from 25 to 15) - Use a server geographically closer to the robot - Check network bandwidth ## Development ### Running Tests ```bash pytest tests/ ``` ### Code Structure - `config.py` - Configuration management and profile loading - `monitoring/` - Metrics tracking and connection monitoring - `websocket_clients/` - WebSocket client implementations - `robot_control.py` - Receive movement commands - `video_stream.py` - Send video frames - `audio_stream.py` - Bidirectional audio - `app.py` - Optional REST API for status - `main.py` - Entry point and ReachyMiniApp implementation ## License Same as Reachy Mini SDK. ## Support For issues and questions: - GitHub Issues: [pollen-robotics/reachy_mini](https://github.com/pollen-robotics/reachy_mini/issues) - Email: contact@pollen-robotics.com