Feature #1380 » branch-admin-engineer-command-plan.md
Branch Admin Engineer Command Center Implementation Plan
1. 目標
在 Branch Admin 增加僅供 Engineer Role 使用的「工程師工具」,讓工程師可以:
- 對指定 CloudLink Connector 執行受控 Modbus 讀取與控制。
- 由 Branch 直接向已連線 Charge Point 發送完整的 OCPP 1.6 CSMS Command。
- 查詢每次操作的 request、response、錯誤、耗時及後續狀態時間軸。
- 以 Fortune(華城)充電樁測試為主要使用情境,同時保留其他廠牌的能力標示。
本文件是實作規劃,不包含本次程式碼或資料庫變更。
2. 已確認的產品決策
| 項目 | 決策 |
|---|---|
| 使用者 | 新增 engineer Role,顯示名稱為 Engineer
|
| 初始成員 | 將既有帳號 ADMIN、power_user 額外加入 engineer Role |
| Role 繼承 | 不自動授權所有 administrator 或 power_user Role 成員 |
| 導覽位置 | Branch Admin 側邊欄新增獨立「工程師工具」頁面 |
| 頁面結構 | Charge Point/Connector 選擇器,加上 Modbus、OCPP、操作紀錄 三個分頁 |
| Connector 入口 | Connector 頁面可以 deep-link 到工程師工具並預選 Connector |
| 操作原因 | 不要求填寫 |
| 二次確認 | 不做全面二次確認;僅 Reset、供電開關、修改 Meter ID 顯示一次簡單確認 |
| OCPP 範圍 | 提供全部 19 個 OCPP 1.6 CSMS -> Charge Point Command |
| 未驗證能力 | 仍允許發送,但顯示「未驗證」警告 |
| 已知不支援 | UI 禁用並顯示原因;後端同樣拒絕,不能只依賴前端 |
| OCPP 輸入 | 結構化表單及進階 JSON 模式;兩者都必須通過同一份 OCPP schema 驗證 |
| API 執行方式 | 保留既有 8 個同步 API;新增 Engineer 專用 Command API,在 HTTP request 內完成 WebSocket dispatch,response tracking 採非同步 |
| 長時間操作 |
GetDiagnostics、UpdateFirmware 以操作時間軸追蹤後續 StatusNotification |
| 檔案 URL | V1 由 Engineer 手動輸入 HTTP/HTTPS URL,Branch 不提供檔案上傳或儲存服務 |
| 稽核保留 |
e_engineer_command_log 保留 365 天 |
| Modbus 控制 | 供電開關刻意呼叫 controlTestMode(),不改為 controlRelay()
|
| 原始 Modbus | 不提供任意 function code、register address 或 raw payload |
3. 現況與缺口
3.1 Branch OCPP
現有 OcppController 提供 8 個 API:
RemoteStartTransactionRemoteStopTransactionResetTriggerMessageChangeAvailabilityDataTransferGetConfigurationReserveNow
主要缺口:
- OCPP 1.6 的另外 11 個 CSMS Command 尚無 Branch API。
- 回應處理採逐 Command 註冊 handler;
ReserveNow未註冊 response handler。 - 既有 API 會在 HTTP request 中等待最多 15 秒,不適合 Engineer 操作追蹤及長時間指令。
- 現有
e_ocpp_message_log是傳輸層訊息紀錄,沒有操作者、功能來源、完整操作狀態及跨服務 correlation。 -
FirmwareStatusNotification、DiagnosticsStatusNotification尚無 Branch incoming handler。
既有 /api/fev/connector/availability 及 8 個 /api/ocpp API必須維持相容,內部可逐步共用新的 dispatcher,但不得改變現有 response contract。
3.2 Charge Point Modbus
CloudLink Charge Point 已有受控的 Modbus 方法及部分 OCPP DataTransfer:
-
MeterRead目前只回傳 current、voltage、active power、total energy。 -
RelayControl已透過controlTestMode()實作供電控制。 - Meter Controller 另有 apparent power、power factor、balance、relay state、Meter ID 等能力,但不應由 Browser 直接呼叫 Charge Point REST API。
缺口是建立完整、受控且可稽核的 Branch -> OCPP DataTransfer -> Charge Point Modbus 路徑。
3.3 Branch Admin 與權限
- 前端選單由
/api/menu/list及 SS3A function/role mapping 動態產生。 - 前端使用 OpenAPI 產生的 TypeScript types、React Hook Form、Zod、TanStack Query 及既有 UI 元件。
- 必須新增 SS3A role、function、API mapping、i18n 及指定帳號 role mapping,不能只在 React 寫死選單或角色判斷。
4. OCPP 1.6 Command Catalog
Engineer OCPP API 提供以下全部 19 個 Command:
| 分類 | Command | 主要欄位 |
|---|---|---|
| Remote operation | RemoteStartTransaction |
idTag、connectorId、chargingProfile |
| Remote operation | RemoteStopTransaction |
transactionId |
| Device control | Reset |
type |
| Device control | ChangeAvailability |
connectorId、type |
| Device control | UnlockConnector |
connectorId |
| Request trigger | TriggerMessage |
requestedMessage、connectorId |
| Vendor extension | DataTransfer |
vendorId、messageId、data |
| Configuration | GetConfiguration |
key |
| Configuration | ChangeConfiguration |
key、value |
| Configuration | ClearCache |
無 payload |
| Reservation | ReserveNow |
connectorId、expiryDate、idTag、reservationId、parentIdTag |
| Reservation | CancelReservation |
reservationId |
| Smart charging | SetChargingProfile |
connectorId、csChargingProfiles |
| Smart charging | ClearChargingProfile |
id、connectorId、chargingProfilePurpose、stackLevel |
| Smart charging | GetCompositeSchedule |
connectorId、duration、chargingRateUnit |
| Diagnostics | GetDiagnostics |
location、startTime、stopTime、retries、retryInterval |
| Firmware | UpdateFirmware |
location、retrieveDate、retries、retryInterval |
| Local auth list | GetLocalListVersion |
無 payload |
| Local auth list | SendLocalList |
listVersion、localAuthorizationList、updateType |
Schema 的基準來源為 documents/OCPP_1.6_documentation/schemas/json/。實作時將所需 schema 複製到 Branch runtime resources,並由後端 validator 驗證;不能只靠前端 Zod。
5. Modbus Command Catalog
V1 只允許下列 command key:
| Command key | 類型 | 行為 |
|---|---|---|
CONNECTION_TEST |
Read | 驗證 Gateway/Slave 是否可通訊 |
READ_SUPPLY_STATE |
Read | 讀取目前供電狀態 |
READ_VOLTAGE |
Read | 讀取電壓 |
READ_CURRENT |
Read | 讀取電流 |
READ_ACTIVE_POWER |
Read | 讀取有效功率 |
READ_APPARENT_POWER |
Read | 讀取視在功率 |
READ_POWER_FACTOR |
Read | 讀取功率因數 |
READ_TOTAL_ENERGY |
Read | 讀取累積電量 |
READ_BALANCE |
Read | 讀取餘額 |
READ_METER_ID |
Read | 讀取 Meter ID |
SET_SUPPLY_STATE |
Write |
on/off 轉成 controlTestMode(..., 1/0)
|
SET_METER_ID |
Write | 設定 1 到 255 的 Meter ID |
明確排除:
- 清除歷史資料
- 任意 Modbus function code
- 任意 register address/value
- 瀏覽器直接連線 Charge Point REST API
- 對 Fortune、Tesla 或其他非 CloudLink Connector 發送 Modbus command
6. 目標架構
sequenceDiagram
actor E as Engineer
participant FE as Branch Admin
participant API as Branch Engineer API
participant DB as Command Log DB
participant WS as Branch OCPP WebSocket
participant CP as Charge Point
E->>FE: 選擇裝置、Command、填寫 payload
FE->>API: POST Engineer Command
API->>API: Role、target、capability、schema 驗證
API->>DB: 建立 command log + CREATED event
API->>WS: OCPP CALL(uniqueId, action, payload)
WS->>CP: 發送指令
API->>DB: 更新為 SENT
API-->>FE: 202 + commandLogId + SENT
CP-->>WS: CALLRESULT 或 CALLERROR
WS->>DB: 依 uniqueId 更新狀態及 event
opt Diagnostics/Firmware
CP->>WS: StatusNotification
WS->>DB: 附加進度 event
end
FE->>API: Poll command detail
API-->>FE: 狀態、payload、時間軸
核心原則:
- HTTP request 內必須完成 command log 建立與 OCPP WebSocket dispatch;OCPP CALL 成功送出後,其 response、後續 status notification 的關聯及稽核不得依賴原始 HTTP connection。Client 離開頁面不會取消已送出的 Command。
- OCPP 傳輸仍由既有 WebSocket/session infrastructure 負責。
- 新流程以
ocppUniqueId查找 command log,使用通用 response observer 更新狀態。 - 原有 response handlers 及同步 request managers 仍可同時接收 response,確保舊 API 相容。
- 所有 Branch 與 CloudLink Charge Point 相關 app log 都加入
correlationId;UI 不保存 PID/thread 的整份 raw log。
7. Branch Backend 實作
7.1 Command catalog 與 validation
建立集中式 EngineerCommandCatalog:
- 定義 protocol、command name、target level、risk level、payload schema、terminal result 規則。
- OCPP action 只能從 catalog 選取,不能讓 client 傳任意 action。
- Modbus operation 只能從第 5 節 allowlist 選取。
- OCPP JSON schema validation 同時服務結構化表單及進階 JSON request。
- 驗證 OCPP connectorId 必須屬於所選 Charge Point。
- Charge Point 未連線時在 dispatch 前失敗,狀態記為
SEND_FAILED/OFFLINE。 - Operator 一律取自 JWT identity,不接受 request body 覆寫。
7.2 Engineer Command API(非同步追蹤)
建議 API:
| Method | Path | 用途 |
|---|---|---|
| GET | /api/engineer/commands/catalog |
回傳 command、schema、風險及 capability |
| POST | /api/engineer/ocpp/commands |
建立並發送 OCPP command,回傳 HTTP 202 |
| POST | /api/engineer/modbus/commands |
建立並發送受控 Modbus command,回傳 HTTP 202 |
| POST | /api/engineer/commands/search |
分頁查詢操作紀錄 |
| GET | /api/engineer/commands/{id} |
查詢完整 operation 與 event timeline |
OCPP create request 範例:
{
"chargePointId": "CP001",
"connectorId": "CP001-001",
"command": "ChangeConfiguration",
"payload": {
"key": "HeartbeatInterval",
"value": "60"
}
}
Create response 最少包含:
{
"commandLogId": "uuid",
"correlationId": "uuid",
"ocppUniqueId": "uuid",
"state": "SENT",
"capability": "UNVERIFIED",
"createdAt": "2026-07-14T10:00:00+08:00"
}
API response 需清楚區分:
- HTTP/API validation error:request 根本沒有建立操作。
-
SEND_FAILED:操作已建立,但 Charge Point offline 或 WebSocket send 失敗。 -
CALL_ERROR:收到 OCPP CALLERROR,保存 errorCode、description、details。 -
REJECTED:收到合法 CALLRESULT,但 protocol status 為 Rejected/NotSupported 等。 -
TIMEOUT:在 vendor-aware response timeout 內未收到 CALLRESULT/CALLERROR。
HTTP 202 只表示 Branch 已完成 WebSocket dispatch 並開始追蹤結果。Command 本身不需要排入背景佇列;只有 CALLRESULT、CALLERROR 與後續 status notification 由 WebSocket incoming flow 非同步更新 operation。
7.3 Request 內 dispatch 與非同步 response observer
新增獨立 EngineerOcppCommandDispatcher:
- 建立 log 後產生
correlationId與ocppUniqueId。 - 在發送前寫入 MDC,並建立
DISPATCHINGevent。 - 呼叫既有
OcppCommandSender發送標準 OCPP CALL。 - 發送成功後在同一 HTTP request 內更新
SENT並回傳 HTTP202;不等待 Charge Point 的 CALLRESULT/CALLERROR。 - 若 WebSocket dispatch 當下失敗,更新為
SEND_FAILED,error response 必須包含 commandLogId,方便查詢稽核紀錄。 -
OcppMessageProcessor稍後收到 CALLRESULT/CALLERROR 時,先交給通用 observer 依 uniqueId 更新 Engineer log,再保留既有 response handler 流程。
V1 不要求 durable job queue,也不承諾 Branch process 重啟後重新發送尚未 dispatch 的 Command。服務重啟恢復若有需要,另立需求定義。
這個 observer 不應依賴 19 個獨立 handler。Action 由 command log 或 e_ocpp_message_log 的原始 request 查得。
7.4 狀態機
建議主要狀態:
CREATED -> VALIDATED -> DISPATCHING -> SENT
SENT -> COMPLETED | REJECTED | CALL_ERROR | TIMEOUT
SENT -> RUNNING -> COMPLETED | FAILED | TIMEOUT | STATUS_UNKNOWN
CREATED/VALIDATED/DISPATCHING -> SEND_FAILED
- 一般 command 收到 CALLRESULT 後依 payload status 判定
COMPLETED或REJECTED。 - 沒有 status 的空 CALLRESULT 視該 command 定義判定成功。
-
GetDiagnostics、UpdateFirmware收到初始 response 後進入RUNNING,後續通知才決定最終狀態。 - Fortune 的同步 response timeout 使用現有 vendor timeout 概念,預設 120 秒;其他 vendor 使用可設定預設值。
- 長時間操作 timeout 另設設定值,不能沿用同步 response timeout。
7.5 Firmware/Diagnostics 時間軸
新增 incoming handlers:
FirmwareStatusNotificationHandlerDiagnosticsStatusNotificationHandler
兩者都必須:
- 回傳符合 OCPP schema 的空 CALLRESULT。
- 保存原始 status notification 到 OCPP message log。
- 找出同一 Charge Point 尚在執行的對應 Engineer operation。
- 寫入 command event 並更新主要狀態。
因 status notification 不帶原始 command uniqueId,V1 對同一 Charge Point 的同類長時間 command 只允許一筆 active operation;重複送出回 HTTP 409,避免錯誤關聯。
7.6 Capability matrix
Capability 狀態:
-
VERIFIED:已在指定 vendor/model/firmware 驗證。 -
UNVERIFIED:可發送,UI 顯示警告。 -
UNSUPPORTED:已知不支援,前後端都拒絕。
Fortune 的 19 個 command 初始可設為 UNVERIFIED,已經實機驗證者再調整為 VERIFIED。未知 vendor 預設為 UNVERIFIED,不能假設支援。
建議新增 e_ocpp_command_capability 保存 vendor、model、firmware、command、status、note、verifiedAt、verifiedBy;V1 不必製作 capability 管理 UI,可先由 migration seed 及後續維運 patch 更新。
7.7 URL 與敏感資料
-
GetDiagnostics.location、UpdateFirmware.location只接受合法 HTTP/HTTPS URI。 - 拒絕含 user-info 的 URL,例如
https://user:password@host/path。 - 稽核資料保存實際發送 payload,列表及一般 UI 顯示使用 masked payload。
- URL query value、idTag 等可能敏感欄位預設遮蔽;完整資料只在 Engineer detail API 的受權限欄位中提供。
- app log 不直接輸出完整敏感 payload,使用 commandLogId、correlationId、action 及結果定位 DB audit。
8. Charge Point 實作
8.1 新增受控 DataTransfer message
保留既有 MeterRead、RelayControl contract,另外新增明確的 Engineer messageId,例如:
vendorId: CloudLink
messageId: EngineerModbusCommand
data: JSON string
Data 最少包含:
{
"correlationId": "uuid",
"connectorId": 1,
"operation": "READ_POWER_FACTOR",
"parameters": {}
}
Charge Point handler 必須再次檢查 operation allowlist,不能把 parameters 當作 raw Modbus request。
8.2 Modbus operation mapping
- Read command 呼叫既有
ConnectorMeterReader或ModbusService的具名方法。 -
SET_SUPPLY_STATE固定呼叫controlTestMode(host, port, slaveId, timeout, command)。 -
SET_METER_ID使用controlMeterId()並限制 1 到 255。 - 每個 response 回傳 operation、connectorId、value/unit 或 result、elapsedMs。
- 錯誤回傳穩定 error code,例如
CONNECTOR_NOT_FOUND、GATEWAY_MISSING、MODBUS_TIMEOUT、INVALID_PARAMETER、OPERATION_FAILED。 - 在 handler scope 將 correlationId 放入 MDC,所有相關 Charge Point log 都可用該 ID 搜尋。
8.3 明確不變更的硬體語意
畫面與 Branch API 使用「供電控制」語意,但 CloudLink 智慧電表只能透過 Test Mode 控制:
UI: 供電開啟/關閉
Backend operation: SET_SUPPLY_STATE
Charge Point implementation: controlTestMode(..., 1/0)
不得在實作時自行改用 controlRelay(),也不額外暴露 Test Mode command。
9. Database Plan
9.1 e_engineer_command_log
建議欄位:
-
idBINARY(16) UUID -
protocol:OCPP/MODBUS command_namecharge_point_id-
connector_idnullable -
vendor、model、firmware_versionsnapshot -
capability_statussnapshot operator_idcorrelation_id-
ocpp_unique_idnullable -
request_payloadJSON/LONGTEXT -
response_payloadJSON/LONGTEXT nullable state-
protocol_statusnullable -
error_code、error_description、error_detailsnullable -
created_at、sent_at、responded_at、completed_at -
elapsed_msnullable
索引至少包含:
- unique
correlation_id - unique nullable
ocpp_unique_id (created_at)(charge_point_id, created_at)(connector_id, created_at)(operator_id, created_at)(protocol, command_name, state, created_at)
9.2 e_engineer_command_event
使用子表保存完整時間軸,避免把多次 status notification 覆蓋在主表:
-
idBINARY(16) UUID -
command_log_idFK sequence_noevent_typestate-
payloadJSON/LONGTEXT nullable messagecreated_at
索引及唯一條件:
- unique
(command_log_id, sequence_no) - index
(command_log_id, created_at)
9.3 Migration 與 retention
新增可重複執行的 SQL patch,包含:
- command log/event/capability tables
- Engineer role/function/API/i18n mappings
-
ADMIN、power_user的 member-role mappings - 365 天 cleanup task;刪除主表時先刪 event,或以 FK cascade 處理
Hibernate entity 與 SQL patch 必須一致;integration-test schema 也要同步新增必要表格。
10. SS3A 權限 Plan
建議 function tree:
engineer_tool_mgmt /engineer-tools menu
engineer_tool_execute execute OCPP/Modbus
engineer_tool_log_list search logs
engineer_tool_log_view view detail/timeline
Migration 必須:
- 新增
ss3a_role.engineer及 zh_TW/en_US i18n。 - 新增 function、function i18n、API records 及 function-API mappings。
- 將上述 function 只授權給
engineerRole。 - 將
ADMIN、power_usermember 加入engineerRole。 - 不把 function 直接加到
administrator或power_userRole。
所有 POST/search/detail API 都要有後端權限測試,不能只測側邊欄是否隱藏。
11. Frontend Implementation Guidance
11.1 路由與整體 layout
新增 /engineer-tools 頁面,沿用現有 dashboard shell。頁面採全寬工作區,不做 landing page,也不要把整個 section 包成巢狀 Card。
第一列固定為 target bar:
- Charge Point searchable select
- Connector searchable select;只在 command 需要 connector 時必填
- 線上狀態
- vendor、model、firmware
- capability badge
Target bar 下方使用三個 tabs:
ModbusOCPP操作紀錄
Desktop 可使用左側 command list、右側 form/result 的兩欄布局;mobile 改為上下排列。command list 需有固定寬度或 responsive grid,切換 command 時不能造成整頁寬度跳動。
11.2 Modbus tab
- 只在 Connector Type 為 CloudLink 時啟用。
- command 依「連線與狀態」、「電力讀值」、「控制」分組。
- Read command 直接執行,不顯示確認 modal。
-
SET_SUPPLY_STATE、SET_METER_ID顯示一次簡單確認。 - 顯示結構化 result、單位、耗時、commandLogId 及 correlationId。
- UI 文案使用「供電控制」,可用次要說明標示底層為智慧電表 Test Mode;不新增獨立 Test Mode 控制。
11.3 OCPP tab
- 19 個 command 依第 4 節分類顯示,支援搜尋。
- target bar 顯示
VERIFIED、UNVERIFIED、UNSUPPORTEDbadge。 -
UNVERIFIED可執行,送出按鈕附近顯示非阻斷警告。 -
UNSUPPORTED禁用並顯示 capability note。 - 使用 segmented control 切換「表單」與「JSON」。
- 表單由 catalog/schema metadata 產生或映射;JSON mode 使用同一份 payload state,切換模式不可丟資料。
- JSON schema error 顯示到欄位/path,例如
/csChargingProfiles/chargingSchedule/...。 -
Reset送出前顯示一次簡單確認;其他 OCPP command 不增加二次確認。 - 建立成功後立即顯示 operation status panel,TanStack Query 輪詢 detail API;進入 terminal state 後停止輪詢。
11.4 操作紀錄 tab
Filter:
- 時間範圍
- protocol
- command
- Charge Point/Connector
- operator
- state/result
- correlationId / ocppUniqueId
Table 欄位:
- 執行時間
- protocol / command
- target
- operator
- state/result
- elapsed
- correlationId
點擊 row 開啟 detail drawer 或獨立 detail view,內容包含:
- 裝置 snapshot
- masked request/response JSON
- OCPP CALLERROR details
- command event timeline
- commandLogId、correlationId、ocppUniqueId 的複製按鈕
長字串使用 monospace、wrap 及 copy icon,不能讓 JSON 或 ID 撐破 drawer。
11.5 Connector deep-link
在既有 Connector status/action 區加入工具 icon button,導向:
/engineer-tools?connectorId={id}&tab=ocpp
只有具 Engineer Role/function 的使用者顯示。目標頁仍須重新由 API 驗證 target 與權限。
11.6 前端技術要求
- 完成 Branch OpenAPI 後執行
yarn openapi:refresh,使用產生的 types。 - 沿用既有 React Hook Form、Zod、TanStack Query、shadcn 元件及 toast/error pattern。
- command catalog 是畫面能力與 schema 的唯一後端來源,不在 FE 重複寫 vendor allowlist。
- FE 可維護 presentation metadata,例如中文標籤、欄位排序及分組,但 command key 必須來自 API contract。
- 實作後執行 lint/build,並檢查 desktop/mobile 無重疊、截斷或布局跳動。
12. Test Plan
12.1 Branch unit tests
- 19 個 OCPP command 都能從 catalog 解析並通過合法 schema。
- 每個 command 的 required field、enum、nested payload 及 additional property 驗證。
- 任意 action、任意 Modbus operation、跨 Charge Point connector 被拒絕。
- capability 的 VERIFIED/UNVERIFIED/UNSUPPORTED 行為。
- state machine 不允許非法倒退或重複 terminal transition。
- URL scheme、user-info、Meter ID range 驗證。
- JWT operator 覆蓋 request operator 的攻擊情境不存在。
12.2 Branch integration tests
- Engineer 可呼叫 catalog、execute、search、detail。
- administrator/power_user Role 本身不能呼叫;只有額外持有 engineer Role 的指定 member 可以。
- 非 Engineer 回 403,未登入回 401。
- fake OCPP session 對 19 個 command 驗證 CALL action、uniqueId、payload。
- CALLRESULT、CALLERROR、offline、send failure、timeout 都正確更新 log/event。
- 舊 8 個
/api/ocppAPI 及/api/fevregression tests。 - cleanup 只刪除超過 365 天資料。
12.3 Charge Point tests
- 12 個受控 Modbus operation 的 normal/abnormal cases。
- 非 allowlist operation、raw register/function payload 被拒絕。
-
SET_SUPPLY_STATEspy 驗證呼叫controlTestMode(),且沒有呼叫controlRelay()。 - Gateway missing、connector missing、Modbus timeout、invalid Meter ID 的穩定 error response。
- correlationId 在 DataTransfer response 及 MDC log 可查。
12.4 OCPP long-running tests
- Firmware status progression:Downloaded/Downloading/Installing/Installed 及 failure states。
- Diagnostics status progression:Uploading/Uploaded 及 failure states。
- 同一 Charge Point 重複 active long-running command 回 409。
- 無可關聯 operation 的 status notification 仍正常回 CALLRESULT,並記錄 orphan warning,不可影響 WebSocket session。
12.5 Fortune 實機驗證矩陣
每個 Fortune model/firmware 對 19 個 command 記錄:
- request payload
- CALLRESULT/CALLERROR
- response latency
- protocol status
- 實際設備行為
- capability 結論及備註
測試後以 migration/維運 patch 將 capability 從 UNVERIFIED 更新為 VERIFIED 或 UNSUPPORTED。
13. 分階段實作順序
Phase 1: Database、Role 與 operation foundation
- 建立 command log/event/capability tables。
- 建立 Engineer role/function/API mappings,授權
ADMIN、power_user。 - 實作 audit repository/service、state machine、365-day cleanup。
- 實作 catalog、schema validator、search/detail API。
Phase 2: OCPP dispatch 與非同步 response tracking
- 實作 request 內 dispatch、HTTP 202 response、generic response observer。
- 先接通現有 8 個 command,補上
ReserveNowresponse 缺口。 - 確認舊 8 個 API 及 FEV API 相容。
Phase 3: 補齊全部 19 個 OCPP command
- 加入其餘 11 個 command schema/validation/dispatch。
- 加入 CALLRESULT/CALLERROR audit。
- 加入 Firmware/Diagnostics incoming handlers 及 timeline correlation。
- 產出完整 OpenAPI contract。
Phase 4: CloudLink Modbus command bridge
- Branch 增加 Modbus create API 及 CloudLink-only target validation。
- Charge Point 增加受控 DataTransfer handler。
- 完成 12 個 operation、錯誤碼與 correlation log。
Phase 5: Branch Admin UI
- 新增動態選單、target bar、三個 tabs。
- 完成 schema-driven OCPP form/JSON mode、Modbus controls、log timeline。
- 加入 Connector deep-link。
- 執行 OpenAPI refresh、lint、build 及 responsive verification。
Phase 6: Fortune 實機驗證與 capability 收斂
- 逐 command 執行 Fortune test matrix。
- 修正 vendor-specific payload/timeout 差異,但不破壞標準 OCPP schema。
- 更新 capability seed/patch 及測試報告。
14. 驗收條件
功能完成至少需要符合:
- 只有持有 Engineer Role 的使用者看得到並呼叫得到工程師工具。
-
ADMIN、power_user已額外持有 Engineer Role。 - Fortune 可由同一個 Engineer API 嘗試全部 19 個 OCPP Command。
-
UNVERIFIED可發送、UNSUPPORTED前後端都禁止。 - 所有 payload 都通過對應 OCPP schema;無任意 action 入口。
- Modbus 僅限 CloudLink 及 12 個 allowlist operation。
- 供電控制實際呼叫
controlTestMode()。 - 每次操作都有 commandLogId、operator、target、request、response/error、elapsed、correlationId。
- Firmware/Diagnostics 能顯示後續狀態時間軸。
- 現有 8 個 OCPP API、FEV API 及一般 Branch Admin 功能無 regression。
- 操作紀錄可搜尋、展開並保留 365 天。
- FE 在 desktop/mobile 可完整操作,無文字或控制項重疊。
15. 主要風險與控制
| 風險 | 控制方式 |
|---|---|
| Fortune 回應慢 | vendor-aware response timeout;HTTP API 不同步等待 |
| Vendor 實作偏離 OCPP schema | 保存 CALLERROR/raw response;用 capability note 記錄,不放寬任意 action |
| 長時間通知無 uniqueId | 每 CP/command 限制單一 active operation,按 CP 與 operation 關聯 |
| 敏感 payload 外洩 | DB 權限、UI masking、app log 不輸出完整 payload |
| Engineer 指令誤操作 | Role 隔離、controlled catalog、指定高風險 command 單次確認、完整 audit |
| Modbus 被當成 raw console | Branch 與 Charge Point 雙重 allowlist validation |
| 新流程破壞現有 OCPP API | 保留既有 endpoints/contracts,以 observer 旁路更新 audit |
| Capability 判斷過度樂觀 | 未知預設 UNVERIFIED,必須經 Fortune 實機矩陣後才標 VERIFIED |
16. 不在 V1 範圍
- Branch 韌體或 diagnostics 檔案儲存服務
- 任意 OCPP action/raw WebSocket frame console
- 任意 Modbus register/function console
- Capability 管理 UI
- 全系統集中式 log 平台
- CloudLink Charge Point 實作全部 19 個 CSMS command handler
- 自動把未來 administrator/power_user 成員加入 Engineer Role