專案

一般

配置概況

Bug #1382

是由 陳國瑋13 天 前更新

## 問題描述 
 Jimmy 大樓的 Fortune 充電樁 `CBDAX50A-24L-XX-B351` 已長時間未連線,但其 connector `CBDAX50A-24L-XX-B351-001` 在 ems_branch 仍顯示 `AVAILABLE / NOERROR`,導致後台/HQ/住戶端可能誤判該槍可用。 

 ## 現場證據(2026-07-21 查 Jimmy) 
 - DB 現在時間:約 `2026-07-21 11:06:00` 
 - `e_charge_points.id = CBDAX50A-24L-XX-B351` 
   - `last_heartbeat = 2026-07-06 14:11:02` 
   - `last_boot_notification = 2026-07-06 13:20:51` 
   - `status = FAULTED` 
 - `e_connectors.id = CBDAX50A-24L-XX-B351-001` 
   - `status = AVAILABLE` 
   - `error_code = NOERROR` 
   - `last_status_change = 2026-07-06 14:04:50` 
 - `e_ocpp_message_log` 最後一筆 `Heartbeat` 在 `2026-07-06 14:11:02` 
 - `e_ocpp_message_log` 最後一筆 `StatusNotification` 在 `2026-07-06 14:09:38`,payload 為 `status: Available` 

 ## 初步原因 
 目前 ems_branch 對 OCPP WebSocket close 與 heartbeat stale 沒有可靠地同步 connector 狀態: 
 - `OcppWebSocketHandler.afterConnectionClosed()` 只 unregister session,沒有更新 DB 狀態。 
 - `HeartbeatHandler` 只更新 charge point heartbeat。 
 - `ChargePointService.updateHeartbeat()` 只更新 `lastHeartbeat`。 
 - 前端/HQ connector DTO 直接讀 `e_connectors.status`,因此最後一次 `AVAILABLE` 會被長期保留。 

 ## 需求確認紀錄 
 - 2026-07-21 Ken 確認:heartbeat stale timeout 預設使用 `5 分鐘`。 
 - 2026-07-21 Ken 確認:charge point 離線時,有 ACTIVE transaction 或 `currentTransactionId` 的 connector 不改 connector 狀態,只把 charge point 標為 `UNAVAILABLE` 並記錄 log;沒有 ACTIVE transaction / 沒有 `currentTransactionId` 的 connector 才改成 `UNAVAILABLE / NO_ERROR` 並發布 connector update event。 
 - 2026-07-21 Ken 確認:離線 charge point 重新連線時,BootNotification 或第一個 Heartbeat 可將 charge point 本體標回 `AVAILABLE`;connector 不整批自動恢復 `AVAILABLE`,必須等待實際 StatusNotification 回報後再恢復。 

 ## 機制文件 設計文件 
 - `documents/20260721/branch-ocpp-offline-status-plan.md` 
 - 文件定位:交接與後續需求開發用的 OCPP 離線狀態同步機制說明,不是單一案場 problem report。 
 - 內容包含 status ownership、core rules、target target architecture class diagram、heartbeat watchdog sequence diagram、WebSocket close sequence diagram、reconnect sequence diagram、connector offline decision flow、connector state rule。 

 ## 建議解法 
 採用 BE 修正 `1 + 2`: 

 1. 新增 heartbeat watchdog 排程:定期掃描 enabled 且 `last_heartbeat` 超過 timeout 的 charge point,將 charge point 標為 `UNAVAILABLE`,並將其底下非 active charging/transaction 的 connectors 標為 `UNAVAILABLE`,同時發布 connector update event。 
 2. 在 OCPP WebSocket close 時即時 mark offline:`afterConnectionClosed()` 觸發 service,將該 charge point/connectors 標為 offline。此機制作為即時修正,但仍需 watchdog 處理 TCP 半斷、process crash、server restart 等情境。 

 ## FE 協作提醒 
 BE 完成並部署後,需要請 FE 協助確認: 
 - Branch Admin / HQ / LIFF 看到的 connector 狀態是否會由 `AVAILABLE` 更新為 `UNAVAILABLE`。 
 - 若現有 UI 只依 `connector.status` 顯示,確認收到 connector update event 後畫面會刷新。 
 - 若 UI 需要額外呈現「設備離線」與「槍本身 OCPP 最後狀態」的差異,再由 FE/API 討論是否另開欄位或 ticket。 

 ## 驗收條件 
 - 當 charge point heartbeat 超過 timeout 或 WebSocket close 後,該 charge point 不應繼續讓 connector 顯示為 `AVAILABLE`。 
 - 不應覆蓋仍在有效交易中的狀態,需避免誤中斷 ACTIVE transaction。 
 - connector 狀態更新後需發布既有 connector update event,讓 HQ/前端可同步。 
 - Jimmy `CBDAX50A-24L-XX-B351-001` 這類長時間無 heartbeat 的案例,修正後應可被標為不可用。

返回