驗證節點紀錄
本文件記錄已完成功能節點的實際驗證結果,用來確認「程式測試通過」以外,使用者也能理解目前功能實際跑起來的效果。
驗證摘要
| 項目 | 內容 |
|---|---|
| 驗證日期 | 2026-05-22 |
| 程式 repo | hs-device-control-template |
| 驗證 commit | 60e61b5 |
| 驗證環境 | Windows、.NET SDK 9.x 執行 .NET 5.0 專案 |
| 自動測試結果 | dotnet test 通過 49 個測試 |
| 注意事項 | .NET 5.0 已 EOL,因此執行時會出現 NETSDK1138 警告,屬於目前指定版本的預期現象 |
Config Loader
| 項目 | 內容 |
|---|---|
| 驗證節點 | Config Loader |
| 驗證目的 | 確認系統可以從指定資料夾載入 devices.json、workflows.json、appsettings.json,並在載入後交由 ConfigValidator 驗證 |
| 驗證方式 | 執行 dotnet test,檢查 ConfigLoaderTests |
| 實際結果 | 可成功載入 samples/config;資料夾不存在、缺少必要檔案、JSON 格式錯誤、載入後驗證失敗,都會回傳失敗結果與可讀錯誤 |
| 是否符合預期 | 符合 |
| 發現問題或限制 | 第一階段僅從檔案系統載入 JSON,尚未導入資料庫或遠端設定中心 |
| 建議下一步 | 保留目前 JSON 設定作為第一階段來源,後續若要支援多案場或雲端管理,再討論設定來源抽象化 |
Config Mapper
| 項目 | 內容 |
|---|---|
| 驗證節點 | Config Mapper |
| 驗證目的 | 確認 WorkflowConfiguration 可以轉成 WorkflowEngine 可執行的 WorkflowDefinition |
| 驗證方式 | 執行 dotnet test,檢查 WorkflowConfigurationMapperTests 與流程模擬測試 |
| 實際結果 | 可將 sample workflow 轉成可執行定義,並由 WorkflowEngine 完成燈號導引 + Sensor 驗證代表流程 |
| 是否符合預期 | 符合 |
| 發現問題或限制 | DeviceId 已帶入 WorkflowNode 與 Log,但目前仍是單一 Mock Adapter,尚未依 DeviceId 分派到不同 Adapter 實例 |
| 建議下一步 | 評估是否建立 Adapter 分派器,讓未來可依 DeviceId 選擇對應設備 Adapter |
ConsoleHost 設定檔啟動
| 項目 | 內容 |
|---|---|
| 驗證節點 | ConsoleHost 設定檔啟動 |
| 驗證目的 | 確認 ConsoleHost 可以用設定檔啟動代表流程,而不是寫死程式內流程 |
| 驗證方式 | 執行 dotnet run --project src\HS.DeviceControl.ConsoleHost -- samples\config LIGHT_SENSOR_DEMO |
| 實際結果 | ConsoleHost 顯示 Loading config from: samples\config,接著依序完成 light-on 與 sensor-verify,Log 可看到 deviceId="LED_001" 與 deviceId="SENSOR_001",最後輸出 Workflow completed. |
| 是否符合預期 | 符合 |
| 發現問題或限制 | 目前仍使用 Mock Adapter,不接真實硬體;ConsoleHost 適合第一階段 Debug,不是正式背景服務入口 |
| 建議下一步 | 進入設備離線、逾時與重試驗證案例,確認失敗路徑也能保留 DeviceId 與錯誤資訊 |
ConsoleHost 實際輸出摘要
Loading config from: samples\config
2026-05-22T00:26:20.6077037+08:00 level="INFO" taskId="demo-task" nodeId="light-on" nodeName="開啟燈號" deviceId="LED_001" command="LightOn" status="completed" retryCount=0 timeTakenMs=0 errorCode="NONE" message="Mock command 'LightOn' completed."
2026-05-22T00:26:20.6188458+08:00 level="INFO" taskId="demo-task" nodeId="sensor-verify" nodeName="Sensor 驗證" deviceId="SENSOR_001" command="SensorVerify" status="completed" retryCount=0 timeTakenMs=0 errorCode="NONE" message="Mock command 'SensorVerify' completed."
Workflow completed.
節點失敗與重試驗證
| 項目 | 內容 |
|---|---|
| 驗證節點 | 節點失敗、逾時與重試 |
| 驗證目的 | 確認 WorkflowEngine 可處理設備離線、節點逾時、重試後成功、重試耗盡失敗 |
| 驗證方式 | 執行 dotnet test,檢查 LightSensorWorkflowTests 中的失敗與重試案例 |
| 實際結果 | 設備離線會回傳 DEV-0002;節點逾時會回傳 WF-0004;RetryCount=1 時會最多執行 2 次;重試成功會完成節點,重試耗盡會失敗 |
| 是否符合預期 | 符合 |
| 發現問題或限制 | 目前逾時判斷是在同步命令返回後計算耗時,尚未做到執行中取消命令 |
| 建議下一步 | 評估 Adapter 分派器或 TaskEngine,決定是否需要更完整的取消、暫停與背景執行模型 |
Adapter 分派器
| 項目 | 內容 |
|---|---|
| 驗證節點 | Adapter Dispatcher |
| 驗證目的 | 確認 ConsoleHost 可依 DeviceId 將命令分派到不同設備 Adapter,避免所有命令共用單一 Mock Adapter |
| 驗證方式 | 執行 dotnet test,檢查 DeviceAdapterDispatcherTests;再執行 dotnet run --project src\HS.DeviceControl.ConsoleHost -- samples\config LIGHT_SENSOR_DEMO |
| 實際結果 | DeviceAdapterDispatcher 可依 LED_001、SENSOR_001 選擇不同 Adapter;未知 DeviceId 會回傳 DEV-0003;ConsoleHost 代表流程仍可完成 |
| 是否符合預期 | 符合 |
| 發現問題或限制 | 目前 Dispatcher 只負責 Execute 分派,尚未管理 Connect、Disconnect、GetStatus 等設備生命週期 |
| 建議下一步 | 規劃 TaskEngine,或先補 Adapter 生命週期介面,讓真實設備接入時能管理連線狀態 |
TaskEngine 最小版本
| 項目 | 內容 |
|---|---|
| 驗證節點 | TaskEngine |
| 驗證目的 | 確認 TaskEngine 可將 Workflow 包裝成 TaskExecutionRecord 任務紀錄,並追蹤 TaskId、WorkflowId、狀態、開始時間、結束時間、耗時與執行結果 |
| 驗證方式 | 執行 dotnet test,檢查 TaskEngineTests;再執行 dotnet run --project src\HS.DeviceControl.ConsoleHost -- samples\config LIGHT_SENSOR_DEMO 確認既有 ConsoleHost 啟動方式不受影響 |
| 實際結果 | 成功 Workflow 會產生 Completed 任務紀錄;失敗 Workflow 會產生 Failed 任務紀錄並保留錯誤;空白 TaskId 會自動產生識別碼 |
| 是否符合預期 | 符合 |
| 發現問題或限制 | 目前 TaskEngine 是同步執行包裝,尚未支援背景排程、暫停、取消或任務儲存 |
| 建議下一步 | 決定下一階段要先補 Adapter 連線生命週期,或讓 TaskEngine 支援取消與背景執行 |
Adapter 生命週期
| 項目 | 內容 |
|---|---|
| 驗證節點 | Adapter Connect / Disconnect / GetStatus |
| 驗證目的 | 確認 IDeviceAdapter 具備最小連線生命週期,並透過 DeviceConnectionStatus 讓 Mock Adapter 表達 Disconnected、Connected 狀態,且未連線時命令會回傳 DEV-0002 |
| 驗證方式 | 執行 dotnet test,檢查 MockDeviceAdapterTests 與 DeviceAdapterDispatcherTests;再執行 dotnet run --project src\HS.DeviceControl.ConsoleHost -- samples\config LIGHT_SENSOR_DEMO |
| 實際結果 | Connect() 會讓 Mock Adapter 進入 Connected;Disconnect() 會回到 Disconnected;Dispatcher 可一次連線或斷線所有註冊 Adapter;ConsoleHost 啟動時會先連線再執行代表流程 |
| 是否符合預期 | 符合 |
| 發現問題或限制 | 目前狀態仍是記憶體內 Mock 狀態,尚未對應真實 PLC、IO、Serial、TCP 或 Modbus 連線細節 |
| 建議下一步 | 討論真實設備 Adapter 的設定欄位、連線失敗重試策略與狀態查詢格式 |
開發狀態自動同步
| 項目 | 內容 |
|---|---|
| 驗證節點 | 開發狀態自動同步 |
| 驗證目的 | 確認程式 repo push 後,能透過 GitHub Actions 通知文件 repo,並自動更新 status.json、public/status.json 與 Cloudflare Pages 首頁開發狀態。 |
| 驗證方式 | 在程式 repo poc/nmodbus-tcp 分支建立測試 commit 3c05cf5,觸發 notify-docs workflow;確認文件 repo 自動產生 commit 1e1fd11,再檢查公開 status.json。 |
| 實際結果 | 文件 repo 已自動產生 1e1fd11 同步程式 repo 開發狀態;公開 status.json 顯示 shortCommit=3c05cf5、branch=poc/nmodbus-tcp、source=github-actions。 |
| 是否符合預期 | 符合 |
| 發現問題或限制 | PowerShell 終端直接顯示公開 JSON 時,中文可能因終端編碼顯示成亂碼;使用 UTF-8 JSON parser 檢查時,commitMessage、stage、nextStep 均為正確中文。 |
| 建議下一步 | 後續每次程式 repo push 後,以首頁與 status.json 確認開發狀態是否更新;若未更新,優先檢查程式 repo notify-docs workflow 與文件 repo apply-code-status workflow。 |
整體判斷
| 項目 | 判斷 |
|---|---|
| Config Loader | 可作為第一階段設定入口 |
| Config Mapper | 可把設定檔流程轉成可執行流程,並保留 DeviceId |
| ConsoleHost | 可作為第一階段代表流程驗證入口 |
| Adapter 分派器 | 可依 DeviceId 分派到不同設備 Adapter |
| TaskEngine | 可追蹤單次 Workflow 任務執行紀錄 |
| Adapter 生命週期 | 可管理 Mock Adapter 連線、斷線與狀態查詢 |
| Log 呈現 | 已可看到 TaskId、NodeId、NodeName、DeviceId、Command、Status、RetryCount、TimeTakenMs、ErrorCode、Message |
| 是否可進下一步 | 可以 |
下一步建議
- 討論真實設備 Adapter 的設定欄位與連線失敗處理。
- 評估 TaskEngine 是否需要支援暫停、取消與背景執行。
- 討論同步 Timeout 是否足夠,或後續需要支援可取消的非同步命令。
ConsoleHost Schema Dry Run 顯示人工驗證
| 項目 | 內容 |
|---|---|
| 驗證節點 | ConsoleHost Schema Dry Run 顯示人工驗證 |
| 驗證目的 | 確認 ConsoleHost 可清楚顯示 Dry Run 摘要、SQL preview 與安全警告 |
| 驗證方式 | dotnet run --project src\HS.DeviceControl.ConsoleHost |
| 實際結果 | Workflow 正常完成,並顯示 Schema dry run:、CREATE TABLE IF NOT EXISTS task_executions 與 Dry Run 不會連線或修改 MySQL |
| 是否符合預期 | 符合預期 |
| 詳細紀錄 | consolehost-schema-dry-run-display-verification-record.md |
| 建議下一步 | 進入 Schema Initializer DryRun 流程設計 |