change to web visualizer

This commit is contained in:
admin committed 2026-09-11 20:14:37 +07:00
1 parent 87be72b52b
commit 417ced90fa
9 files changed
+2580 -680

No files matched your search

+565
View File
@@ -0,0 +1,565 @@
# ESP32-S3 LD2453 Radar — Web Visualizer cho Orange Pi
> **English version** below / Xem bản tiếng Anh ở cuối file.
Hướng dẫn cài đặt và sử dụng **Web Visualizer** trên Orange Pi (hoặc máy tính bất kỳ có Python 3.8+) để hiển thị dữ liệu radar realtime dưới dạng giao diện web đẹp trên trình duyệt.
> ✅ **Không cần giao diện desktop (Tkinter/Pygame) nữa.** Visualizer chạy nền dạng Web Server (FastAPI), bạn chỉ cần mở trình duyệt (trên điện thoại, laptop, PC…) là xem được đồ họa.
---
## 1. Chuẩn bị
### 1.1 Yêu cầu hệ thống
- Orange Pi / Raspberry Pi / PC bất kỳ có **Python 3.8+**
- Cùng mạng LAN với ESP32 (WiFi hoặc cổng LAN)
- Biết IP của ESP32 (xem Serial Monitor khi boot, hoặc vào router xem)
### 1.2 Cấu trúc thư mục
```
orangepi-server/
├── visualizer.py # Web Server (FastAPI): kết nối ESP32 + broadcast tới trình duyệt
├── requirements.txt # Python dependencies
├── templates/
│ └── index.html # Giao diện Web (HTML)
└── static/
├── style.css # Giao diện (CSS): sáng/tối, responsive, song ngữ
└── app.js # Canvas render + WebSocket client trong trình duyệt
```
### 1.3 Copy file lên Orange Pi
Copy cả thư mục `orangepi-server/` lên Orange Pi (clone repo, SCP, USB…).
Ví dụ SCP (chạy từ máy bạn):
```bash
scp -r orangepi-server/ orangepi@<ORANGE_PI_IP>:/home/orangepi/
```
---
## 2. Cài đặt Python dependencies
```bash
cd ~/orangepi-server
# (Tùy chọn nhưng khuyến nghị) Dùng virtual env
python3 -m venv venv
source venv/bin/activate
# Cài dependencies
pip install -r requirements.txt
```
**Cài global (nhanh hơn, không khuyến nghị):**
```bash
pip3 install -r requirements.txt
```
> Không cần `python3-tk` nữa — toàn bộ chạy trên web.
---
## 3. Sử dụng
### 3.1 Bật ESP32 ở chế độ Full Stage
Trong `config.h` trên Arduino IDE:
```cpp
#define DIAGNOSTIC_MODE 0 // Full mode: WiFi + WebSocket + REST API
```
Nạp code, mở Serial Monitor lấy IP ESP32. Ví dụ: `192.168.1.100`
### 3.2 Khởi động Web Visualizer trên Orange Pi
```bash
# Nếu dùng venv:
source venv/bin/activate
# Chạy (thay bằng IP ESP32 của bạn):
python3 visualizer.py 192.168.1.100
```
Các tùy chọn lệnh:
```bash
# Tùy chỉnh port (mặc định 8000):
python3 visualizer.py 192.168.1.100 --port 8080
# Giới hạn truy cập chỉ local (không cho từ ngoài):
python3 visualizer.py 192.168.1.100 --host 127.0.0.1
# Log chi tiết:
python3 visualizer.py 192.168.1.100 --verbose
```
Màn hình console sẽ hiển thị:
```
==============================================================
ESP32-S3 LD2453 Radar — Web Visualizer
==============================================================
ESP32 : ws://192.168.1.100/ws
Web UI : http://0.0.0.0:8000/
WS UI : ws://<OrangePi_IP>:8000/ws
==============================================================
```
### 3.3 Mở trình duyệt xem kết quả
Trên **bất kỳ thiết bị nào cùng LAN** (điện thoại, laptop, PC…):
```
http://<IP_OrangePi>:8000/
```
Ví dụ: Orange Pi có IP `192.168.1.50` → mở `http://192.168.1.50:8000/`
---
## 4. Tính năng giao diện Web
### 4.1 Tổng quan
| Tính năng | Mô tả |
|---|---|
| 🎨 **Giao diện đẹp** | Chủ đề sáng/tối (Light/Dark), màu sắc theo chuẩn Catppuccin |
| 🌐 **Song ngữ** | Bật/tắt Tiếng Việt / English ngay trên header |
| 📱 **Responsive** | Xem tốt trên cả mobile, tablet, desktop |
| 🧭 **Radar Canvas** | Hiển thị radar, grid 1m, vòng tròn khoảng cách, hiệu ứng quét (sweep) |
| 🎯 **Targets** | Lên đến 3 target với màu khác nhau, đường dẫn (trail), mũi tên tốc độ, nhãn tọa độ |
| 🟩 **Zones** | 3 vùng hình chữ nhật với màu & trạng thái (Có người / Trống) |
| 📊 **Thống kê** | Frames nhận, target hợp lệ, vùng có người, cập nhật lần cuối |
| 📝 **Chi tiết** | Thông tin chi tiết từng target & zone ở panel bên phải |
| ✏️ **Sửa zones** | Chỉnh tọa độ zones ngay trên web, tự động gửi cập nhật tới ESP32 |
| 🔗 **Multi client** | Nhiều trình duyệt xem cùng lúc, dữ liệu đồng bộ realtime |
### 4.2 Header
- 🟢 / 🟡 / 🔴 Trạng thái kết nối **ESP32** và **WebSocket**
- ☀️ / 🌙 Nút chuyển Sáng / Tối
- `VI / EN` Nút chuyển ngôn ngữ
### 4.3 Radar View (Canvas)
- **Grid**: Mỗi ô = 1 mét, có đánh số (−5m ← 0 → +5m ngang, 0 → 7m thẳng)
- **Vòng tròn khoảng cách**: Các vòng tròn nét đứt cách nhau 1m tính từ radar
- **Trục Y chính**: Nét đứt màu xanh, chỉ hướng thẳng từ radar
- **Radar**: Vị trí radar ở giữa cạnh dưới (điểm đỏ, ghi chữ RADAR)
- **Hiệu ứng quét**: Cảm giác radar thực tế, có thể tắt trong công cụ
- **Zones (3 hình chữ nhật)**:
- Zone 1 (Xanh lá), Zone 2 (Cam), Zone 3 (Đỏ)
- Có người → Màu đậm, nét liền, badge `CÓ NGƯỜI`
- Trống → Màu nhạt, nét đứt, badge `TRỐNG`
- **Targets (3 điểm)**:
- Màu: Vàng (Slot 1), Tím (Slot 2), Xanh (Slot 3)
- Điểm sáng có viền trắng, bao quanh là hiệu ứng glow
- Mũi tên: Tốc độ (độ dài tỉ lệ với cm/s, hướng theo chuyển động)
- Nhãn: `T# | X,Y mm | tốc độ cm/s`
- Đường dẫn (trail): Mờ dần theo thời gian (tối đa 3.5s)
- Target vừa mất dấu: Hiển thị viền đứt mờ trong 3.5s nữa
### 4.4 Công cụ trên Canvas (bên phải tiêu đề)
- ✅ **Hiệu ứng quét** — Bật/tắt hiệu ứng quét radar
- ✅ **Đường dẫn target** — Bật/tắt trail fade
- ✅ **Hiển thị label** — Bật/tắt nhãn trên zones & targets
### 4.5 Panel bên phải
**Thống kê:**
- Frames nhận (tổng cộng)
- Cập nhật cách đây bao nhiêu giây
- Target hợp lệ / 3
- Vùng có người / 3
**Chi tiết Target:**
- Mỗi target có một thẻ màu, hiển thị:
- Trạng thái: `Đã phát hiện` / `Vừa mất dấu` / `Trống`
- `X, Y (mm)`
- `Tốc độ (cm/s)`
- `Khoảng cách (m)`
- `Góc (°)` — 0° = thẳng, âm = trái, dương = phải
**Zones:**
- Danh sách 3 zones với tọa độ
- Nút **Sửa zones** mở form chỉnh sửa từng toạ độ X1/Y1/X2/Y2 (mm)
- **Mặc định**: Khôi phục layout gốc
- **Hủy**: Bỏ sửa
- **Lưu & Áp dụng**: Gửi cập nhật POST `/api/zones` → forward tới ESP32 `/updateZones`, hiển thị toast thành công
---
## 5. Kiến trúc & luồng dữ liệu
```
┌───────────┐ WebSocket /ws ┌──────────────────┐ WebSocket /ws ┌──────────────┐
│ ESP32-S3 │ ◄──────────────────► │ Orange Pi (WS │ ◄──────────────────► │ Trình duyệt │
│ LD2453 │ JSON frame radar │ Server FastAPI) │ JSON state đồng bộ │ (Canvas 2D) │
└───────────┘ └──────────────────┘ └──────────────┘
▲ ▲ ▲
│ REST GET /zones │ GET / → trả về index.html │
│ REST POST /updateZones │ GET /static/* → CSS, JS │
└───────────────────────────────────┘ REST API /api/* │
Visualizer tự động gọi ESP32 khi bạn chỉnh zones trên web │
```
**Các endpoint chính:**
| Method | Endpoint | Mục đích |
|---|---|---|
| GET | `/` | Trả về trang web chính |
| GET | `/api/state` | Lấy trạng thái radar hiện tại (JSON) |
| GET | `/api/zones` | Lấy danh sách zones |
| POST | `/api/zones` | Cập nhật zones (forward tới ESP32 `/updateZones`) |
| WS | `/ws` | Endpoint WebSocket cho trình duyệt (broadcast realtime) |
---
## 6. Tùy chỉnh & chạy nền
### 6.1 Chạy nền bằng tmux
```bash
tmux new -s radar
cd ~/orangepi-server && source venv/bin/activate
python3 visualizer.py 192.168.1.100
# Ctrl+B D → detach (thoát ra mà vẫn chạy)
# tmux attach -t radar → quay lại session
```
### 6.2 systemd service (tự chạy khi boot Orange Pi)
Tạo file `/etc/systemd/system/radar-web.service`:
```ini
[Unit]
Description=LD2453 Radar Web Visualizer
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=orangepi
WorkingDirectory=/home/orangepi/orangepi-server
ExecStart=/home/orangepi/orangepi-server/venv/bin/python3 /home/orangepi/orangepi-server/visualizer.py 192.168.1.100 --port 8000
Restart=always
RestartSec=5
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
```
Sau đó:
```bash
sudo systemctl daemon-reload
sudo systemctl enable radar-web
sudo systemctl start radar-web
journalctl -u radar-web -f # Xem log realtime
```
### 6.3 Tùy chỉnh giao diện
- **Màu sắc & chủ đề**: chỉnh các biến CSS ở đầu file `static/style.css` (định nghĩa `--z1`, `--t1`, `--bg`…)
- **Range hiển thị**: chỉnh hằng `MAP.X_MIN/X_MAX/Y_MIN/Y_MAX` trong `static/app.js`
- **Mặc định zones**: sửa `DEFAULT_ZONES` trong `static/app.js` và `STATE.zones[0..2]` trong `visualizer.py`
---
## 7. Troubleshooting
### Không mở được trang web
1. **Ping Orange Pi**: `ping <OrangePi_IP>`
2. **Kiểm tra port đang mở**: `ss -tulpn | grep 8000`
3. **Tường lửa?** `sudo ufw allow 8000/tcp` hoặc tạm thời `sudo ufw disable`
4. **Visualizer đang chạy?** `ps aux | grep visualizer`
### Không thấy dữ liệu radar (không có target)
1. **Kiểm tra trạng thái ESP32** (chip màu đỏ/xanh trên cùng bên phải trang web)
2. **Ping ESP32**: `ping 192.168.1.100`
3. **Test REST ESP32**: `curl http://192.168.1.100/status` → phải có JSON `{"status":"ok",...}`
4. **ESP32 đang DIAGNOSTIC_MODE 1?** → phải là `0` mới có WiFi/WebSocket
5. **Parser ESP32 vẫn là stub?** → Target luôn `INVALID` nếu parser chưa triển khai (thông báo ở README gốc)
### Tốc độ cập nhật chậm
- Mặc định radar LD2453 gửi ~2 frame/giây. Đó là giới hạn phần cứng.
- Đảm bảo Orange Pi và ESP32 có tín hiệu WiFi tốt.
### WebSocket không kết nối (trình duyệt báo lỗi)
- Mở DevTools (F12) → Console xem lỗi chi tiết
- Kiểm tra trình duyệt truy cập đúng `http://<IP>:8000` (không phải `https://`)
- Nếu dùng reverse proxy (Caddy/Nginx): cấu hình WebSocket upgrade (header `Upgrade: websocket`)
---
## 8. So sánh với bản cũ (Tkinter/Pygame)
| Đặc điểm | Tkinter cũ | **Web Visualizer mới** |
|---|---|---|
| Cần màn hình gắn Orange Pi? | ✅ Có | ❌ **Không** (xem trên trình duyệt bất kỳ đâu) |
| Xem trên điện thoại? | ❌ Không | ✅ **Có** |
| Nhiều người xem cùng lúc? | ❌ 1 người | ✅ **Không giới hạn** (multi-client) |
| Đồ họa đẹp? | ⭐⭐ cơ bản | ⭐⭐⭐⭐⭐ **Canvas2D + hiệu ứng + sáng/tối** |
| Chỉnh sửa zones? | Edit code Python | ✅ **Form trên web** |
| Song ngữ VI/EN? | ❌ Không | ✅ **Có** |
| Responsive mobile? | ❌ Không | ✅ **Có** |
---
---
# 🇬🇧 English Version
# ESP32-S3 LD2453 Radar — Orange Pi Web Visualizer
Installation and usage guide for the **Web Visualizer** on Orange Pi (or any machine with Python 3.8+) to display realtime radar data via a beautiful web interface — **no Tkinter/Pygame desktop required anymore**.
---
## 1. Requirements
- Orange Pi / Raspberry Pi / Any PC with **Python 3.8+**
- Same LAN as the ESP32 (Wi-Fi or Ethernet)
- ESP32 IP address known (check Serial Monitor at boot, or router admin)
### 1.1 Folder structure
```
orangepi-server/
├── visualizer.py # FastAPI server: connects to ESP32 + broadcasts to browsers
├── requirements.txt # Python dependencies
├── templates/
│ └── index.html # Web UI HTML
└── static/
├── style.css # Styling: light/dark, responsive, bilingual
└── app.js # Canvas renderer + browser WebSocket client
```
### 1.2 Copy files to Orange Pi
Copy the whole `orangepi-server/` folder to the Orange Pi. SCP example:
```bash
scp -r orangepi-server/ orangepi@<ORANGE_PI_IP>:/home/orangepi/
```
---
## 2. Install Python dependencies
```bash
cd ~/orangepi-server
# (Recommended) Use a virtual env
python3 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
```
**Global install (faster, not recommended):**
```bash
pip3 install -r requirements.txt
```
> No `python3-tk` needed — everything runs in the browser.
---
## 3. Usage
### 3.1 Flash ESP32 in Full Stage mode
In `config.h` (Arduino IDE):
```cpp
#define DIAGNOSTIC_MODE 0 // Full mode: WiFi + WebSocket + REST API
```
Flash the code, grab the ESP32 IP from Serial Monitor. Example: `192.168.1.100`.
### 3.2 Start the Web Visualizer on Orange Pi
```bash
source venv/bin/activate # if using venv
python3 visualizer.py 192.168.1.100
```
CLI options:
```bash
# Custom port (default 8000):
python3 visualizer.py 192.168.1.100 --port 8080
# Restrict to localhost only:
python3 visualizer.py 192.168.1.100 --host 127.0.0.1
# Verbose logging:
python3 visualizer.py 192.168.1.100 --verbose
```
The console will print:
```
==============================================================
ESP32-S3 LD2453 Radar — Web Visualizer
==============================================================
ESP32 : ws://192.168.1.100/ws
Web UI : http://0.0.0.0:8000/
WS UI : ws://<OrangePi_IP>:8000/ws
==============================================================
```
### 3.3 Open the web UI on any device
On **any device on the same LAN** (phone, laptop, desktop…) open:
```
http://<OrangePi_IP>:8000/
```
Example: if Orange Pi IP is `192.168.1.50` → `http://192.168.1.50:8000/`
---
## 4. Web UI features
### 4.1 Highlights
| Feature | Description |
|---|---|
| 🎨 **Beautiful UI** | Light/Dark themes with Catppuccin color palette |
| 🌐 **Bilingual** | Vietnamese / English toggle in header |
| 📱 **Responsive** | Looks great on mobile, tablet, desktop |
| 🧭 **Radar Canvas** | Grid, concentric range rings, sweep animation |
| 🎯 **Targets** | Up to 3 colored targets, trails, velocity arrows, labels |
| 🟩 **Zones** | 3 rectangular zones with occupancy state badges |
| 📊 **Stats** | Frames received, valid targets, occupied zones, latency |
| 📝 **Details** | Per-target and per-zone info in the right panel |
| ✏️ **Zone editor** | Edit zone coordinates directly in the UI → pushes to ESP32 |
| 🔗 **Multi-client** | Any number of browser tabs/screens stay in sync |
### 4.2 Header
- 🟢/🟡/🔴 ESP32 + WebSocket connection status chips
- ☀️/🌙 Theme toggle (Light/Dark)
- `VI / EN` Language toggle
### 4.3 Radar View (Canvas)
- **Grid**: 1m cells with labels (−5m ← 0 → +5m horizontal, 0 → 7m forward)
- **Range rings**: Dashed concentric arcs every 1m from the radar
- **Radar dot**: Red circle at bottom-center with "RADAR" label
- **Sweep effect**: Rotating semi-transparent cone (toggleable)
- **Zones (3 rectangles)**:
- Z1 (Green), Z2 (Orange), Z3 (Red)
- Occupied → solid fill, bold border, `OCCUPIED` badge
- Empty → faint fill, dashed border, `EMPTY` badge
- **Targets (3 slots)**:
- Colors: Yellow (S1), Purple (S2), Cyan (S3)
- Glowing dots with white outline
- Velocity arrow (length ∝ cm/s, points along direction)
- Label: `T# | X,Y mm | speed cm/s`
- Fading trail for each target, persists ~3.5s
- Recently-lost targets show as dashed ghost circles
### 4.4 Tool toggles (top-right of canvas)
- Sweep effect on/off
- Target trails on/off
- Zone/target labels on/off
### 4.5 Side panels (right column)
**Statistics:**
- Total frames received
- Seconds since last frame
- Valid targets / 3
- Occupied zones / 3
**Target details:**
- Colored cards per target with status badge (`Detected`/`Recently seen`/`Free`)
- X/Y (mm), Speed (cm/s), Distance (m), Angle (°)
**Zones:**
- Per-zone list with coordinates and status
- **Edit zones** button opens a form (X1/Y1/X2/Y2 in mm):
- *Reset defaults* → reload original layout
- *Cancel* → close without saving
- *Save & Apply* → POST to `/api/zones` → forwarded to ESP32 `/updateZones` with success toast
---
## 5. Architecture & data flow
```
┌───────────┐ WebSocket /ws ┌──────────────────┐ WebSocket /ws ┌──────────────┐
│ ESP32-S3 │ ◄──────────────────► │ Orange Pi (WS │ ◄──────────────────► │ Browser │
│ LD2453 │ JSON radar frames │ FastAPI Server) │ synced state JSON │ (Canvas 2D) │
└───────────┘ └──────────────────┘ └──────────────┘
▲ ▲ ▲
│ REST /zones /updateZones │ GET / → index.html │
└───────────────────────────────────┘ GET /static/* → CSS, JS │
Zone edits in the UI are forwarded to the ESP32 │
```
**Endpoints:**
| Method | Endpoint | Purpose |
|---|---|---|
| GET | `/` | Main web page |
| GET | `/api/state` | Current radar state (fallback poll) |
| GET | `/api/zones` | Zones list |
| POST | `/api/zones` | Update zones (forwarded to ESP32 `/updateZones`) |
| WS | `/ws` | Realtime broadcast for browser clients |
---
## 6. Background running & customization
### 6.1 Run with tmux
```bash
tmux new -s radar
cd ~/orangepi-server && source venv/bin/activate
python3 visualizer.py 192.168.1.100
# Ctrl+B D → detach; tmux attach -t radar to return
```
### 6.2 systemd service (auto-start at boot)
Create `/etc/systemd/system/radar-web.service`:
```ini
[Unit]
Description=LD2453 Radar Web Visualizer
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=orangepi
WorkingDirectory=/home/orangepi/orangepi-server
ExecStart=/home/orangepi/orangepi-server/venv/bin/python3 /home/orangepi/orangepi-server/visualizer.py 192.168.1.100 --port 8000
Restart=always
RestartSec=5
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
```
Then:
```bash
sudo systemctl daemon-reload
sudo systemctl enable radar-web
sudo systemctl start radar-web
journalctl -u radar-web -f # Live logs
```
### 6.3 Customization tips
- **Colors/themes**: edit CSS variables at top of `static/style.css` (`--z1`, `--t1`, `--bg`…)
- **Display range**: tweak `MAP.X_MIN/X_MAX/Y_MIN/Y_MAX` constants in `static/app.js`
- **Default zones**: modify `DEFAULT_ZONES` in `static/app.js` and `STATE.zones[0..2]` in `visualizer.py`
---
## 7. Troubleshooting
### Can't open the web page
1. Ping Orange Pi: `ping <OrangePi_IP>`
2. Check open port: `ss -tulpn | grep 8000`
3. Firewall? `sudo ufw allow 8000/tcp`
4. Is visualizer running? `ps aux | grep visualizer`
### No radar targets visible
1. Check ESP32 connection status chip (top-right corner of UI)
2. Ping ESP32: `ping 192.168.1.100`
3. Test ESP32 REST: `curl http://192.168.1.100/status` → JSON expected
4. ESP32 still in `DIAGNOSTIC_MODE 1`? → set to `0` for WiFi/WebSocket
5. ESP32 parser is still stubbed? → Targets always `INVALID` until real byte parser is implemented (see main repo README)
### Slow UI updates
- LD2453 radar sends ~2 frames/second by design (hardware limit)
- Ensure good Wi-Fi signal on both ESP32 and Orange Pi
### Browser WebSocket fails to connect
- Open DevTools → Console for the exact error
- Make sure you visit `http://<IP>:8000` (not `https://`)
- If behind Caddy/Nginx: enable WebSocket upgrade headers (`Upgrade: websocket`)
---
## 8. Comparison with old Tkinter/Pygame version
| Aspect | Old Tkinter | **New Web Visualizer** |
|---|---|---|
| Requires a monitor on Orange Pi? | Yes | ❌ **No** — view anywhere |
| View on phone? | No | ✅ **Yes** |
| Multiple viewers? | No | ✅ **Unlimited clients** |
| Graphics quality | Basic ⭐⭐ | **Canvas + effects + themes ⭐⭐⭐⭐⭐** |
| Zone editor | Edit Python | ✅ **In-UI form** |
| i18n (VI/EN) | No | ✅ **Built-in** |
| Mobile responsive | No | ✅ **Yes** |