專案

一般

配置概況

動作

Feature #1381

進行中

[BE] Branch Engineer Command API 與 OCPP/Modbus 控制

是由 陳國瑋20 天 前加入. 於 18 天 前更新.

狀態:
Resolved
優先權:
Normal
被分派者:
開始日期:
2026-07-14
完成日期:
完成百分比:

100%

預估工時:

概述

背景

Branch Admin 需要提供 Engineer Role 專用 Backend API,讓工程師對指定 Charge Point / Connector 發送受控 Modbus command 與完整 OCPP 1.6 CSMS command。主要使用情境為 Fortune(華城)充電樁測試。

完整需求與實作規劃請見附件 branch-admin-engineer-command-plan.md

Backend Scope

  1. 新增 engineer Role,並將既有 ADMINpower_user 帳號加入該 Role。
  2. 建立 Engineer command catalog、capability 判定及後端 payload validation。
  3. 建立 OCPP Engineer Command API,涵蓋全部 19 個 OCPP 1.6 CSMS -> Charge Point commands。
  4. HTTP request 內完成 command log 建立與 WebSocket dispatch;成功後回 HTTP 202 + SENT,不等待 CALLRESULT/CALLERROR。
  5. 以 OCPP uniqueId 非同步關聯 CALLRESULT/CALLERROR;補上 Diagnostics/Firmware status timeline。
  6. 建立 e_engineer_command_log、event timeline 與 capability persistence,保留 365 天。
  7. 建立 CloudLink 受控 Modbus command path,只允許 Plan 內 12 個 operation。
  8. SET_SUPPLY_STATE 必須刻意使用既有 controlTestMode(..., 1/0)
  9. 維持既有 8 個 /api/ocpp API 與 /api/fev/connector/availability contract 相容。
  10. 補齊 OpenAPI、unit/integration tests、migration 及 AI/技術文件。

協作票

FE UI:#1380,由前端依同一份 Plan 實作 React Branch Admin「工程師工具」頁面。


檔案

branch-admin-engineer-command-plan.md (26.9 KB) branch-admin-engineer-command-plan.md Branch Admin Engineer Command Center implementation plan 陳國瑋, 2026-07-14 05:37

是由 陳國瑋20 天 前更新

  • 狀態New 變更為 In Progress
  • 被分派者 設定為 陳國瑋

需求與 implementation plan 已由 Ken 確認,開始 Backend 實作。協作 FE ticket:#1380。

是由 陳國瑋20 天 前更新

Backend implementation 已完成並推送 feature branch:feature/redmine-1381-engineer-command-backend

Commits:

  • EMS root 16730ac feat(#1381): 實作工程師 OCPP 與稽核 API
  • EMS root 6c636af docs: 更新 Redmine Agent 自行實作規範
  • charge_point ffe8754 feat(#1381): 新增受控 Modbus 工程師指令

完成項目:

  1. Engineer Role、SS3A function/API mappings,明確授權 ADMIN 與 power_user member。
  2. Engineer catalog / OCPP dispatch / controlled Modbus dispatch / search / detail API。
  3. 全部 19 個 OCPP 1.6 CSMS→CP command 與官方 request schema validation。
  4. CALLRESULT/CALLERROR generic observer、GetDiagnostics/UpdateFirmware status timeline。
  5. e_engineer_command_log、e_engineer_command_event、e_ocpp_command_capability migration 與 365 天 retention。
  6. CloudLink charge_point 12 個具名 Modbus operation 雙層 allowlist;SET_SUPPLY_STATE 刻意使用 controlTestMode()。
  7. 舊 generic DataTransfer 禁止 EngineerModbusCommand,避免繞過 Engineer authorization。
  8. AI 文件、FE handoff 與 Obsidian 知識已同步。

測試:

  • Engineer Branch targeted tests:全部通過(19 actions、schema、async observer、send failure audit、DataTransfer authorization bypass)。
  • charge_point targeted tests:全部通過(allowlist、controlTestMode 且不呼叫 controlRelay)。
  • ems_branch full suite:101 tests,100 passed;唯一既有失敗為 BillHistoricalTariffE2ETest 缺少 2025-05 測試資料,與 #1381 無關。
  • charge_point full suite 仍有既有 test profile placeholder ocpp.client.charge-point-id 無法解析;本次 targeted test 與 compile 通過。

下一個 gate:請 Ken 部署兩個 feature branch 並套用 patch_20260714_redmine_1381_engineer_command.sql,之後執行 Fortune 19 OCPP commands 與 CloudLink 12 Modbus operations 實機 E2E。Issue 暫不 resolve。

是由 陳國瑋20 天 前更新

依 Ken code review 意見補齊詳盡程式碼註解並推送:

  • EMS 083490c docs(#1381): 補充工程師指令程式註解
  • charge_point d51f26b docs(#1381): 說明受控 Modbus 安全與硬體限制

補充範圍:

  1. Engineer Command 同步 dispatch/非同步 completion 契約。
  2. audit 狀態機、append-only event timeline 與快速回應競態。
  3. 固定 catalog、schema/capability 差異與雙層 allowlist 安全邊界。
  4. SS3A Engineer Role 不繼承 administrator/power_user 的原因。
  5. Firmware/Diagnostics status notification 配對限制。
  6. 原始與 masked payload 的使用界線。
  7. charge_point 的穩定錯誤格式、correlation tracing,以及 SET_SUPPLY_STATE 必須使用 controlTestMode() 的硬體原因。
  8. migration 重要欄位與 member-level role mapping 說明。

註解規範已加入 REDMINE_CODING_SOP、ai/README 及 Obsidian EMS inbox,後續實作會固定檢查。

驗證:ems_branch compile + Engineer targeted tests 通過;charge_point Engineer Modbus targeted tests 通過。

是由 陳國瑋20 天 前更新

依 Ken 指示已整理 feature branch commit history,並以 force-with-lease 更新遠端:

  • EMS #1381 commits 已 squash 為:16a8702 feat(#1381): 實作工程師 OCPP 與稽核 API
  • charge_point #1381 commits 已 squash 為:ad6d988 feat(#1381): 新增受控 Modbus 工程師指令

EMS 中與 #1381 無關的 Update commit(settings / AGENTS / CLAUDE / deployment 文件)保留為獨立 commit 617b50e,未併入 #1381

已用 tree diff 確認 squash 前後檔案內容完全一致;charge_point 尚未提交的 ConnectorType.java 修改仍保留且未納入 commit。

是由 陳國瑋20 天 前更新

依 Ken 第二次 code review 意見,註解標準已提升並完成全範圍補充:

  1. Engineer API 的每個 DTO record component 均加入 OpenAPI @Schema(description=...) 欄位說明。
  2. 本次新增的 public/private helper、JPA lifecycle/getter、repository contract、OCPP handler、scheduler 與 test method 均補上 method-level 用途註解。
  3. 跨服務 dispatch、狀態機、payload masking、status 配對、雙層 allowlist 與 controlTestMode 硬體限制保留更完整的設計理由。
  4. REDMINE_CODING_SOP、ai/README 與 Obsidian EMS inbox 已明定「每個 method、每個 DTO 欄位都要有註解」。

依前次要求未增加零碎 commit,直接 amend 單一 #1381 commit 並 force-with-lease 更新:

  • EMS:cc559f0 feat(#1381): 實作工程師 OCPP 與稽核 API
  • charge_point:c62a53d feat(#1381): 新增受控 Modbus 工程師指令

驗證:ems_branch compile 與 Engineer targeted tests 通過;charge_point Engineer Modbus targeted tests 通過。未提交的 ConnectorType.java 修改仍未納入 commit。

是由 陳國瑋20 天 前更新

依 Ken 最終指示完成 commit & squash。現在兩個 feature branch 相對各自 private 均只剩一顆 commit:

  • EMS:ab9efbb feat(#1381): 實作工程師 OCPP 與稽核 API
  • charge_point:c62a53d feat(#1381): 新增受控 Modbus 工程師指令

EMS 先前獨立的 Update commit 也已一併 squash。已用 tree diff 確認 squash 前後內容一致,並以 force-with-lease 更新遠端。charge_point 未提交的 ConnectorType.java 修改仍保留且未納入。

是由 陳國瑋20 天 前更新

依 code review 補強 Engineer Modbus 跨服務契約一致性:

  • Branch 與 charge_point 新增 wire contractVersion=1。
  • Branch 的 EngineerModbusCommand DataTransfer 內層 JSON 必須帶 contractVersion。
  • edge 在 Connector 查詢及任何 Modbus I/O 前驗證版本;缺漏或不支援時回 UNSUPPORTED_CONTRACT_VERSION。
  • 兩端仍各自維護 12 個 operation allowlist 與參數驗證,不因版本相同而放寬 defense-in-depth。
  • 雙邊新增 V1 operation 集合鎖定、版本傳送、版本缺漏/不符拒絕測試。
  • 設計文件同步校正 vendorId 為 com.sylksoft.ems,並補充升版規則。

驗證:

  • ems_branch targeted tests passed
  • charge_point OcppDataTransferHandlerEngineerCommandTest passed
  • ems_branch / charge_point compile passed

目前變更尚未 commit,待後續依既有單一 commit 慣例 squash。

是由 陳國瑋20 天 前更新

依 Ken 指示調整 SS3A database constraint 設計:

  • patch 移除 e_engineer_command_log 的 correlation_id / ocpp_unique_id UNIQUE KEY,改為普通 index。
  • patch 移除 e_engineer_command_event 的 (command_log_id, sequence_no) UNIQUE KEY,改為普通 index。
  • patch 移除 event -> command_log FOREIGN KEY 與 ON DELETE CASCADE。
  • JPA @Table 同步移除 @UniqueConstraint,避免 Hibernate 再建立限制。
  • application layer 寫入前檢查 correlationId / ocppUniqueId 重複。
  • operation 更新使用 pessimistic write lock,event sequence 由程式產生並再次檢查。
  • 365 天 retention 改為每批 500 筆,先刪 event 再刪 command log,避免 orphan。
  • PRIMARY KEY 與既有 NOT NULL 保留;普通 index 僅負責查詢效能。
  • REDMINE_CODING_SOP、AI knowledge 與 Engineer Command Plan 已補上此 SS3A 慣例。

驗證:EngineerCommandAuditServiceTest 等 targeted tests passed;ems_branch compile passed。
目前變更尚未 commit,待依既有單一 commit 慣例 squash。

是由 陳國瑋18 天 前更新

  • 狀態In Progress 變更為 Resolved
  • 完成百分比0 變更為 100

Backend #1381 已完成開發、測試、Jimmy 部署與文件更新,依 Ken 確認將本票標記為 Resolved。

最終交付

  • Engineer Role、4 functions、5 API mappings;ADMIN 與 power_user member 已加入 Engineer Role。
  • 19 個 OCPP 1.6 CSMS commands、JSON Schema validation 與 capability。
  • 12 個 CloudLink 受控 Modbus operations;SET_SUPPLY_STATE 依硬體設計使用 controlTestMode()。
  • command audit、event timeline、CALLRESULT/CALLERROR observer、Diagnostics/Firmware status tracking、365 天 retention。
  • DB table 不使用 UNIQUE/FK/ON DELETE CASCADE,資料一致性由 application layer 控制。
  • 時間欄位改為 DATETIME(6),並修正快速完成 operation 可能出現負 elapsedMs 的問題。

版本

  • Jimmy 部署 runtime source:EMS Branch 25058e5;charge_point bb0a2b2。
  • EMS repo 最終收斂 commit(包含部署/E2E 文件):8411ee0。
  • Feature branch:feature/redmine-1381-engineer-command-backend。
  • 未建立 PR/MR、未 merge。

驗證

  • ems_branch:107 tests,0 failures/errors。
  • charge_point:16 tests,0 failures/errors(MySQL Testcontainer)。
  • ems_hq:4 tests,0 failures/errors。
  • Jimmy real E2E:HTTP -> Branch -> OCPP -> CP001 -> Modbus -> audit 完成。
  • OCPP TriggerMessage 的 Accepted/Rejected、search/detail、未登入 401、raw Modbus 400 均通過。
  • 正式報告:test_report/20260714_001_redmine_1381_engineer_command_e2e.md。

已知限制

Fortune(華城)Charge Point 在 2026-07-14 測試時離線,因此尚未完成 Fortune 19 commands 實機 capability matrix;目前維持 UNVERIFIED,待設備恢復後另做回歸,不影響 Backend API 與 Jimmy CloudLink 路徑驗收。

FE 串接說明已更新至協作票 #1380

是由 陳國瑋18 天 前更新

#1381 已於 2026-07-16 部署至 A17,ticket 維持 Resolved。

部署內容:

  • EMS Branch Engineer API / audit / SS3A Role migration。
  • 3 個 CloudLink charge_point instances:CP001、CP002、CP003。
  • 新增 3 tables、Engineer Role、4 functions、5 API mappings、ADMIN/power_user member mapping、19 筆 FE-EVI UNVERIFIED capability。
  • 部署前 Branch 與 edge active transaction 均為 0。
  • 完整 DB 與 4 份原 jar 已備份並驗證。

自動化測試:

  • ems_branch 107 tests,0 failures/errors。
  • charge_point 16 tests,0 failures/errors(MySQL Testcontainer)。

A17 E2E:

  • ADMIN login / Engineer authorization:PASS。
  • Catalog:31 commands(19 OCPP + 12 Modbus):PASS。
  • CP001 READ_SUPPLY_STATE:COMPLETED / Accepted,elapsedMs=1190。
  • Fortune CBDAX50A-25L-A6-A072 TriggerMessage(Heartbeat):COMPLETED / Accepted,elapsedMs=267。
  • search/detail:PASS。
  • 無 JWT:401。
  • RAW_REGISTER_READ:400。
  • negative elapsed count:0。
  • Branch、CP001、CP002、CP003、Fortune 均已恢復 OCPP heartbeat。

既有環境狀態:

  • CP002-001 在部署前即為 FAULTED / INTERNALERROR,部署後維持相同狀態;其餘 connectors 狀態正常。
  • CP002 因該故障 meter 的 Modbus retry,完整 recovery / OCPP reconnect 約需 95 秒;container Up 不代表 recovery 已完成。

Capability 決策:
A17 Fortune 的單一 TriggerMessage 成功只驗證基本 OCPP 通訊,不代表 19 commands 全部已驗證,因此 FE-EVI capability 仍維持 UNVERIFIED,待完整實機矩陣逐項收斂。

動作

匯出至 Atom PDF