Replace FFmpeg UDP forwarding with WebSocket streaming for lower latency. Changes: - Add WebSocket endpoint at /stream/ws/video for video frame transmission - Implement capture_video_frames worker using OpenCV to read Tello UDP stream - Add Canvas element to web UI for video display - Create WebSocket client in app.js with base64 JPEG decoding - Start video capture worker on server lifespan - Add CLAUDE.md documentation for codebase architecture Technical details: - Video frames captured at ~30 FPS from udp://192.168.10.1:11111 - Frames encoded as JPEG (80% quality) and base64-encoded - WebSocket provides bidirectional persistent connection for minimal latency - Auto-reconnection on WebSocket disconnect - Video worker waits for Tello connection and command mode before streaming Co-Authored-By: Claude <noreply@anthropic.com>
4.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Tello Commander is a FastAPI-based control system for DJI Tello drones. The system provides a web UI for controlling the drone and manages WiFi connectivity, video streaming, and flight telemetry. It runs on Raspberry Pi and Linux systems with supervisor for process management.
Development Commands
Running the Server
Local development:
export $(grep -v '^#' env | xargs) && python src/server/server.py
Production (via supervisor on Raspberry Pi):
# Manage remote server
./scripts/manage_server.sh {start|stop|restart|status|update|logs}
# View logs
./scripts/manage_server.sh logs
Deployment
Pull latest changes:
./scripts/pull_from_origin.sh
Update supervisor service:
./scripts/manage_server.sh update
Architecture
Core Components
Server Entry Point (src/server/server.py):
- FastAPI application with lifespan management
- Initializes shared state with Tello instance and connection status
- Spawns background workers:
maintain_connection_to_telloandcollect_flight_stats - Serves static files from
src/client/staticand templates fromsrc/client/templates - Runs on port 8001 with reload enabled
Background Workers (src/server/workers.py):
maintain_connection_to_tello: Continuously manages WiFi connection to Tello via dhclient (wlan1 interface). Setsstate["connection"]to "OK" or "NOK"collect_flight_stats: Polls battery, temperature, and barometer data. Enters command mode when connected. Updatesstate["stats"]forward_video_stream: FFmpeg-based video forwarding from Tello (UDP 11111) to client- Uses ThreadPoolExecutor for blocking I/O operations
Routers:
router_main.py: Root endpoint, UI endpoint (/ui), status endpoint (/status), reconnect triggerrouter_command.py: Flight commands (/takeoff,/land,/turn,/move,/emergency,/end)router_stream.py: Video streaming control (/streamon)- All routers access shared state via
request.app.state.shared_state
Connection Management (src/server/services/connections.py):
release_and_renew: Uses dhclient to release/renew IP on wlan1 interfacecheck_dhcp_ip: Validates DHCP assignment matches expected Tello IP (from envTELLO_STATION_IP)- Designed for Linux network management via subprocess calls
State Management
Shared state dictionary stored in app.state.shared_state:
connection: "genesis" | "OK" | "NOK" - WiFi connection status to Tellotello: DJI Tello instance (djitellopy)command: Boolean - Whether Tello is in command modestats: Dict withbat,temp,barokeysstreamon: Boolean - Video stream status
Network Configuration
Environment variables (defined in env file):
TELLO_SSID_NAME: Tello WiFi network nameTELLO_SSID_PASS: Tello WiFi passwordTELLO_STATION_IP: Expected IP address for this station on Tello network (e.g., 192.168.10.4)DONGLE_IFNAME: WiFi interface name (wlan1)
Deployment Details
Supervisor Configuration (src/server/supervisor/tello-server.conf):
- Service runs as user
uad - Working directory:
/home/uad/tello-commander - Uses CPU affinity (taskset) to distribute load
- Auto-restart enabled
- Logs written to supervisor directory
Remote Access:
- Default server IP:
192.168.1.219:8001 - Web UI:
http://192.168.1.219:8001/ui - Managed via SSH (
uad@192.168.1.219)
Important Patterns
Router Pattern:
All routers are registered through routers/base.py which creates a single api_router. This router is imported in server.py during lifespan startup to avoid circular imports.
Connection Recovery:
When state["connection"] becomes "NOK", the maintain_connection worker automatically attempts reconnection via dhclient release/renew cycles. Manual reconnection can be triggered via /reconnect endpoint.
Barometer Calibration:
Barometer readings are calibrated in workers.py using get_calibrated_altitude with a hardcoded offset (39 meters for "tuncel yerde").
Dependencies
Key packages (from requirements-dev.txt):
fastapi==0.112.0- Web frameworkuvicorn==0.30.5- ASGI serverdjitellopy==2.5.0- Tello SDK wrapperloguru==0.7.2- Loggingnmcli==1.3.0- NetworkManager CLI wrapperopencv-python==4.10.0.84- Video processingav==12.3.0- Video codec bindingsffmpegio- FFmpeg wrapper
Current Branch
Development occurs on refactor/v2 branch.