A beautiful radar visualization web application that displays real-time tracking data.
simple-radar/
├── fe/ # Frontend
│ ├── index.html # Main HTML page
│ ├── style.css # Styling
│ └── scripts/
│ ├── config.js # Configuration constants
│ ├── radar.js # Radar rendering logic
│ ├── network.js # API calls and polling
│ └── main.js # Application initialization
│
├── be/ # Backend
│ ├── server.js # Main server file
│ ├── config.js # Server configuration
│ └── routes/
│ ├── health.js # Health check endpoint
│ └── radar.js # Radar data endpoint
│
└── package.json # Project metadata
- Beautiful Radar Display: Circular radar with cartesian coordinate mapping
- Real-time Playback: Automatically advances timestamps every 50ms
- Multi-Target Tracking: Displays multiple tracked objects simultaneously
- Health Monitoring: System status HUD in top-right corner
- Dot Tooltips: Each radar dot displays track ID, range, and velocity
- Track History: Maintains position history for smooth trail effects
- Auto-cleanup: Clears dots when server becomes unavailable
- Modern Design: Dark theme with cyan and red neon accents
First time setup (creates Python venv and installs dependencies):
bun install
bun run python:setupbun run dev
# or
bun startThis starts both the Python backend (port 1337) and frontend (port 8001) servers with color-coded output.
Then open your browser to: http://localhost:8001
Press Ctrl+C to stop both servers.
bun run prod
# or
bun src/run.ts --prodIf you prefer to run servers in separate terminals:
Terminal 1 - Backend (Python):
bun run be
# or
./venv/bin/python src/radar_tracks_server.pyTerminal 2 - Frontend:
bun run feNote: You cannot open
fe/index.htmldirectly in the browser due to CORS restrictions with ES6 modules. You must use the frontend server.
GET /tracks- Returns current track data for all radarsGET /radars_status- Returns status for all radarsPOST /radar/on- Turn a radar on (requiresradar_idin body)POST /radar/off- Turn a radar off (requiresradar_idin body)
{
"radar1": {
"track_id": 1,
"azimuth": 45.0,
"range": 25.5
}
}{
"radar1": {
"is_active": true,
"orientation_angle": 70.0
}
}API_BASE: Backend server URLHEALTH_CHECK_INTERVAL: Health check polling interval (ms)RADAR_CHECK_INTERVAL: Radar data polling interval (ms)SERVER_TIMEOUT: Time before clearing dots when server is offline (ms)MAX_DOTS: Maximum number of dots to display
- Frontend: TypeScript, HTML5 Canvas, CSS3
- Backend: Python Flask server
- Runtime: Bun (for frontend and dev scripts), Python 3.8+ (for backend)
- No build process required for frontend
The project uses MediaMTX for RTSP to WebRTC streaming.
docker run -d --name mediamtx \
-p 8554:8554 \
-p 8889:8889 \
-p 8189:8189/udp \
-p 9997:9997 \
-v "$PWD/mediamtx.yml:/mediamtx.yml" \
bluenviron/mediamtx:latestCamera streams are configured in mediamtx.yml:
- Each camera has day (channel 0) and night (channel 1) streams
- Paths use format:
cam{N}_{channel}(e.g.,cam7_0for Camera 7 day mode) - WebRTC WHEP endpoint:
http://localhost:8889/{path}/whep
| Port | Protocol | Description |
|---|---|---|
| 8554 | TCP | RTSP server |
| 8889 | HTTP | WebRTC WHEP endpoint |
| 8189 | UDP | WebRTC ICE |
| 9997 | HTTP | API server |
By default, mediamtx.yml uses TCP for RTSP source connections (rtspTransport: tcp). On Linux with native Docker networking, you can try UDP for lower latency:
pathDefaults:
rtspTransport: udp # or tcp
sourceOnDemand: yes