update UI, version
This commit is contained in:
150
README.md
150
README.md
@@ -1,9 +1,10 @@
|
||||
# ⚡ Mira Firmware Loader
|
||||
|
||||
Công cụ desktop dùng để **scan, phát hiện và flash firmware hàng loạt** cho các thiết bị OpenWrt trong mạng LAN.
|
||||
Công cụ desktop dùng để **scan, phát hiện và flash firmware hàng loạt** cho các thiết bị OpenWrt trong mạng LAN.
|
||||
Hỗ trợ nạp **thủ công** (chọn thiết bị → flash) và **tự động hóa** (scan → phát hiện → flash → retry).
|
||||
|
||||
> **Tech stack:** Python 3.9+ · PyQt6 · Paramiko/SCP · Scapy · Requests · PyInstaller
|
||||
> **Phiên bản:** `1.1.3`
|
||||
> **Phiên bản:** `1.2.0`
|
||||
|
||||
---
|
||||
|
||||
@@ -11,7 +12,7 @@ Công cụ desktop dùng để **scan, phát hiện và flash firmware hàng lo
|
||||
|
||||
```text
|
||||
Mira_Firmware_Loader/
|
||||
├── main.py # UI chính (PyQt6)
|
||||
├── main.py # UI chính (PyQt6) — App + AutoFlashWindow
|
||||
├── version.txt # Số phiên bản ứng dụng
|
||||
├── requirements.txt # Danh sách dependencies
|
||||
├── core/
|
||||
@@ -22,17 +23,19 @@ Mira_Firmware_Loader/
|
||||
│ ├── ssh_new_flash.py # Luồng SSH cho chế độ Nạp Mới (Telnet → set passwd → SSH)
|
||||
│ ├── ssh_update_flash.py # Luồng SSH cho chế độ Update (SSH trực tiếp)
|
||||
│ ├── flash_new_worker.py # NewFlashThread — QThread điều phối Nạp Mới FW
|
||||
│ └── flash_update_worker.py # UpdateFlashThread — QThread điều phối Update FW
|
||||
│ ├── flash_update_worker.py # UpdateFlashThread — QThread điều phối Update FW
|
||||
│ └── auto_flash_worker.py # AutoFlashWorker — QThread tự động scan → flash → retry
|
||||
├── ui/
|
||||
│ ├── components.py # Custom Qt Widgets (CollapsibleGroupBox)
|
||||
│ └── styles.py # Stylesheet toàn ứng dụng
|
||||
│ └── styles.py # Stylesheet toàn ứng dụng (STYLE + AUTO_STYLE)
|
||||
├── utils/
|
||||
│ ├── network.py # Helper IP / network (get_local_ip, get_default_network)
|
||||
│ └── system.py # Lấy thông tin máy, resource path cho PyInstaller
|
||||
├── docs/
|
||||
│ ├── api_flash_docs.md # Tài liệu kỹ thuật LuCI API flash
|
||||
│ ├── load_fw_ssh_docs.md # Tài liệu kỹ thuật SSH flash (cả 2 luồng)
|
||||
│ └── scanner_docs.md # Tài liệu kỹ thuật scanner
|
||||
│ ├── scanner_docs.md # Tài liệu kỹ thuật scanner
|
||||
│ └── auto_flash_docs.md # Tài liệu kỹ thuật tự động hóa nạp FW
|
||||
├── run.sh # Script khởi chạy (macOS/Linux)
|
||||
├── run.bat # Script khởi chạy (Windows)
|
||||
└── build_windows.bat # Script đóng gói thành .exe (Windows, PyInstaller)
|
||||
@@ -89,31 +92,33 @@ Output: `dist\Mira_Firmware_Loader.exe` — không cần cài Python trên máy
|
||||
│ Method: [ API (LuCI) | SSH (paramiko) ] │
|
||||
│ Concurrent devices: [SpinBox] │
|
||||
│ [ ⚡ FLASH SELECTED DEVICES ] │
|
||||
│ ───────────────────────────────────────────────────── │
|
||||
│ [ 🤖 Tự động hóa nạp FW ] │
|
||||
└────────────────────────┬─────────────────────────────────┘
|
||||
│
|
||||
┌──────────────┼──────────────┐
|
||||
│ │
|
||||
┌──────▼──────┐ ┌────────▼────────────────┐
|
||||
│ scanner.py │ │ Flash Workers │
|
||||
│ │ │ │
|
||||
│ 1. Ping │ │ NewFlashThread │
|
||||
│ Sweep │ │ ├─ method=api │
|
||||
│ 2. arp -a │ │ │ └── api_flash.py │
|
||||
│ 3. Scapy │ │ └─ method=ssh │
|
||||
│ ARP │ │ └── ssh_new_flash │
|
||||
└─────────────┘ │ │
|
||||
│ UpdateFlashThread │
|
||||
│ └─ ssh_update_flash.py │
|
||||
└─────────────────────────┘
|
||||
│
|
||||
┌──────────▼──────────┐
|
||||
│ ssh_utils.py │
|
||||
│ (Transport Layer) │
|
||||
│ _create_ssh_client │
|
||||
│ _upload_firmware │
|
||||
│ _verify_firmware │
|
||||
│ _sync_and_sysupgr │
|
||||
└─────────────────────┘
|
||||
┌─────────────────┼─────────────────┐
|
||||
│ │ │
|
||||
┌──────▼──────┐ ┌───────▼──────────┐ ┌───▼──────────────────┐
|
||||
│ scanner.py │ │ Flash Workers │ │ AutoFlashWorker │
|
||||
│ │ │ (thủ công) │ │ (tự động hóa) │
|
||||
│ 1. Ping │ │ │ │ │
|
||||
│ Sweep │ │ NewFlashThread │ │ Phase 1: Scan LAN │
|
||||
│ 2. arp -a │ │ ├─ api_flash │ │ (tối đa 15 lần) │
|
||||
│ 3. Scapy │ │ └─ ssh_new_flash│ │ Phase 2: Flash │
|
||||
│ ARP │ │ │ │ (auto-retry x3) │
|
||||
└─────────────┘ │ UpdateFlash │ │ ├─ api_flash │
|
||||
│ Thread │ │ └─ ssh_new_flash │
|
||||
│ └─ ssh_update │ └──────────────────────┘
|
||||
└──────────────────┘
|
||||
│
|
||||
┌──────────▼──────────┐
|
||||
│ ssh_utils.py │
|
||||
│ (Transport Layer) │
|
||||
│ _create_ssh_client │
|
||||
│ _upload_firmware │
|
||||
│ _verify_firmware │
|
||||
│ _sync_and_sysupgr │
|
||||
└─────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
@@ -138,7 +143,7 @@ Kết quả được merge theo IP và sort tăng dần trước khi trả về
|
||||
- Mặc định ẩn gateway và IP máy tính đang chạy (có thể bật "Show all")
|
||||
- Thiết bị đã flash trong session được đánh dấu "Already Flashed" và tự bỏ tick
|
||||
|
||||
### 3. Flash Firmware
|
||||
### 3. Flash Firmware (Thủ công)
|
||||
|
||||
Có 2 chế độ và 2 method, tổng cộng 3 luồng thực thi khác nhau:
|
||||
|
||||
@@ -169,7 +174,73 @@ Luồng `ssh_update_flash.py`, SSH trực tiếp (không qua Telnet):
|
||||
|
||||
> ⚠️ Update Mode hiển thị cảnh báo nếu IP thiết bị khác `192.168.11.102` và yêu cầu xác nhận.
|
||||
|
||||
### 4. Xử lý song song
|
||||
### 4. 🤖 Tự động hóa nạp FW (MỚI)
|
||||
|
||||
Tính năng nạp FW hoàn toàn tự động — chỉ cần cấu hình và nhấn bắt đầu:
|
||||
|
||||
```
|
||||
Cấu hình → Auto Scan LAN → Phát hiện đủ thiết bị → Auto Flash → Auto Retry → Thông báo
|
||||
```
|
||||
|
||||
#### 4.1. Quy trình
|
||||
|
||||
| Phase | Mô tả |
|
||||
| --------------------- | ------------------------------------------------------------------------- |
|
||||
| **Phase 1: Scan LAN** | Scan mạng liên tục mỗi 5 giây, tối đa **15 lần**, cho đến khi đủ thiết bị |
|
||||
| **Phase 2: Flash** | Nạp FW song song qua ThreadPoolExecutor, tự động **retry tối đa 3 lần** |
|
||||
|
||||
#### 4.2. Cấu hình
|
||||
|
||||
| Tham số | Mô tả | Mặc định |
|
||||
| --------------- | --------------------------------------------- | ------------------- |
|
||||
| **Firmware** | File firmware (.bin/.hex/.uf2) | Lấy từ cửa sổ chính |
|
||||
| **Mạng** | Dải mạng LAN cần scan | Tự suy từ IP host |
|
||||
| **Số lượng** | Số thiết bị cần nạp | 5 |
|
||||
| **Phương thức** | API (LuCI) hoặc SSH | API (LuCI) |
|
||||
| **Song song** | Số thiết bị nạp cùng lúc (0 = không giới hạn) | 10 |
|
||||
|
||||
#### 4.3. Auto-Retry nạp FW
|
||||
|
||||
Khi một thiết bị nạp thất bại, hệ thống tự động retry:
|
||||
|
||||
```
|
||||
Lần 1 → FAIL: Connection timeout
|
||||
⚠️ Log cảnh báo, chờ 2 giây...
|
||||
Lần 2 → FAIL: Upload error
|
||||
⚠️ Log cảnh báo, chờ 2 giây...
|
||||
Lần 3 → DONE ✅ (hoặc ❌ báo lỗi sau 3 lần)
|
||||
```
|
||||
|
||||
- Tối đa **3 lần retry** mỗi thiết bị (`MAX_FLASH_RETRIES`)
|
||||
- Chờ **2 giây** giữa mỗi lần retry để thiết bị ổn định
|
||||
- Nếu hết 3 lần vẫn fail → đánh dấu ❌, tiếp tục thiết bị tiếp theo
|
||||
|
||||
#### 4.4. Scan Timeout
|
||||
|
||||
- Nếu scan **15 lần** mà chưa đủ thiết bị → dừng và hiện cảnh báo
|
||||
- Gợi ý kiểm tra: thiết bị đã bật chưa, dải mạng có đúng không
|
||||
|
||||
#### 4.5. Quy tắc bảo vệ IP `192.168.11.102`
|
||||
|
||||
| Chế độ | Được nạp 192.168.11.102? | Cơ chế |
|
||||
| ------------------------ | :----------------------: | ----------------------------------- |
|
||||
| **New Flash (thủ công)** | ❌ Không | Chặn trước khi flash, hiện cảnh báo |
|
||||
| **Update FW (thủ công)** | ✅ Có | Cho phép bình thường |
|
||||
| **Tự động hóa** | ❌ Không | Tự động lọc khỏi kết quả scan |
|
||||
|
||||
#### 4.6. Lịch sử nạp
|
||||
|
||||
Kết quả nạp được lưu ở 2 cấp:
|
||||
|
||||
| Nơi lưu | Phạm vi | Format |
|
||||
| ------------------------------- | ---------------------- | ------------------------------------ |
|
||||
| `AutoFlashWindow._auto_history` | Phiên tự động hiện tại | `list[(ip, mac, result, timestamp)]` |
|
||||
| `App.flashed_macs` | Toàn bộ session app | `dict{MAC: (ip, mac, result, ts)}` |
|
||||
|
||||
- Cả thành công ✅ lẫn thất bại ❌ đều được ghi lại
|
||||
- Nút "📋 Lịch sử nạp" hiển thị cùng format ở cả 2 cửa sổ: `[HH:MM:SS] ✅/❌ IP (MAC) — result`
|
||||
|
||||
### 5. Xử lý song song
|
||||
|
||||
| Tham số | Mô tả |
|
||||
| ---------------------- | ------------------------------------------------------------------------ |
|
||||
@@ -188,6 +259,23 @@ Luồng `ssh_update_flash.py`, SSH trực tiếp (không qua Telnet):
|
||||
| **SSH Password** | `admin123a` | Hardcoded, không hiển thị trên UI |
|
||||
| **Concurrent devices** | `10` | Số luồng flash song song |
|
||||
| **Show all** | Tắt | Ẩn gateway và IP máy host |
|
||||
| **MAX_FLASH_RETRIES** | `3` | Số lần retry nạp FW (tự động) |
|
||||
| **MAX_SCAN_ROUNDS** | `15` | Số lần scan tối đa (tự động) |
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ Xử lý lỗi tổng hợp
|
||||
|
||||
| Tình huống | Hành vi |
|
||||
| -------------------------------- | --------------------------------------------------- |
|
||||
| Scan exception (network error) | Log lỗi, chờ 3s, scan lại (đếm vào MAX_SCAN_ROUNDS) |
|
||||
| Scan 15 lần chưa đủ thiết bị | Hiện popup cảnh báo, dừng tự động |
|
||||
| Flash thất bại lần 1–2 (tự động) | Log cảnh báo, chờ 2s, retry tự động |
|
||||
| Flash thất bại sau 3 lần retry | Log lỗi, đánh dấu ❌, tiếp tục device tiếp theo |
|
||||
| User nhấn DỪNG | Set stop flag, dừng scan/flash an toàn |
|
||||
| IP 192.168.11.102 + New Flash | Chặn ngay, hiện cảnh báo |
|
||||
| Chưa chọn firmware | Hiện popup cảnh báo, không cho bắt đầu |
|
||||
| Mạng không hợp lệ | Hiện popup cảnh báo, không cho bắt đầu |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user