229 lines
7.1 KiB
Markdown
Executable File
229 lines
7.1 KiB
Markdown
Executable File
# Difference Equation Analyzer
|
||
|
||
Difference Equation Analyzer 是一個用來設計、檢視與驗證離散時間濾波器的工具。後端使用 FastAPI、NumPy、SciPy 與 Pandas;前端使用 Vue 3、Vite、Tailwind CSS 與 Plotly。
|
||
|
||
主要功能:
|
||
|
||
- 設計 Lowpass、Highpass、Bandpass、Notch、1P1Z、2P1Z、2P2Z、PID、SOGI 濾波器。
|
||
- 比較浮點係數與 fixed-point 係數的頻率響應。
|
||
- 手動微調 b/a 係數、a1/a2 組合(支援 δ/r 參數微調)、Q 格式位元數與 fixed-point 整數係數。
|
||
- 透過瀏覽器 Web Serial API 直接將 fixed-point 係數命令送到 MCU(需透過 HTTPS 連線)。
|
||
- 上傳 CSV 時域資料,套用目前差分方程並繪製輸入/輸出波形。
|
||
- 匯出包含濾波輸出欄位的 CSV。
|
||
- 支援深色模式 (Dark Mode) 與響應式 UI。
|
||
|
||
## 專案結構
|
||
|
||
```text
|
||
dea_api.py FastAPI 入口與 HTTP route
|
||
dea/ 後端核心模組
|
||
bode.py 頻率響應計算
|
||
config.py 限制值與伺服器端 serial 設定
|
||
csv_processing.py CSV 讀取、驗證、濾波與匯出
|
||
filter_design.py 濾波器設計
|
||
mcu.py MCU serial port 列表與命令寫入 (後端備用支援)
|
||
schemas.py Pydantic request schema
|
||
security.py LAN 存取限制與安全標頭
|
||
validation.py 係數、頻率與有限值驗證
|
||
src/ Vue 3 前端原始碼
|
||
certs/ HTTPS 自簽憑證與產生腳本
|
||
static/ FastAPI 對外提供的靜態 UI
|
||
static/build/ Vite build 輸出
|
||
tests/ unittest 測試
|
||
dea.service systemd service 範例
|
||
chirp_signal.csv CSV 上傳測試範例
|
||
```
|
||
|
||
## 安裝
|
||
|
||
在目標主機上建立 Python venv 並安裝依賴:
|
||
|
||
```bash
|
||
cd /home/wisetop/diff-eq-analyzer
|
||
python3 -m venv .venv
|
||
.venv/bin/pip install -r requirements.txt
|
||
```
|
||
|
||
安裝前端依賴並建置:
|
||
|
||
```bash
|
||
npm install
|
||
npm run build
|
||
```
|
||
|
||
## HTTPS 設定
|
||
|
||
為了支援 Web Serial API(瀏覽器直接存取本機連接埠),後端必須透過 HTTPS 連線提供服務。
|
||
|
||
1. **產生自簽憑證**:
|
||
```bash
|
||
bash certs/generate_cert.sh
|
||
```
|
||
這會在 `certs/` 目錄下產生 `key.pem` 與 `cert.pem`。
|
||
|
||
2. **信任憑證**:
|
||
由於是自簽憑證,瀏覽器會顯示安全性警告。請在「進階」中選擇「繼續前往」或將其加入信任清單。
|
||
|
||
## 執行
|
||
|
||
### 手動啟動 (HTTPS)
|
||
|
||
```bash
|
||
.venv/bin/uvicorn dea_api:app --host 0.0.0.0 --port 8000 --ssl-keyfile certs/key.pem --ssl-certfile certs/cert.pem
|
||
```
|
||
|
||
瀏覽器開啟:`https://<server-ip>:8000/ui/` 或本機 `https://localhost:8000/ui/`
|
||
|
||
根路徑 `/` 會自動導向 `/ui/`。
|
||
|
||
### 使用 systemd
|
||
|
||
1. 檢查 `dea.service` 中的路徑是否正確(需確認 `ExecStart` 已加上 `--ssl-keyfile` 等參數)。
|
||
2. 啟用並啟動服務:
|
||
```bash
|
||
sudo cp dea.service /etc/systemd/system/
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable dea.service
|
||
sudo systemctl start dea.service
|
||
```
|
||
|
||
查看狀態與 Log:
|
||
```bash
|
||
sudo systemctl status dea.service
|
||
sudo journalctl -u dea.service -f
|
||
```
|
||
|
||
## MCU 連接埠 (Web Serial)
|
||
|
||
本工具優先使用瀏覽器的 Web Serial API 直接與 MCU 通訊,無需伺服器端具備 serial 權限。
|
||
|
||
- **連線**:點擊 UI 上的「選擇連接埠並連線」,在瀏覽器彈出視窗中選擇正確的 MCU 裝置。
|
||
- **寫值**:點擊「寫值到 MCU」,系統會將目前定點數係數格式化為 `bodeplot=b0,b1,b2,a1,a2` 並送出。
|
||
- **限制**:需使用 Chrome 或 Edge 瀏覽器,且必須透過 HTTPS (或 localhost) 連線。
|
||
|
||
## 後端 MCU Serial 設定 (備用)
|
||
|
||
若無法使用 Web Serial,後端仍保留透過伺服器端實體連線寫入的 API。預設值在 `dea/config.py`,也可用環境變數覆蓋:
|
||
|
||
```bash
|
||
MCU_SERIAL_PORT=/dev/ttyUSB2
|
||
MCU_BAUD_RATE=115200
|
||
MCU_WRITE_TIMEOUT=1.0
|
||
```
|
||
|
||
若使用 systemd,可在 `dea.service` 的 `[Service]` 區塊加入:
|
||
|
||
```ini
|
||
Environment="MCU_SERIAL_PORT=/dev/ttyUSB2"
|
||
Environment="MCU_BAUD_RATE=115200"
|
||
Environment="MCU_WRITE_TIMEOUT=1.0"
|
||
```
|
||
|
||
## API
|
||
|
||
目前主要 API:
|
||
|
||
- `POST /api/design`:依濾波器參數產生 b/a 係數。
|
||
- `POST /api/bode`:計算單組 b/a 係數的頻率響應。
|
||
- `POST /api/bode/compare`:一次計算浮點與 fixed-point 兩組頻率響應。
|
||
- `POST /api/filter`:上傳 CSV 並回傳圖表用的濾波結果。
|
||
- `POST /api/filter/download`:上傳 CSV 並下載包含 `<欄位>_filtered` 的結果 CSV。
|
||
- `GET /api/mcu/ports`:列出伺服器端可用 serial ports (後端模式)。
|
||
- `POST /api/mcu/write`:送出伺服器端 MCU 命令 (後端模式)。
|
||
|
||
MCU 寫入命令格式固定為:
|
||
|
||
```text
|
||
bodeplot=b0,b1,b2,a1,a2
|
||
```
|
||
|
||
## a1/a2 微調 (δ/r 參數)
|
||
|
||
針對二階濾波器 (2P1Z/2P2Z),UI 提供了進階的步階微調功能:
|
||
|
||
- **δ (Delta)**:控制極點的頻率/阻尼平衡點。
|
||
- **r**:控制極點的半徑/頻寬。
|
||
- 公式:`a1 = -a0 - r + δ`,`a2 = r + δ` (定點數模式) 或 `a1 = -1 - r + δ`,`a2 = r + δ` (浮點數模式)。
|
||
- 支援透過 Shift + 滑鼠滾輪或觸控拖曳進行高精度微調。
|
||
|
||
## CSV 上傳
|
||
|
||
限制與行為:
|
||
|
||
- CSV 檔案大小上限為 32 MB。
|
||
- CSV 必須有標題列與至少一筆資料。
|
||
- 可選擇要濾波的訊號欄位;若第一欄像 `time`、`t`、`sec`、`x`、`index`,前端會預設選第二欄。
|
||
- 圖表回應最多回傳 5000 點,避免大型 CSV 讓前端過重。
|
||
- 下載 CSV 會保留完整資料,不套用圖表降採樣。
|
||
|
||
專案根目錄的 `chirp_signal.csv` 是上傳測試範例,約 19 MB、500001 行,欄位為:
|
||
|
||
```text
|
||
time,value
|
||
```
|
||
|
||
## 測試與檢查
|
||
|
||
Python 語法檢查:
|
||
|
||
```bash
|
||
.venv/bin/python -m py_compile dea_api.py tests/test_dea_api.py
|
||
```
|
||
|
||
後端測試使用 Python 內建 `unittest`,不需要安裝或執行 `pytest`:
|
||
|
||
```bash
|
||
.venv/bin/python -m unittest discover -s tests
|
||
```
|
||
|
||
前端建置檢查:
|
||
|
||
```bash
|
||
npm run build
|
||
```
|
||
|
||
建議完整驗證順序:
|
||
|
||
```bash
|
||
.venv/bin/pip install -r requirements.txt
|
||
.venv/bin/python -m unittest discover -s tests
|
||
npm run build
|
||
sudo systemctl restart dea.service
|
||
```
|
||
|
||
## 安全與限制
|
||
|
||
- API middleware 只允許 private / loopback IP 存取。
|
||
- 回應會加上 CSP、`Referrer-Policy`、`X-Content-Type-Options: nosniff`、`X-Frame-Options: DENY`。
|
||
- CSP 的 script 來源允許本機與 Plotly CDN。
|
||
- 係數數量上限為 64。
|
||
- CSV 上限為 32 MB。
|
||
- 頻率、係數、`a[0]` 與 CSV 訊號欄位都有後端驗證。
|
||
|
||
## 常見問題
|
||
|
||
### 為什麼無法連線連接埠?
|
||
1. 確認是否使用 HTTPS 連線。
|
||
2. 確認瀏覽器是否支援 Web Serial API (推薦使用 Chrome/Edge)。
|
||
3. 檢查 USB 傳輸線是否連接正確。
|
||
|
||
### 頁面沒有更新
|
||
1. 瀏覽器按 `Ctrl+F5` 強制重新整理。
|
||
2. 執行 `npm run build` 重新建置前端。
|
||
3. 執行 `sudo systemctl restart dea.service`。
|
||
|
||
### systemd 顯示 `status=203/EXEC`
|
||
通常是 `.venv` 或 `uvicorn` 路徑不正確。可重建 venv:
|
||
```bash
|
||
rm -rf .venv
|
||
python3 -m venv .venv
|
||
.venv/bin/pip install -r requirements.txt
|
||
sudo systemctl restart dea.service
|
||
```
|
||
|
||
### 找不到 pytest
|
||
本專案不使用 pytest。請改用:
|
||
```bash
|
||
.venv/bin/python -m unittest discover -s tests
|
||
```
|