# 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 組合、Q 格式位元數與 fixed-point 整數係數。 - 上傳 CSV 時域資料,套用目前差分方程並繪製輸入/輸出波形。 - 匯出包含濾波輸出欄位的 CSV。 - 透過 USB serial 將 fixed-point 係數命令送到 MCU。 ## 專案結構 ```text dea_api.py FastAPI 入口與 HTTP route dea/ 後端核心模組 bode.py 頻率響應計算 config.py 限制值與 MCU 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 前端原始碼 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 ``` 建置前端: ```bash npm run build ``` Vite 會輸出到: ```text static/build/app.js static/build/app.css ``` ## 執行 本機開發可直接啟動 FastAPI: ```bash .venv/bin/uvicorn dea_api:app --host 127.0.0.1 --port 8000 ``` 瀏覽器開啟: ```text http://localhost:8000/ui/ ``` 部署在區網主機時可用: ```text http://:8000/ui/ ``` 根路徑 `/` 會自動導向 `/ui/`。 ## 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 ``` 前端會使用目前 fixed-point 係數自動組出此命令。 ## CSV 上傳 限制與行為: - CSV 檔案大小上限為 32 MB。 - CSV 必須有標題列與至少一筆資料。 - 可選擇要濾波的訊號欄位;若第一欄像 `time`、`t`、`sec`、`x`、`index`,前端會預設選第二欄。 - 圖表回應最多回傳 5000 點,避免大型 CSV 讓前端過重。 - 下載 CSV 會保留完整資料,不套用圖表降採樣。 專案根目錄的 `chirp_signal.csv` 是上傳測試範例,約 19 MB、500001 行,欄位為: ```text time,value ``` ## MCU Serial 設定 MCU serial 預設值在 `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" ``` 更新 service 後重新載入: ```bash sudo systemctl daemon-reload sudo systemctl restart dea.service ``` 注意:MCU 功能需要 `pyserial>=3.5`,已列在 `requirements.txt`。 ## systemd 查看服務狀態: ```bash sudo systemctl status dea.service ``` 啟動、停止、重啟: ```bash sudo systemctl start dea.service sudo systemctl stop dea.service sudo systemctl restart dea.service ``` 查看 log: ```bash sudo journalctl -u dea.service -f ``` 若修改 `/etc/systemd/system/dea.service`: ```bash sudo systemctl daemon-reload sudo systemctl restart dea.service ``` ## 測試與檢查 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: ```text 'self' https://cdn.plot.ly ``` - 係數數量上限為 64。 - CSV 上限為 32 MB。 - 頻率、係數、`a[0]` 與 CSV 訊號欄位都有後端驗證。 ## 常見問題 ### 頁面沒有更新 1. 瀏覽器按 `Ctrl+F5` 強制重新整理。 2. 確認前端 build 檔存在: ```bash ls static/build/app.js static/build/app.css ``` 3. 重新 build 並重啟服務: ```bash npm run build 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 ``` ### MCU COM Port清單是空的 1. 確認 USB 裝置已插入。 2. 確認執行服務的使用者有 serial port 權限。 3. 檢查預設 port: ```bash echo $MCU_SERIAL_PORT ``` 4. 可在頁面按「更新」重新讀取 serial ports。