---
date: 2025-11-05T13:21:41+08:00
researcher: Claude (Sonnet 4.5)
git_commit: 6b56270e6be04a65c3caf94aa873f0c742ff2a1c
branch: main
repository: FWAauto
topic: "AM62x 環境下 log_node 遠端日誌存取研究"
tags: [research, log-node, am62x, remote-access, uart, vm]
status: complete
last_updated: 2025-11-05
last_updated_by: Claude (Sonnet 4.5)
---

# Research: AM62x 環境下 log_node 遠端日誌存取研究

**Date**: 2025-11-05T13:21:41+08:00
**Researcher**: Claude (Sonnet 4.5)
**Git Commit**: 6b56270e6be04a65c3caf94aa873f0c742ff2a1c
**Branch**: main
**Repository**: FWAauto

## Research Question

在 AM62x 開發環境下，FWAuto 在 VM 中執行，而韌體日誌透過 UART 輸出到開發機（Arch Linux）。如何讓 VM 中的 log_node 能夠存取開發機上的 UART 日誌？

## Summary

本研究深入分析了 FWAuto 的 log_node 在 AM62x 環境下的日誌存取挑戰，並探索了可行的解決方向。

### 核心發現

1. **當前 log_node 設計**：完全基於本地檔案系統，使用 `os.path.exists()` 驗證，無遠端存取能力
2. **AM62x 架構**：三層架構（開發機 → VM → 開發板），日誌流向為 開發板 UART → 開發機 /dev/ttyACM0
3. **既有基礎設施**：flash.sh 已實現完整的 SSH/SCP 遠端執行機制，可作為擴展基礎
4. **技術方案**：推薦使用 SSH/SCP 方案，符合 KISS 原則且已在生產環境驗證

### 主要結論

- **可行性**：✅ 技術上完全可行，無需引入新依賴
- **複雜度**：⭐⭐ 中等，需要擴展現有 log_node 和配置系統
- **優先級**：⭐⭐⭐ 高，影響 AM62x 開發流程效率
- **時程估計**：1-2 週（含測試）

## Detailed Findings

### 1. log_node 當前實現

#### 日誌路徑處理機制

**檔案位置**：`src/fwauto/nodes/log.py:50-61`

```mermaid
graph LR
    A["輸入路徑"] --> B{"是絕對路徑?"}
    B -->|否| C["轉換為絕對路徑<br/>os.path.join(cwd, path)"]
    B -->|是| D["使用原路徑"]
    C --> E["驗證檔案存在<br/>os.path.exists()"]
    D --> E
    E -->|失敗| F["返回錯誤"]
    E -->|成功| G["提取目錄<br/>os.path.dirname()"]
    G --> H["設定 Claude SDK<br/>add_dirs=[log_dir]"]
```

**關鍵限制**：
- 使用 `os.path.exists()` 只適用本地檔案系統
- `add_dirs` 參數要求目錄在本地可存取
- 無任何遠端協議處理（SSH、SFTP、HTTP）

#### Claude SDK 配置

**檔案位置**：`src/fwauto/nodes/log.py:86-108`

| 配置項 | 值 | 用途 |
|--------|-----|------|
| `allowed_tools` | `["Read", "Grep"]` | 限制為只讀操作 |
| `permission_mode` | `"bypassPermissions"` | 自動化工作流無需互動 |
| `add_dirs` | `[log_dir]` | 限制存取範圍（安全邊界） |
| `system_prompt` | SDK 模式提示 | 強制直接執行，不詢問 |

**設計特點**：
- ✅ 安全性佳（只讀 + 目錄限制）
- ✅ 自動化友好（無互動）
- ❌ 無遠端存取支援

### 2. AM62x 環境架構

#### 三層架構圖

```mermaid
graph TB
    subgraph DEV["開發機 (Arch Linux)"]
        UART["UART 連接<br/>/dev/ttyACM0/1"]
        FWAUTO_DEV["FWAuto?<br/>(可選安裝)"]
        CODE_DEV["程式碼?<br/>(可選)"]
    end

    subgraph VM["VM (VirtualBox)"]
        FWAUTO_VM["FWAuto ✓<br/>(已安裝)"]
        CODE_VM["程式碼 ✓<br/>(git clone)"]
        SDK["TI AM62x SDK"]
        BUILD["編譯工具"]
    end

    subgraph BOARD["開發板 (AM62X)"]
        APP["應用程式"]
        LOG["日誌輸出"]
    end

    DEV -->|SSH<br/>192.168.50.163| VM
    VM -->|SCP<br/>192.168.50.170| BOARD
    BOARD -->|UART| DEV

    style DEV fill:#e1f5ff
    style VM fill:#fff3e0
    style BOARD fill:#f3e5f5
```

#### 網路配置

| 節點 | IP 位址 | 連接方式 | 用途 |
|------|---------|---------|------|
| 開發機 | 192.168.50.x (Host) | UART 連接開發板 | 日誌接收、開發控制 |
| VM | 192.168.50.163 | SSH 連線開發機/開發板 | FWAuto 執行、編譯 |
| 開發板 | 192.168.50.170 | UART 輸出到開發機 | 韌體執行、日誌產生 |

#### 日誌流向

```mermaid
sequenceDiagram
    participant Board as 開發板
    participant UART as UART 硬體
    participant Dev as 開發機<br/>/dev/ttyACM0
    participant VM as VM<br/>FWAuto
    participant Log as log_node

    Board->>UART: stdout/stderr 輸出
    UART->>Dev: UART 傳輸
    Note over Dev: 使用者需手動收集<br/>或使用 serial monitor
    Dev->>Dev: 保存到檔案<br/>logs/uart.log
    Note over VM,Log: 問題：VM 如何存取？
    VM->>Dev: ❓ 需要遠端存取機制
    VM->>Log: fwauto log "分析"
    Log->>Dev: ❌ os.path.exists() 失敗
```

### 3. 既有 SSH/SCP 基礎設施

#### flash.sh 遠端執行機制

**檔案位置**：`src/fwauto/templates/sdk_am62x_linux/flash/flash.sh`

**完整流程**：

```mermaid
graph TD
    A[flash.sh 開始] --> B[find_binary<br/>尋找編譯產物]
    B --> C[deploy_binary<br/>SCP 上傳到開發板]
    C --> D[execute_on_board<br/>SSH 執行程式]
    D --> E{執行成功?}
    E -->|是| F[顯示 stdout]
    E -->|否| G[顯示錯誤]
    F --> H[結束]
    G --> H

    style A fill:#90EE90
    style E fill:#FFD700
    style H fill:#FFB6C1
```

**SSH 配置範例**：

```bash
BOARD_IP="192.168.50.170"
BOARD_USER="root"
SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"

# 部署
scp ${SSH_OPTS} "$binary_path" ${BOARD_USER}@${BOARD_IP}:/home/root/

# 執行（stdout 直接顯示）
ssh ${SSH_OPTS} ${BOARD_USER}@${BOARD_IP} "cd /home/root && ./$binary_name"
```

**關鍵優勢**：
- ✅ 已在生產環境驗證
- ✅ 零新依賴（使用系統 ssh/scp）
- ✅ 符合 KISS 原則
- ✅ stdout 自動回傳到 VM

### 4. 日誌配置系統現況

#### User Config 結構

**檔案位置**：`src/fwauto/user_config.py`

**現有 API**：

| 函數 | 用途 | 回傳值 |
|------|------|--------|
| `get_sdk_config(sdk_id)` | 取得 SDK 配置 | `dict \| None` |
| `set_sdk_config(sdk_id, config)` | 設定 SDK 配置 | `None` |
| `get_device_config(device_id)` | 取得裝置配置 | `dict \| None` |
| `set_device_config(device_id, config)` | 設定裝置配置 | `None` |

**缺少的配置**：
- ❌ 無 UART 配置 API
- ❌ 無遠端日誌路徑配置
- ❌ 無 SSH 連線資訊配置

#### Project Config 結構

**檔案位置**：`src/fwauto/config.py`

**現有欄位**：

```toml
[project]
name = "MyProject"

[build]
makefile = ".fwauto/build/Makefile"

[flash]
makefile = ".fwauto/flash/Makefile"

[sdk]
type = "am62x"
path = "/path/to/sdk"

[device]
family = "AM62x"
model = "AM6254"
```

**缺少的配置**：
- ❌ 無 `[log]` section
- ❌ 無 `log_path` 欄位
- ❌ 無 `uart_port` 欄位
- ❌ 無 `remote_host` 欄位

### 5. 技術方案分析

#### 方案對比表

| 方案 | 複雜度 | 可行性 | KISS 原則 | 建議 |
|------|--------|--------|----------|------|
| **SSH/SCP** | ⭐⭐ 中 | ⭐⭐⭐⭐⭐ 極高 | ⭐⭐⭐⭐⭐ 完全符合 | ✅ **推薦** |
| VirtualBox 共享資料夾 | ⭐ 低 | ⭐⭐ 低 | ⭐⭐⭐ 一般 | ❌ 不推薦 |
| NFS/SSHFS | ⭐⭐⭐ 高 | ⭐⭐⭐ 中 | ⭐⭐ 複雜 | ❌ 不推薦 |
| Paramiko (Python SSH) | ⭐⭐⭐ 高 | ⭐⭐⭐⭐ 高 | ⭐⭐ 新依賴 | ❌ 不推薦 |

#### 推薦方案：SSH/SCP

**實施流程**：

```mermaid
graph LR
    A["使用者執行<br/>fwauto log 問題"] --> B["log_node 檢查<br/>log_file_path"]
    B --> C{"本地檔案?"}
    C -->|是| D["直接使用<br/>當前邏輯"]
    C -->|否| E["檢測遠端格式<br/>user@host:path"]
    E --> F["SCP 下載<br/>到暫存目錄"]
    F --> G["更新 log_file_path<br/>為本地路徑"]
    G --> H["執行 AI 分析<br/>Claude SDK"]
    H --> I["清理暫存檔案"]
    I --> J["返回結果"]
    D --> H
```

**範例配置**：

```toml
# .fwauto/config.toml
[log]
# 本地檔案
path = "logs/uart.log"

# 或遠端檔案
remote_host = "192.168.50.1"  # 開發機
remote_user = "kent"
remote_path = "/home/kent/uart.log"
```

**範例使用**：

```bash
# 本地檔案（現有功能）
fwauto log "有錯誤嗎?" --log-path logs/uart.log

# 遠端檔案（擴展功能）
fwauto log "有錯誤嗎?" --log-path kent@192.168.50.1:/home/kent/uart.log
```

## Code References

| 檔案路徑 | 行號 | 說明 |
|---------|------|------|
| `src/fwauto/nodes/log.py` | 20-125 | log_node 主要實現 |
| `src/fwauto/nodes/log.py` | 50-61 | 路徑處理和驗證邏輯 |
| `src/fwauto/nodes/log.py` | 86-108 | Claude SDK 配置 |
| `src/fwauto/cli.py` | 176-222 | log 命令 CLI 介面 |
| `src/fwauto/state.py` | 62-64 | log 相關狀態欄位 |
| `src/fwauto/config.py` | 全部 | ProjectConfig 實現 |
| `src/fwauto/user_config.py` | 全部 | UserConfig 實現 |
| `src/fwauto/templates/sdk_am62x_linux/flash/flash.sh` | 全部 | SSH/SCP 遠端執行範例 |
| `docs/am62x.md` | 1-31 | AM62x 環境架構圖 |
| `prompts/log.md` | 全部 | 日誌分析 AI prompt 模板 |
| `tests/test_story_004_log_analysis_node.py` | 全部 | log_node 單元測試 |

## Architecture Insights

### 現有設計模式

**log_node 採用的設計模式**：

1. **純函數節點** (Pure Function Node)
   - 輸入：`FirmwareState`
   - 輸出：`dict`（部分狀態更新）
   - 無副作用（除了日誌記錄）

2. **早期失敗** (Fail-Fast)
   - 路徑驗證失敗立即返回
   - 避免不必要的 SDK 呼叫

3. **職責分離** (Separation of Concerns)
   - log_node：日誌分析
   - ai_brain_node：程式碼修復
   - 不同工具權限（Read/Grep vs Read/Write/Edit）

4. **安全邊界** (Security Boundary)
   - `add_dirs` 限制存取範圍
   - `allowed_tools` 限制工具集
   - `permission_mode` 自動化控制

### 可擴展方向

**架構圖**：

```mermaid
graph TB
    subgraph Current["當前架構"]
        A1["CLI: fwauto log"] --> B1["log_node"]
        B1 --> C1["Local File System"]
        C1 --> D1["Claude SDK<br/>Read/Grep"]
    end

    subgraph Extended["擴展架構"]
        A2["CLI: fwauto log"] --> B2["log_node_v2"]
        B2 --> C2{"檔案來源?"}
        C2 -->|本地| D2["Direct Read"]
        C2 -->|遠端| E2["SSH/SCP Fetcher"]
        E2 --> F2["Temp File"]
        F2 --> D2
        D2 --> G2["Claude SDK<br/>Read/Grep"]
    end

    style Current fill:#ffe4e1
    style Extended fill:#e8f5e9
```

**擴展點**：

1. **路徑解析器** (Path Parser)
   - 偵測 `user@host:path` 格式
   - 支援 SCP/SFTP/HTTP 協議

2. **檔案獲取器** (File Fetcher)
   - 實現 `fetch_remote_file(remote_path) -> local_path`
   - 自動清理暫存檔案

3. **配置整合** (Config Integration)
   - UserConfig 新增 `get_remote_config()`
   - ProjectConfig 新增 `[log]` section

### 相容性考量

**向後相容性**：
- ✅ 現有本地檔案路徑繼續運作
- ✅ 遠端路徑作為額外功能
- ✅ 無需修改 FirmwareState 結構
- ✅ Claude SDK 配置保持不變

**測試策略**：
- 單元測試：Mock SSH/SCP 呼叫
- 整合測試：使用真實 SSH 連線
- 回歸測試：確保本地路徑功能正常

## Historical Context (from .ai/prpi)

**相關研究文件**：

- `.ai/prpi/research/2025-11-03-fwauto-ssh-remote-execution-feasibility.md`
  - SSH/SCP 遠端執行可行性分析
  - Flash 階段的 SSH 整合經驗
  - 技術債務和限制說明

- `.ai/prpi/plans/2025-11-03-fwauto-vm-ssh-integration.md`
  - Phase 1: VM 中心架構（67% 完成）
  - Phase 2: 開發機控制架構（設計完成）
  - 12 項實施步驟詳細規劃

- `.ai/prpi/problems/2025-11-03-fwauto-vm-dev-machine-control-dilemma.md`
  - VM vs 開發機的控制權衡
  - 蘇格拉底式問題診斷
  - 根本問題分析

**關鍵洞察**：
- Flash 階段已成功實現 SSH/SCP 遠端執行
- 證明了 subprocess + ssh 方案的可行性
- 無需引入 Paramiko 等新依賴
- 符合 KISS 原則

## Related Research

**內部研究**：
- `.ai/prpi/research/2025-11-05-am62x-log-node-remote-access.md` (本文件)

**外部參考**：
- [SSH Config Best Practices](https://www.ssh.com/academy/ssh/config)
- [Python subprocess with SSH](https://docs.python.org/3/library/subprocess.html)
- [LangGraph State Management](https://docs.langchain.com/oss/python/langgraph/overview)

## Open Questions

### 技術問題

1. **UART 自動偵測**
   - Q: 如何自動偵測 /dev/ttyACM0 vs /dev/ttyACM1？
   - 方向：使用 `pyserial` 的 `list_ports` 功能

2. **日誌格式標準化**
   - Q: 是否需要定義統一的日誌格式？
   - 方向：考慮使用 JSON structured logs

3. **即時日誌串流**
   - Q: 是否需要支援即時日誌分析（而非檔案）？
   - 方向：可以使用 `ssh -t` 即時串流

### 架構問題

4. **多環境支援**
   - Q: STM32 環境是否需要相同的遠端日誌功能？
   - 方向：設計通用的遠端檔案存取介面

5. **日誌 → AI → Build 閉環**
   - Q: log_node 是否應該觸發 ai_brain 修復？
   - 方向：新增 `route_after_log()` 函數

6. **暫存檔案管理**
   - Q: 下載的遠端日誌應該保留多久？
   - 方向：使用 `tempfile` 模組自動清理

### 使用者體驗問題

7. **SSH 金鑰管理**
   - Q: 如何簡化 SSH 無密碼登入設定？
   - 方向：提供 `fwauto init-ssh` 設定助手

8. **錯誤訊息改善**
   - Q: 遠端存取失敗時如何提供清楚的錯誤訊息？
   - 方向：區分網路錯誤、權限錯誤、路徑錯誤

9. **配置簡化**
   - Q: 是否可以自動偵測開發機 IP？
   - 方向：使用 `ip route` 或 VirtualBox API

### 測試問題

10. **整合測試環境**
    - Q: 如何在 CI/CD 中測試 SSH 功能？
    - 方向：使用 Docker 建立模擬 SSH 環境

## 後續建議

### 實施優先級

**P0 (立即)**：
- 閱讀並討論本研究報告
- 確認技術方向和需求

**P1 (本週)**：
- 執行 `/prpi:plan` 建立詳細實施計劃
- 設計 API 和配置結構

**P2 (下週)**：
- 實作遠端檔案存取功能
- 擴展 log_node 支援遠端路徑

**P3 (兩週後)**：
- 整合測試和文檔
- 使用者驗收測試

### 成功標準

- ✅ `fwauto log "問題" --log-path user@host:path` 運作正常
- ✅ 本地路徑功能保持不變（向後相容）
- ✅ 測試覆蓋率 > 80%
- ✅ 文檔完整且清晰
