Bug #1382
進行中[Branch] OCPP 充電樁離線後 connector 狀態仍停留 AVAILABLE
概述
問題描述¶
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-B351last_heartbeat = 2026-07-06 14:11:02last_boot_notification = 2026-07-06 13:20:51status = FAULTED
-
e_connectors.id = CBDAX50A-24L-XX-B351-001status = AVAILABLEerror_code = NOERRORlast_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 architecture class diagram、heartbeat watchdog sequence diagram、WebSocket close sequence diagram、reconnect sequence diagram、connector offline decision flow、connector state rule。
建議解法¶
採用 BE 修正 1 + 2:
- 新增 heartbeat watchdog 排程:定期掃描 enabled 且
last_heartbeat超過 timeout 的 charge point,將 charge point 標為UNAVAILABLE,並將其底下非 active charging/transaction 的 connectors 標為UNAVAILABLE,同時發布 connector update event。 - 在 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 的案例,修正後應可被標為不可用。
是由 陳國瑋 於 13 天 前更新
實作進度更新(2026-07-21):
已依 Ken 確認的 1+2 方向完成 Branch OCPP 離線狀態同步機制:
- 新增 ChargePointOfflineService,集中處理 charge point offline propagation。
- WebSocket close path 會在 unregisterIfCurrent 確認關閉的是目前 session 後才 mark offline,避免快速重連時舊 session close 誤移除新 session。
- 新增 ChargePointOfflineWatchdogTask,預設每分鐘掃描 enabled 且 heartbeat stale 的 charge point;預設 timeout = 300 秒(5 分鐘)。
- 沒有 currentTransactionId 且 DB 無 ACTIVE transaction 的 connectors 會被標為 UNAVAILABLE / NO_ERROR,並發布 connector update event。
- 有 currentTransactionId 或 ACTIVE transaction 的 connector 不覆寫狀態,只記錄 log,以保護 StopTransaction / reconciliation。
- BootNotification / Heartbeat 只恢復 charge point 本體 AVAILABLE,不批次恢復 connectors;connector recovery 必須等待實際 StatusNotification。
- 測試 profile 已關閉 offlineWatchdogEnabled,避免 Spring integration tests 自動掃描共享測試 DB。
文件:
- documents/20260721/branch-ocpp-offline-status-plan.md
- ai/02-backend-services.md
- test_report/20260721_001_redmine_1382_ocpp_offline_status.md
測試結果:
- mvn -Dtest=ChargePointOfflineServiceTest,ChargePointOfflineWatchdogTaskTest,OcppSessionRegistryTest test:7 tests, 0 failures, 0 errors, 0 skipped
- mvn test:114 tests, 0 failures, 0 errors, 0 skipped
FE 協作提醒:BE 部署並確認 log 正常後,請 FE 協助確認 Branch Admin / HQ / LIFF 收到 connector update event 後畫面是否會從 AVAILABLE 刷新為 UNAVAILABLE;若 UI 需要區分「設備離線」與「最後 OCPP connector status」,建議另開欄位或後續 ticket 討論。
是由 陳國瑋 於 13 天 前更新
Commit / Push 更新(2026-07-21):
已推送 feature branch:feature/redmine-1382-ocpp-offline-connector-status
Commit:798284d fix(#1382): 實作 OCPP 離線 connector 狀態同步
測試維持通過:
- Targeted unit tests:7 tests, 0 failures, 0 errors, 0 skipped
- ems_branch mvn test:114 tests, 0 failures, 0 errors, 0 skipped
請 Ken review 後決定 merge / deployment 時機。BE 部署後請 FE 協助確認 Branch Admin / HQ / LIFF 是否會在 connector update event 後將長時間離線且無交易的 connector 從 AVAILABLE 刷新為 UNAVAILABLE。
是由 陳國瑋 於 13 天 前更新
補充設定更新(2026-07-21):
Ken 提醒 EmsProperties 新增 offline watchdog 參數後,profile application.yml 也應明確設定。已補上 ems_branch 六個 profile:
- conf/local/application.yml
- conf/staging/application.yml
- conf/openclaw/application.yml
- conf/production/application.yml
- conf/deploying/application.yml
- conf/ken/application.yml
新增設定:
- ems.branch.chargePoint.offlineWatchdogEnabled: true
- ems.branch.chargePoint.offlineTimeoutSeconds: 300
- ems.branch.chargePoint.offlineScanFixedDelayMs: 60000
測試:
- mvn -Dtest=ChargePointOfflineServiceTest,ChargePointOfflineWatchdogTaskTest,OcppSessionRegistryTest test:7 tests, 0 failures, 0 errors, 0 skipped
Commit:53f40fa chore(#1382): 補上 OCPP 離線 watchdog 設定
是由 陳國瑋 於 13 天 前更新
Commit 整理更新(2026-07-21):
已依 Ken 要求將 #1382 branch 上屬於本 issue 的 commits squash 成單一 commit,並以 --force-with-lease 更新 remote branch。
目前 feature branch:feature/redmine-1382-ocpp-offline-connector-status
目前唯一 #1382 commit:6f0335e fix(#1382): 實作 OCPP 離線 connector 狀態同步
先前未 squash 的 commit 798284d / 53f40fa 已被整理進 6f0335e。
是由 陳國瑋 於 12 天 前更新
P1-1 狀態 ownership 修正(2026-07-22,Ken 已確認設計):
先前 ticket 所寫「Heartbeat / BootNotification 將 ChargePoint.status 恢復 AVAILABLE」會混淆連線存活與設備運作狀態,現已修正為兩個獨立欄位:
- e_charge_points.ocpp_connection_status
- Branch 內部連線狀態:UNKNOWN / ONLINE / OFFLINE。
- WebSocket established、BootNotification、Heartbeat 會設為 ONLINE。
- 目前 WebSocket close 或 stale heartbeat watchdog 會設為 OFFLINE。
- WebSocket established 不更新 last_heartbeat;只有真正收到 Heartbeat 才更新 last_heartbeat。
- e_charge_points.status
- 保存 charge point main controller 最後回報的運作狀態。
- 只有 OCPP StatusNotification(connectorId=0) 可更新。
- Heartbeat、BootNotification、WebSocket establish/close、watchdog 都不得覆寫 AVAILABLE / FAULTED / CHARGING 等設備狀態。
- connectorId>0 只更新實體 connector,不得覆寫 ChargePoint.status。
離線 connector propagation 維持原需求:
- 有 currentTransactionId 或 DB ACTIVE transaction:保留 connector 狀態並記錄保護 log。
- 無 active transaction:設為 UNAVAILABLE / NO_ERROR 並發布 connector updated event。
- reconnect 不批次恢復 connector,仍等待實際 StatusNotification。
Schema / API:
- 新增非空欄位 ocpp_connection_status,default UNKNOWN。
- migration:documents/sql/redmine-1382-add-ocpp-connection-status.sql。
- 必須先 migration、再部署 JAR;未 migration 時 Hibernate 會因 Unknown column 使讀取 ChargePoint 的 API 失敗。
- ChargePointDto 新增唯讀 ocppConnectionStatus,status 的 Swagger 說明改為 station operational status。
文件:
- documents/20260721/branch-ocpp-offline-status-plan.md 已改寫為純機制交接文件,含 ownership matrix、mapping、UML/sequence/flow diagrams、migration 與 FE contract。
- ai/02-backend-services.md、ai/03-database.md、redmine-tickets/1382.md、測試報告已同步。
測試:
- Targeted regression:10 tests,0 failures / errors / skipped。
- 完整 mvn test:integration DB migration 後 120 tests,0 failures / errors / skipped。
- 測試報告:test_report/20260721_001_redmine_1382_ocpp_offline_status.md。
FE 後續介入:
- Branch Admin / HQ / LIFF 必須將 ocppConnectionStatus(是否在線)與 status(設備最後回報的運作狀態)分開呈現與判斷。
- BE 完成全部 P1/P2、部署並確認 log 後,再正式要求 FE 驗證。
本次只完成第一個 P1。第二、第三個 P1 與 P2 尚待依序討論與修正,因此 ticket 不結案。
是由 陳國瑋 於 12 天 前更新
P1-1 補充相容性 audit:
完整掃描 ChargePoint.status 寫入點後,確認需保留兩個 #1382 前既有的 operational status 來源:
- Charge Point 管理 API:人工註冊初始值與明確的 status override。
- Fortune vendor DataTransfer 告警:可投影 FAULTED / UNAVAILABLE / CHARGING。
因此精確規則是:
- 標準 OCPP runtime 的 station operational status 來源為 StatusNotification(connectorId=0)。
- 既有 admin override / Fortune vendor alarm 仍可更新 ChargePoint.status,但都不得更新 ocpp_connection_status 或 last_heartbeat。
- WebSocket、Heartbeat、BootNotification、close 與 watchdog 屬 connection liveness,絕對不得更新 ChargePoint.status。
另已在 updateChargePoint 明確排除 request.ocppConnectionStatus,避免前端/管理 API 偽造 Branch 內部連線判定,並新增回歸測試。
最終測試:
- Targeted:11 tests,0 failures / errors / skipped。
- Full mvn test:121 tests,0 failures / errors / skipped。
前一則備註的「只有 StatusNotification(connectorId=0) 可更新」請依本則較精確的相容性定義解讀。
是由 陳國瑋 於 12 天 前更新
第二個 P1 修正與驗證完成(尚未 commit/部署):
- OCPP Heartbeat interval 維持 300 秒,增加 30 秒網路傳輸與 scheduler 抖動寬限;offline watchdog effective timeout 改為 330 秒。
- Watchdog 第一次 stale query 僅視為候選清單,不直接寫入 OFFLINE。
- 每個候選使用同一個 cutoffTime 呼叫 markOfflineIfHeartbeatStale;service 以 PESSIMISTIC_WRITE 鎖定 charge point row,重讀最新 lastHeartbeat 後再判斷。
- Heartbeat/WebSocket ONLINE 更新使用同一 row lock,使 ONLINE 與 watchdog OFFLINE 寫入具明確交易順序。
- 邊界與 repository query 一致:lastHeartbeat < cutoff 才是 stale;lastHeartbeat == cutoff 視為未逾時並跳過所有離線/connector 寫入。
- 已同步工程註解、ai/02-backend-services.md、documents/20260721/branch-ocpp-offline-status-plan.md(含 sequence diagram)、本地 ticket 與 test report。
測試:
- Targeted:12 tests,0 failures,0 errors,0 skipped。
- Full ems_branch regression:123 tests,0 failures,0 errors,0 skipped,BUILD SUCCESS。
第三個 P1 與後續 P2 尚未處理,issue 維持未完成狀態。
是由 陳國瑋 於 12 天 前更新
第三個 P1 修正與驗證完成(尚未 commit/部署):
問題:
#1382 的 offline propagation 直接更新 connector DB 與 MQ event,沒有通知 ChargingOrchestrator;PRIVATE connector 的 e_connector_priority 可能仍停在 ELIGIBLE/NOT_PLUGGED/CHARGING,造成離線 connector 留在 queue、占用 slot或再次被派發。
修正:
- 新增 ChargingOrchestrator.onConnectorOffline(connectorId) 明確 hook。
- 無 active transaction 的 connector 改為 UNAVAILABLE 後,在同一 transaction 同步 PRIVATE 未完成 queue:
- chargeStatus = BLOCKED
- statusReason = OCPP_OFFLINE
- priority 移到群組末位
- 進入既有單次補派流程
- 設備主動回報 StatusNotification(Faulted/Unavailable) 的既有 reason 仍維持 FAULTED,避免改壞 #1382 前行為。
- PUBLIC connector 或沒有 queue record 時不建立/修改 queue。
- Active transaction 保護成立時不更新 connector,也不呼叫 offline hook。
- 已是 UNAVAILABLE 的安全 connector 仍執行 idempotent hook,可修復部署前遺留的可派發 queue;已 BLOCKED 時不重複改寫。
- Connector 與 queue 同 transaction 更新;orchestrator 失敗時一起 rollback,connector MQ event 只在 commit 後發布。
- 補派 log 明確區分 eventSource=STATUS_NOTIFICATION/OCPP_OFFLINE。
測試:
- 第三個 P1 targeted:10 tests,0 failures/errors/skipped。
- P1 相關擴大 regression:20 tests,0 failures/errors/skipped。
- mvn clean test:127 tests,0 failures/errors/skipped,BUILD SUCCESS。
- Spring context failureCount=0;JaCoCo 無 class mismatch。
文件已同步:
- documents/20260721/branch-ocpp-offline-status-plan.md(class/sequence/decision flow)
- ai/02-backend-services.md、ai/03-database.md
- redmine-tickets/1382.md
- test_report/20260721_001_redmine_1382_ocpp_offline_status.md
【FE 協作請求】
BE 新增 ConnectorPriority.statusReason = OCPP_OFFLINE(顯示名稱「OCPP 離線」)。請 FE 在 BE 全部 P1/P2 完成並部署後介入:
- refresh OpenAPI generated types;目前 react/branch 的 union 尚未包含 OCPP_OFFLINE。
- queue reason 顯示 mapping 加入 OCPP_OFFLINE,不得顯示成未知值或 FAULTED。
- 驗證 Branch Admin/HQ/LIFF 將 ocppConnectionStatus 與設備 operational status 分開判斷。
- 驗證 connector updated event 後,長時間離線且無交易的 connector 由 AVAILABLE 刷新為 UNAVAILABLE。
三個 P1 已完成;後續 P2 尚待依序確認與修正,issue 維持未完成。
是由 陳國瑋 於 12 天 前更新
第一個 P2 review finding 已修正:WebSocket 快速重連時,舊 close callback 不得把新連線留在 OFFLINE。
修正內容:
- afterConnectionClosed 先用 OcppSessionRegistry.unregisterIfCurrent() 確認關閉的是目前 session。
- 成功移除後改呼叫 ChargePointOfflineService.markOfflineIfNoCurrentSession();service 取得 charge point PESSIMISTIC_WRITE row lock,再用 registry session ownership 複查是否已有新 session。
- WebSocket established 保持先 register、再以同一 row lock 寫 ONLINE。新 session 若在複查前註冊,舊 callback 會跳過 OFFLINE;若在複查後註冊,ONLINE transaction 會等待 OFFLINE commit,最終 DB 仍為 ONLINE。
- 複查刻意使用 getSession().isPresent(),不使用 isOnline();ownership 才是判定 callback 寫入權的依據。
- Repository lock method 更名為 findByIdForOcppConnectionStateUpdate,明確表示 Heartbeat、WebSocket ONLINE/OFFLINE 共用。
文件已更新:documents/20260721/branch-ocpp-offline-status-plan.md(class diagram、兩層 reconnect sequence diagram 與時序規則)、ai/02-backend-services.md、redmine-tickets/1382.md、測試報告。
驗證:
- targeted:13/13 PASS(ChargePointOfflineServiceTest、OcppWebSocketHandlerTest、OcppSessionRegistryTest)
- related targeted:18/18 PASS(另含 ChargePointServiceOcppConnectionStatusTest)
- mvn clean test:131/131 PASS,0 failure / 0 error / 0 skipped,JaCoCo 正常。
目前尚未 commit、push、merge 或部署。下一步依確認順序討論第二個 P2:線上統計仍使用固定 10 分鐘,與 watchdog 330 秒 timeout 不一致。
是由 陳國瑋 於 12 天 前更新
第二個 P2 review finding 已修正:系統健康統計不再使用固定 10 分鐘 Heartbeat 時窗推導 persisted online count。
修正內容:
- ChargePointService.getOnlineChargePointCount() 改為統計 ocppConnectionStatus = ONLINE。
- ChargePointRepository 新增 countByOcppConnectionStatus(ONLINE),移除已無用途的 countByLastHeartbeatAfter / findByLastHeartbeatAfter。
- /api/system/health 的兩個指標保留不同責任:ocpp.active_connections = 目前 process 的 OcppSessionRegistry session 數;charge_points.online = DB persisted OCPP connection state 為 ONLINE 的數量。
- lastHeartbeat 僅作為 watchdog 通訊證據與稽核時間,不再產生第二套在線判準。WebSocket close 或 watchdog 寫入 OFFLINE 後,健康統計會直接反映該 persisted state。
文件已更新:
- documents/20260721/branch-ocpp-offline-status-plan.md:新增 health metric source/meaning table 與維護規則。
- ai/02-backend-services.md、redmine-tickets/1382.md、測試報告同步更新。
驗證:
- targeted:ChargePointServiceOcppConnectionStatusTest 6/6 PASS。
- mvn clean test:132/132 PASS,0 failure / 0 error / 0 skipped;Spring Data repository context 與 JaCoCo 均正常。
至此原 review 的三個 P1 與兩個 P2 findings 均已完成。仍未 commit、push、merge 或部署;FE 協作事項維持:refresh OpenAPI types、支援 OCPP_OFFLINE reason、分開顯示 connection/operational status 並驗證 connector update event。
是由 陳國瑋 於 12 天 前更新
#1382 commits 已依要求 squash 完成。
- Branch:feature/redmine-1382-ocpp-offline-connector-status
- Base:f856713(private)
- Squashed commit:75d3390ee3e1073c5bc2c45eb5987f6e84446d8c
- Message:fix(#1382): 修正 OCPP 離線與連線狀態同步
- private..HEAD commit count:1
- Working tree:clean
- git diff --check private..HEAD:PASS
- 最後程式回歸:mvn clean test 132/132 PASS;squash 後僅另清除三處尾端空白,未改變程式行為。
目前未 push、未 merge、未部署。由於 amend 改寫了既有遠端 branch commit,後續若要更新 origin 需使用 force-with-lease。
是由 陳國瑋 於 12 天 前更新
已完成整併至本機 private 分支。
- 先將 private fast-forward 至 origin/private:508c28a8fcfeaac25c74e67ad539e2b8e0bad00d
- #1382 squash commit:75d3390ee3e1073c5bc2c45eb5987f6e84446d8c
- merge commit:32ab1ba5ccc7e34edaa722de7a4625ac3b199c80(merge(#1382): 整併 OCPP 離線與連線狀態同步)
- 合併衝突:無
- 合併後驗證:java/ems_branch 執行 mvn clean test,132 tests,Failures 0、Errors 0、Skipped 0,BUILD SUCCESS
- git diff --check:通過
- 目前本機 private 較 origin/private ahead 2;尚未 push、尚未部署。
是由 陳國瑋 於 12 天 前更新
Jimmy 大樓部署與驗收完成(2026-07-22)。
部署版本
- branch: private
- merge commit: 32ab1ba5ccc7e34edaa722de7a4625ac3b199c80
- #1382 squash commit: 75d3390ee3e1073c5bc2c45eb5987f6e84446d8c
- deployed JAR SHA-256: c138f743182a677546d94311974aaf5053026c8058507baa1d13a0bab12e64b9
備份
- /opt/ems/backups/20260722-2109-redmine-1382/ems_branch-api.jar
- /opt/ems/backups/20260722-2109-redmine-1382/ems_branch.sql
- 兩份備份均已驗證非空並記錄 SHA-256。
上線前交易檢查
- cp_transactions ACTIVE = 0。
- e_transactions 有一筆 2025-09-25 的歷史孤兒 ACTIVE(transaction_id=199、connector_id=CNT00002),對應 connector 已不存在;有效 connector ACTIVE = 0。未修改此歷史資料。
部署過程與處置
- 初次先啟動 JAR 時,監看發現 Jimmy DB 尚未執行 #1382 migration,OCPP/BootNotification/watchdog 因缺少 e_charge_points.ocpp_connection_status 出現 Unknown column。
- 立即回滾備份 JAR;確認 CP001 WebSocket、StatusNotification、RabbitMQ 恢復。
- 使用 commit 內 documents/sql/redmine-1382-add-ocpp-connection-status.sql 套用 additive migration;本機/遠端 migration SHA-256 一致。既有 status、last_heartbeat、last_boot_notification 均未改動,新增欄位初始值皆為 UNKNOWN。
- 重新部署新 JAR並完成 protocol-level 驗收。
最終驗收
- ems-branch-api: running,restart=0,OOM=false。
- /api-docs: HTTP 200。
- Spring Started Application: 7.809 秒。
- RabbitMQ connection 建立成功。
- CP001: ocpp_connection_status=ONLINE、status=AVAILABLE、connector=AVAILABLE;WebSocket、StatusNotification、Heartbeat 均有新證據。
- CBDAX50A-24L-XX-B351: ocpp_connection_status=OFFLINE,原 station operational status 保持 FAULTED。
- CBDAX50A-24L-XX-B351-001: AVAILABLE 已投影為 UNAVAILABLE。
- 對應 e_connector_priority: charge_status=blocked、status_reason=OCPP_OFFLINE。
- 連續兩輪後續 watchdog 均 confirmedOfflineCount=1,沒有 Unknown column、SQL/OCPP exception 或 container restart。
部署注意事項
- java/ems_branch/scripts/deploy.sh 只負責 build 與 SFTP upload,不會執行 DB migration,也不會 restart container。含 schema 變更的版本必須依文件先 migration、後 JAR,再以 run.sh 重建並做 protocol-level 監看。
是由 陳國瑋 於 12 天 前更新
【請 FE 介入】#1382 Backend 已完成並部署至 Jimmy 大樓,請接續處理前端契約與畫面驗證。
Backend 已提供/改變的契約:
- ChargePoint DTO 新增 ocppConnectionStatus:UNKNOWN / ONLINE / OFFLINE。
- 原 status 保持充電站 operational status(AVAILABLE / FAULTED 等),不可再拿它判斷是否在線。
- OCPP 離線時 connector 會投影為 UNAVAILABLE,並發布既有 connector UPDATED event。
- e_connector_priority.statusReason 新增 OCPP_OFFLINE;Jimmy 實測 queue 已轉為 blocked / OCPP_OFFLINE。
- 遠端命令仍須依 live OCPP connection 判斷,不能只看 operational status=AVAILABLE。
FE 待辦:
- Refresh OpenAPI generated types。
- Branch Admin/HQ/LIFF 若有 ChargePoint 狀態顯示,分開呈現連線狀態與 operational status。
- 補上 UNKNOWN / ONLINE / OFFLINE 與 OCPP_OFFLINE 的 label、顏色及 fallback。
- 確認收到 connector UPDATED event 後會刷新 connector/queue 畫面。
- 在 Jimmy 驗證:CP001 顯示 ONLINE + AVAILABLE;CBDAX50A-24L-XX-B351 顯示 OFFLINE,connector 為 UNAVAILABLE,queue reason 為 OCPP_OFFLINE。
本次只部署 ems_branch,尚未變更或部署任何 FE。
是由 陳國瑋 於 11 天 前更新
【第 17 則說明重寫:本則取代 Journal #4875】
#1382 Backend 已完成並部署至 Jimmy。以下從「為什麼要改」開始說明 FE 需要配合的內容。
一、原本的問題
過去前端容易把 ChargePoint.status 當成「充電樁是否在線」。但 status 實際上是充電樁最後一次主動回報的設備運作狀態,例如 AVAILABLE、FAULTED、CHARGING。
這會造成誤判:充電樁斷線很久以後,資料庫裡的 status 仍可能停在 AVAILABLE,畫面便看起來像「目前可使用」,實際上 Backend 已經無法透過 OCPP 聯絡它,也不能可靠地下遠端命令。
二、為什麼新增 ocppConnectionStatus,而不是直接把 status 改成 OFFLINE
「是否連線」和「設備最後回報的運作狀態」是兩件不同的事,因此 Backend 將它們拆成兩個欄位:
- ocppConnectionStatus:現在是否能透過 OCPP 聯絡充電樁
- ONLINE:目前有有效 OCPP 連線/Heartbeat。
- OFFLINE:WebSocket 已斷線,或超過 Heartbeat timeout。
- UNKNOWN:尚無足夠資料判定,常見於舊資料 migration 後、設備尚未重新連線。
- status:充電樁最後一次回報的設備運作狀態
- 例如 AVAILABLE、FAULTED、CHARGING。
- 斷線時不會被 Backend 改寫,因為 Backend 在失去連線後並不知道硬體目前真正的運作狀態。
- 重新連線時也不應自行猜測 AVAILABLE,必須等設備再次送出 StatusNotification。
因此「OFFLINE + FAULTED」代表:目前聯絡不到充電樁,而它最後一次回報時處於故障狀態。這兩個值同時出現是正確的,不是資料矛盾。
三、為什麼 connector 離線時會改成 UNAVAILABLE
ChargePoint.status 用來保留設備最後回報的事實;但 connector 狀態會直接影響「是否可被車主使用、是否可進入輪充排程」。
當整座 OCPP 充電樁離線,而且 connector 沒有進行中的交易時,Backend 會:
- 將 connector 投影為 UNAVAILABLE。
- 發布既有 connector UPDATED event,通知畫面刷新。
- 若是 PRIVATE connector 且仍在輪充 queue,將 queue 改成 blocked,statusReason 設為 OCPP_OFFLINE,避免離線槍仍占用名額或再次被派發。
這是安全與排程保護,不代表充電樁真的回報了 UNAVAILABLE。若 connector 有進行中的交易,Backend 會先保留原狀態,避免僅因通訊中斷就誤判交易已停止。
四、FE 必須採用的判斷規則
- 顯示「在線/離線」
- 只看 ChargePoint.ocppConnectionStatus。
- 不可再用 ChargePoint.status === AVAILABLE 推論在線。
- 顯示「設備運作狀態」
- 顯示 ChargePoint.status,並清楚標示這是設備最後回報的狀態。
- 若 ocppConnectionStatus === OFFLINE,畫面可同時呈現「離線」與「最後狀態:FAULTED/AVAILABLE」,不要互相覆蓋。
- 遠端操作按鈕
- 只有 ocppConnectionStatus === ONLINE 時才可視為具備即時 OCPP 操作條件。
- 即使 status === AVAILABLE,只要 ocppConnectionStatus === OFFLINE,也不可讓使用者誤以為可正常下達遠端命令。
- UNKNOWN 應採保守處理,不視為 ONLINE。
- Connector 與輪充 queue
- 支援 ConnectorPriority.statusReason = OCPP_OFFLINE,顯示名稱建議為「OCPP 離線」。
- 不可把 OCPP_OFFLINE 顯示成未知值,也不可誤顯示為 FAULTED;FAULTED 是設備故障,OCPP_OFFLINE 是通訊中斷,原因不同。
- 收到既有 connector UPDATED event 後,需刷新 connector 與 queue 畫面。
五、FE 實作事項
- Refresh OpenAPI generated types,取得 ChargePoint.ocppConnectionStatus 與 OCPP_OFFLINE enum。
- 為 UNKNOWN/ONLINE/OFFLINE 補上顯示文字、樣式與未知值 fallback。
- 為 OCPP_OFFLINE 補上 queue reason mapping。
- 檢查 Branch Admin、HQ、LIFF 中所有顯示充電樁狀態或提供遠端操作的畫面,依上述規則調整;沒有使用相關資料的畫面不需變更。
- 確認即時 connector UPDATED event 會使 connector/queue 畫面更新。
六、Jimmy 驗收案例
- CP001
- 預期:ocppConnectionStatus = ONLINE,status = AVAILABLE。
- 畫面意義:目前在線,設備最後回報可用。
- CBDAX50A-24L-XX-B351
- 預期:ocppConnectionStatus = OFFLINE,status = FAULTED。
- 畫面意義:目前離線;最後一次設備回報為故障。
- Connector CBDAX50A-24L-XX-B351-001 預期為 UNAVAILABLE。
- 對應 PRIVATE queue 預期為 blocked,reason = OCPP_OFFLINE。
- 遠端 OCPP 操作不應顯示為可正常執行。
Backend 本次只部署 ems_branch,尚未修改或部署任何 FE。FE 完成後請依上述兩個 Jimmy 案例回報畫面與操作驗證結果。
是由 陳國瑋 於 11 天 前更新
【Jimmy runtime 回復通知(2026-07-23)】
依 Ken 指示,Jimmy 大樓的 ems_branch 已回復至 #1382 部署前版本。本次只回復 Branch runtime,不變更 charge_point、Frontend、交易資料或既有狀態資料。
版本與備份:
- 現行回復後 JAR SHA-256:164b569bb0a88aaefefd4c481216e3695440218e175a0b4c6844e5feef5cd402
- 被替換的 #1382 JAR 已備份:/opt/ems/backups/20260723-173944-rollback-redmine-1382/current-1382-ems_branch-api.jar
- #1382 JAR SHA-256:c138f743182a677546d94311974aaf5053026c8058507baa1d13a0bab12e64b9
部署前交易確認:
- cp_transactions 進行中交易 = 0。
- 所有現存 connector.current_transaction_id = NULL。
- e_transactions transaction_id=199 是 2025-09-25 遺留、connector 已不存在的孤立 ACTIVE 紀錄,本次未修改。
Schema / 資料處理:
- 保留 #1382 additive migration 新增的 e_charge_points.ocpp_connection_status 欄位;舊 JAR 已證實可正常忽略多出的欄位。刪欄位會增加不必要的資料庫風險。
- 本次沒有反向改寫 #1382 已投影的資料,因此 CBDAX connector 仍為 UNAVAILABLE,既有 ocpp_connection_status 亦保留。
- 舊版 Branch 不會再執行 #1382 offline watchdog,也不會持續維護 ocpp_connection_status。此前「#1382 已部署至 Jimmy」及 FE Jimmy 驗收案例,應以本則 runtime 狀態更新為準;待重新部署 #1382 後再執行。
回復後驗收:
- ems-branch-api:running,restart=0,OOM=false。
- /api-docs:HTTP 200。
- Spring Started Application:7.758 秒。
- RabbitMQ:連線建立成功。
- CP001:完成 WebSocket reconnect、BootNotification、StatusNotification(AVAILABLE),並於下一個 5 分鐘週期收到 Heartbeat;connector=AVAILABLE、無進行中交易。
- 回復後未觀察到新的啟動、SQL、OCPP 或 RabbitMQ error。
是由 陳國瑋 於 11 天 前更新
本次先處理 LIFF 車主文案與既有離線充電機制的衝突(暫不處理 ems_hq 新舊並行 / staging env):
-
Branch 端新增
driverState,由後端回傳 LIFF 可直接呈現的中文文案與操作狀態:-
code:穩定狀態代碼,供 FE 測試與 analytics 使用。 -
title/description:可直接顯示給車主。 -
start/stop:包含enabled、label、disabledMessage,FE 不需要再自行由 raw OCPP status 推導按鈕可不可按。
-
-
這樣做的原因:管理後台需要完整技術狀態,但 LIFF 的車主不應看到
SUSPENDEDEVSE、UNAVAILABLE、OCPP_OFFLINE這類技術狀態。LIFF 應呈現「目前能不能開始/停止充電」與清楚中文原因,避免未知狀態被 FE 預設成可開始充電。 -
修正與離線充電機制的衝突:#1382 offline propagation 原本只保護 Branch 的
currentTransactionId/e_transactions ACTIVE,但 CloudLink 私人樁在 OCPP 斷線時,charge_point 本機仍可能依電流與 relay 建立cp_transactions ACTIVE離線交易。現在 Branch 也會讀cp_transactions.status = ACTIVE作為保護條件;若 CP 本機仍有 ACTIVE 交易,就保留 connector 狀態,不投影成UNAVAILABLE,也不呼叫 queue offline hook。 -
若讀取 CP runtime 證據失敗,採保守策略:保留 connector 狀態。這是為了避免 DB/schema 暫時不可讀時,把仍在離線充電的私人樁錯誤釋放或讓車主畫面誤判。
-
文件已更新:
documents/20260721/branch-ocpp-offline-status-plan.md、ai/02-backend-services.md、ai/03-database.md。
是由 陳國瑋 於 11 天 前更新
補充 ems_hq 新版 staging 調整:
-
目前 ems_hq 正式環境運行版本視為舊版,仍維持既有
status/statusLabel行為,不改變舊 LIFF 的相容性。 -
新版 ems_hq 只做
driverStatepassthrough,不在 HQ 重新推導車主文案。原因是車主狀態需要同時理解 Branch OCPP connection、connector operational status、Branch transaction 與 charge_point 本機 offline transaction 證據;這個判斷應集中在 Branch,避免 HQ/FE 出現第二套 mapping。 -
已更新的 passthrough 路徑:
-
GET /api/user/connectors:Branch/cp/hq/user/connectors回來的driverState會複製到MyConnectorsDto.Connector.driverState。 -
GET /api/connector/info:ConnectorFromBranchDto.driverState保留 Branch 回傳值。 - WebSocket 初始資料與 RabbitMQ connector event:
ConnectorEventData.driverState直接承接 Branch payload。
-
-
相容性規則:
driverState可能為null,代表上游 Branch 還是舊版或舊 payload。FE 不得因driverState = null將 connector 預設為可開始充電;新版 LIFF 應優先使用driverState,舊欄位只作相容/備援顯示。 -
驗證:
java/ems_hq已通過mvn test(5 tests passed)。文件已同步更新documents/20260721/branch-ocpp-offline-status-plan.md與ai/02-backend-services.md。
是由 陳國瑋 於 11 天 前更新 · 已被編輯
【FE 協作請求:LIFF 改用 driverState,含設計源由與新舊 HQ 相容方式】
#1382 最初要解決的是「OCPP 充電樁已離線很久,但 connector 仍停留 AVAILABLE,讓系統與使用者誤以為可以充電」。第 18 則 note 說明了管理端為何要把連線狀態與設備運作狀態分開;本則進一步說明 LIFF 車主畫面為何不能直接呈現或自行解讀這些技術狀態,以及 FE 應如何串接。
一、原本 LIFF 會遇到的問題
Backend 內同時存在多種不同責任的狀態:
- ChargePoint.ocppConnectionStatus:目前 OCPP 是否在線。
- ChargePoint.status:充電樁最後一次回報的設備運作狀態。
- Connector.status:槍的 OCPP operational status。
- ConnectorPriority.statusReason:輪充 queue 的阻擋原因。
- Branch e_transactions:Branch 已知的交易狀態。
- charge_point cp_transactions:CP 本機在 Branch 斷線時仍可能建立或維持的離線交易。
這些資料對管理後台與除錯很重要,但不適合原樣交給車主。若 LIFF 直接顯示 SUSPENDEDEVSE、UNAVAILABLE、OCPP_OFFLINE,或由 FE 自行組合上述欄位,很容易產生以下問題:
- 車主看不懂技術狀態,不知道現在到底能不能開始或停止充電。
- HQ、Branch、FE 各自維護一套 mapping,日後新增狀態時容易出現不同判斷。
- 未識別的新狀態可能被前端 fallback 成「可開始充電」,造成錯誤操作。
- 充電樁雖然 OCPP 離線,但 CP 本機可能仍在離線充電;若只看 OFFLINE 或 UNAVAILABLE,可能誤顯示可重新開始,或顯示可遠端停止但命令其實送不出去。
因此,管理後台仍可呈現完整技術狀態;LIFF 則應只回答車主真正需要的三件事:目前狀況、能不能開始、能不能停止,以及不能操作的中文原因。
二、為什麼由 Branch 產生 driverState
車主狀態的正確判斷需要同時掌握 OCPP connection、connector operational status、輪充狀態、Branch transaction,以及 CP 本機 offline transaction。這些證據只有 Branch 最完整,因此由 Branch 集中產生 driverState:
- code:穩定代碼,供 FE 測試、analytics 與畫面分支使用。
- title / description:可直接顯示給車主的中文文案。
- start / stop:各自包含 enabled、label、disabledMessage。
這樣可確保 HTTP 初始資料、WebSocket initial data 與後續 connector UPDATED event 使用同一套規則。HQ 不重新推導,FE 也不再由 raw status 猜測按鈕權限,避免形成第二、第三套狀態機。
三、為什麼這個設計不會破壞既有離線充電
CloudLink 私人樁在 CP 與 Branch 的 OCPP 連線中斷後,CP 本機仍可能依電流與 relay 狀態持續充電,並在 cp_transactions 留下 ACTIVE 交易。若 #1382 只因 OCPP OFFLINE 就把 connector 改成 UNAVAILABLE 並釋放 queue,會和既有離線充電機制衝突。
新版 Branch 在進行 offline propagation 與 driverState 判斷時,會同時檢查:
- connector.currentTransactionId。
- Branch e_transactions ACTIVE。
- charge_point cp_transactions ACTIVE。
只要任一交易證據仍存在,就保留交易中的 connector,不把它當成一般可重新開始的槍;LIFF 回傳 OFFLINE_CHARGING。此狀態會告訴車主「充電仍在進行」,但 Start 與 Stop 都 disabled:不可重複開始,也不可假裝離線時能遠端停止。
若 CP runtime transaction 證據暫時讀取失敗,Backend 採保守策略保留 connector 狀態,不會因 DB/schema 暫時不可讀而錯誤釋放仍在離線充電的槍。
四、為什麼新版 HQ 只 passthrough
正式環境目前運行的 ems_hq 是舊版;修改後的新版 ems_hq 先部署在 staging。新版 HQ 的責任只有把 Branch 回傳的 driverState 原樣傳給 LIFF 與 WebSocket,不在 HQ 重新解讀 OCPP 或交易資料。
原因是 HQ 並不具備 Branch 與 CP 的全部 runtime 證據。若 HQ 再自行推導,不但容易與 Branch 不一致,也可能漏掉 cp_transactions 所代表的離線充電。
五、新舊 HQ 如何讓同一份 FE 並行服務
- driverState != null:代表上游已提供新版車主狀態,LIFF 必須以 driverState 作為中文顯示及 Start/Stop 按鈕的唯一依據。
- driverState == null:代表目前上游仍是舊版 HQ、舊版 Branch 或舊 payload。FE 必須完整沿用既有 status/statusLabel UI 與既有按鈕邏輯,不可把 null 或未知狀態預設為可開始充電。
因此 FE 可以先部署同一份程式,同時服務正式舊 HQ 與 staging 新 HQ;等正式 HQ 升級後,資料出現 driverState,畫面會自然切換到新版規則,不需要同時維護兩份 FE。
六、FE 實際會收到 driverState 的位置
- LIFF 充電樁清單
- GET /api/resident/connectors
- Headers:X-Line-Id、X-Building-Id
- 每個 connector 內含 driverState。
- LIFF 單一充電樁
- GET /api/connector/info/{buildingId}/{connectorId}
- Header:X-Line-Id
- 回傳 connector 內含 driverState。
- WebSocket
- initial data:connectorData.driverState。
- 後續 connector UPDATED event:connectorData.driverState。
HQ 呼叫 Branch 的內部路徑為:
- GET /api/cp/hq/user/connectors?user={userId}
- GET /api/cp/hq/connector/info?id={connectorId}
七、FE 欄位使用規則
- title、description、start.label、stop.label、disabledMessage:都是 BE 提供的中文文案,FE 直接填值顯示,不另做 OCPP-to-Chinese mapping。
- Start 是否可點:只看 driverState.start.enabled。
- Stop 是否可點:只看 driverState.stop.enabled。
- enabled=false 時,顯示相對應的 disabledMessage,讓車主知道不能操作的原因。
- 新版模式下,不得再由 status、statusLabel、ocppConnectionStatus 自行推導按鈕權限;這些 raw 欄位保留給管理端、除錯與舊版相容。
- code 可供測試與 analytics 使用,但畫面文字以 BE 文案為準,不要用 code 重新維護另一套中文 mapping。
driverState 範例:
{
"driverState": {
"code": "OFFLINE_CHARGING",
"title": "充電中",
"description": "充電樁目前離線,但本機充電紀錄顯示充電仍在進行。遠端操作會在連線恢復後提供。",
"start": {
"enabled": false,
"label": "開始充電",
"disabledMessage": "目前已有充電進行中"
},
"stop": {
"enabled": false,
"label": "停止充電",
"disabledMessage": "充電樁離線,暫時無法遠端停止"
}
}
}
八、主要狀態的驗收期待
- READY:顯示「可開始充電」;Start enabled,Stop disabled。
- QUEUED:顯示「等待充電」;Start/Stop disabled。
- CHARGING:顯示「充電中」;Start disabled,Stop enabled。
- OFFLINE_CHARGING:顯示「充電中」,但 Start/Stop 都 disabled;說明本機充電仍在進行、離線時不能遠端停止。
- OFFLINE_UNAVAILABLE:顯示「暫時無法使用」;Start/Stop disabled。
- FAULTED、UNAVAILABLE、UNKNOWN:直接顯示 BE 文案;Start/Stop disabled。
九、部署與端到端驗證結果
- 新版 ems_hq 已部署至 staging;正式舊版 ems_hq 未變更。
- 最新 ems_branch 已部署至 Jimmy 大樓。
- staging HQ 與 Jimmy Branch 的 /api-docs 均為 HTTP 200。
- 實際呼叫 staging GET /api/resident/connectors 回傳 HTTP 200;HQ log 證實請求轉送到 Jimmy /api/cp/hq/user/connectors。
- 回應內已取得 driverState;本次資料包含 READY 與 OFFLINE_UNAVAILABLE,其中 READY.start.enabled=true。
- Jimmy CP001 已完成 WebSocket reconnect、BootNotification、StatusNotification 與部署後 Heartbeat。
十、FE 待辦與回報項目
- Refresh OpenAPI generated types,取得 driverState 與 ConnectorPriority.statusReason=OCPP_OFFLINE。
- LIFF 實作 driverState != null / == null 的新舊相容分流。
- HTTP initial response 與 WebSocket UPDATED event 都必須更新同一組 driverState 畫面與按鈕,不能再被舊 status mapping 覆蓋。
- 驗證 READY、CHARGING、OFFLINE_CHARGING、OFFLINE_UNAVAILABLE 與 driverState=null。
- Branch Admin 的 queue reason 補上 OCPP_OFFLINE,中文顯示「OCPP 離線」,不可顯示 unknown,也不可誤映射成 FAULTED。
- 完成後請回報 staging 畫面、Start/Stop enabled 狀態、disabledMessage,以及正式舊 HQ 畫面是否維持原行為。
是由 陳國瑋 於 11 天 前更新
【更正前一則 FE note 的 API 路徑,並補充 staging 實測結果】
前一則 note 將 LIFF API 路徑寫成 GET /api/user/connectors,該路徑不正確,請以下列資訊為準:
- LIFF 充電樁清單:
GET /api/resident/connectors- Request headers:
X-Line-Id、X-Building-Id
- Request headers:
- LIFF 單一充電樁:
GET /api/connector/info/{buildingId}/{connectorId}- Request header:
X-Line-Id
- Request header:
- HQ 呼叫 Branch 的內部 API:
- 清單:
GET /api/cp/hq/user/connectors?user={userId} - 單一槍:
GET /api/cp/hq/connector/info?id={connectorId}
- 清單:
2026-07-23 已在 staging HQ 搭配 Jimmy 大樓新版 ems_branch 做端到端驗證:呼叫 GET /api/resident/connectors 回傳 HTTP 200;HQ log 顯示請求確實轉送到 Jimmy 的 /api/cp/hq/user/connectors。回應內含 driverState,本次資料出現 READY 與 OFFLINE_UNAVAILABLE;其中 READY.start.enabled=true,符合目前設計。
FE 實作規則與中文文案不變;本 note 僅更正 API 路徑並提供實測結果。
是由 鍾正剛 於 11 天 前更新
【LIFF (react/web) driverState 串接完成,回應 note #22/#23】
已完成開發,branch: feature/redmine-1382-liff-driver-state(由 fix/issue-1382-ocpp-offline-connector-status 分出)。
變更範圍僅 react/web(LIFF),依 note #22/#23:
-
yarn openapi:refresh(指向 https://hq-api.sylksoft.com,已確認為新版 ems_hq staging)拉取 driverState schema 至 lib/data/emsapi.ts。 - WS payload 型別(useChargingStore.ts ChargingConnectorData)新增 driverState。
- app/charger/charge.ts 新增 getDriverPresentation:driverState 存在時回傳 code/title/description/start/stop/tone;driverState 為 null 時回傳 null。
- app/charger/hooks/use-dashboard-data.ts 回傳 driverPresentation(HTTP + WS 合併資料)。
- Public(dashboard-api.tsx)/ Private(dashboard-private.tsx)畫面:driverState != null 時完全用 BE 的 title/description/start.enabled/stop.enabled/disabledMessage 顯示與控制按鈕;driverState == null(正式舊版 HQ)時完全維持原本 status.id 邏輯不變,未修改既有分支。
- code -> tone 顏色新增:READY/CHARGING=green, QUEUED=blue, OFFLINE_CHARGING/OFFLINE_UNAVAILABLE/UNAVAILABLE=gray, FAULTED=red, UNKNOWN/未知新值=gray fallback。
- 本地新增 docs/driver-state-qa-checklist.md(此專案 docs/*.md 為 gitignore,未進 git,僅供本機 QA 對照)。
驗證:npx tsc --noEmit 通過(0 errors);yarn build production build 成功。yarn lint 因專案既有 eslint-config-next module 解析問題失敗,已用 git stash 確認改動前也會失敗,與本次無關。
未執行:實機 LIFF/LINE 登入 E2E 測試(新版 driverState 目前僅在 staging,正式 HQ 尚未升級);react/branch 的 queue reason OCPP_OFFLINE 中文顯示(屬於另一個 project,不在此次範圍)。
是由 鍾正剛 於 11 天 前更新
【FE(Branch Admin) 完成回報 - 對應 note #22(#4881/#4882) 第十節第5點】
Branch:fix/issue-1382-ocpp-offline-connector-status
Commit:0541b75 issue #1382: 充電站連線狀態顯示與遠端操作把關
已完成:
- yarn openapi:refresh 同步 ChargePoint.ocppConnectionStatus(UNKNOWN/ONLINE/OFFLINE)與 ConnectorPriority.statusReason 新值 OCPP_OFFLINE。
- 充電站清單(cp/list)與工程師工具 Target Bar 新增獨立的連線狀態 badge,與設備運作狀態(status)分開顯示,不再用 status===AVAILABLE 推論在線。
- Connector 編輯頁「充電樁狀態」tab:
- 顯示所屬充電站連線狀態 badge。
- 開始/停止充電按鈕在充電站 ocppConnectionStatus!==ONLINE 時停用並提示「充電樁離線」;充電中但離線時提示不可誤判交易已結束。
- 連線由離線恢復為在線時自動刷新一次 connector 狀態,不再卡在舊的 UNAVAILABLE。
- 新增輪充佇列狀態顯示區塊(chargeStatus + statusReason,含 OCPP_OFFLINE→「OCPP 離線」中文標籤),呼叫既有但先前未串接的 GET /api/charge-rotation/queue/connector/{connectorId}。
- 工程師工具 OCPP 指令面板:充電站離線時停用指令送出並提示,Modbus 面板維持不動(走 charge_point 硬體橋接,非 OCPP 連線層)。
瀏覽器實測(Jimmy 大樓資料):
- 充電站清單:CBDAX50A-24L-XX-B351 正確顯示「故障」+「已離線」;CP001 正確顯示「可用」+「已連線」。
- 工程師工具:選到離線充電站時 OCPP 指令送出鈕停用並顯示提示;切到 CP001(在線)恢復正常可送出。
- Connector 編輯頁:CBDAX50A-24L-XX-B351-001 顯示紅色「已離線」;CP001-001 顯示綠色「已連線」且開始充電按鈕正常可用。
待後端協助事項:
- GET /api/charge-rotation/queue/connector/{connectorId} 目前回傳 403,其餘所有既有 API 皆為 200,判斷是新 API 尚未加入 ss3a_func_api_mapping / role 權限。前端輪充佇列顯示的程式邏輯已完成,權限補上後即可直接顯示,無需再改前端程式碼。
本次僅變更 react/branch,未變更 react/web(LIFF driverState 屬另一分支/範圍)。
是由 鍾正剛 於 11 天 前更新
【FE(Branch Admin) 調整回報】
Branch:fix/issue-1382-ocpp-offline-connector-status
Commit:527051f issue #1382: 移除輪充佇列狀態顯示與相關 API 呼叫
前一則回報中新增的「輪充佇列狀態」顯示區塊,實測發現其呼叫的 GET /api/charge-rotation/queue/connector/{connectorId} 回傳 403(其餘既有 API 皆為 200),研判是新 API 尚未加入 ss3a_func_api_mapping / role 權限。
因此本次先將該顯示區塊與對應的 useConnectorPriorityQueue hook、lib/ocpp-status.ts 內未再使用的 ConnectorPriority label mapping 一併移除,避免多打一支目前用不到、且會回 403 的 API。lint / tsc 皆通過。
連線狀態顯示(ocppConnectionStatus badge)、遠端操作把關(充電/停止充電、OCPP 指令面板)等其餘功能不受影響,維持前一則回報的驗證結果。
待後端補上該 API 的權限後,若仍需要在 Branch Admin 顯示輪充佇列原因(含 OCPP_OFFLINE),前端會再重新串接。