專案

一般

配置概況

動作

Bug #1517

進行中

[Backend Bug] A17 CP003 已回報狀態仍被心跳 watchdog 覆寫為 UNAVAILABLE,修正 OCPP 存活判定與恢復同步

是由 陳國瑋 於 5 天 前加入. 於 4 天 前更新.

狀態:
In Progress
優先權:
High
被分派者:
-
開始日期:
2026-09-26
完成日期:
預估工時:

概述

1. 本單要解決什麼問題

寶台 A17 的充電樁列表中,CP003-001、CP003-004、CP003-008 持續顯示「無法使用」。然而,2026-09-26 凌晨查核時,CP003 已經與 Branch 恢復通訊,設備端記錄這三支 Connector 的狀態都是 AVAILABLE(可用),而且仍持續成功讀取電表。

本次已確認的問題是:

CP 曾經主動把「可用」狀態送給 Branch,Branch 也已成功收到;但 Branch 後來只根據過舊的心跳時間,將三支 Connector 改成「無法使用」。心跳恢復後,Branch 沒有重新取得並更新 Connector 狀態,導致列表長時間保留錯誤的不可用狀態。

本單需要同時處理兩件事:

  1. 避免誤判離線: CP 還在傳送有效 OCPP 訊息時,Branch 應將這些訊息納入「設備仍有通訊」的判斷,不能只看最後一筆 Heartbeat。
  2. 讓狀態可以恢復: 若 Branch 已經因離線把 Connector 標成不可用,通訊恢復後應重新取得 CP 的實際狀態,避免永久停留在舊的不可用狀態。

目前的證據可以確認「後台狀態與設備端狀態不一致」,但本次沒有操作實機開始充電,不能把電表通訊正常直接當成「實際充電功能已驗證正常」。

2. 系統角色與名詞

本單使用的名詞如下,避免把「通訊在線」和「可以充電」混為一談。

名稱 在本案中的意思
CP(Charge Point) 設備端。本案是 CP003,由它與實體設備通訊,再透過 OCPP 回報給 Branch。
Connector 個別充電連接器。本案 CP003 底下有 001、004、005、008。
Branch/CS 接收 OCPP 的後台服務。Branch 在本系統扮演 OCPP 的 Central System(CS),充電樁列表所使用的狀態也由它提供。
Heartbeat CP 傳給 Branch 的心跳訊息,用來表示仍有通訊。它不包含每一支 Connector 的充電狀態。
StatusNotification CP 主動回報設備或 Connector 狀態的訊息,例如 Available、Charging、Faulted、Unavailable。
BootNotification CP 啟動註冊時使用的訊息。現行 CP 程式在部分重連流程也會嘗試發送,但有冷卻時間,短時間內不一定再次發送。
Watchdog Branch 定時執行的離線檢查程式。若判定通訊已逾時,會把 CP 標成離線,並依交易保護規則處理其 Connectors。
TriggerMessage Branch 請 CP 重新送出某類 OCPP 訊息的標準指令。本案可用來請 CP 回報目前的 StatusNotification。

CP 為 ONLINE,只能證明通訊狀態;某支 Connector 究竟是可用、故障或正在充電,仍須依該支的實際狀態判斷。 因此不能在收到 Heartbeat 時,把所有 Connector 一律改成 AVAILABLE。

3. 現場症狀與查核結果

以下是 2026-09-26 約 01:19(台灣時間)的查核快照,並非持續即時監控結果。

項目 查核結果 代表的意義
CP003 的 Branch 連線狀態 ONLINE;最近 Heartbeat 為 01:18:01 CP 與 Branch 當時已恢復通訊。
Branch 的 CP003-001 UNAVAILABLE;原因為 OCPP heartbeat stale 後台仍保存「心跳逾時造成的不可用」。
Branch 的 CP003-004 同上 同上。
Branch 的 CP003-008 同上 同上。
三支 Connector 的 Branch 狀態變更時間 均為 2026-09-25 06:11:57 三支是同一輪離線判定一起被改寫。
CP 設備端的三支 Connector 均為 AVAILABLE,current_transaction_id 均為 NULL 設備端記錄與 Branch 不一致。
三支 Connector 的電表讀取 持續更新;當時可讀到約 230V、0A,polling log 顯示繼電器斷開 當時仍能取得設備量測,但尚未做實際充電測試。
06:11:57 之後的 CP003 StatusNotification 截至查核時,OCPP audit 中 request 共 0 筆 Branch 改成不可用後,沒有再收到可用來恢復狀態的通知。

使用者看到的直接影響,是這三支在列表中長時間顯示「無法使用」,無法正確判斷設備是否可用。本次未實際送出啟動充電指令,因此不以此查核宣稱已驗證每一個啟動入口的阻擋結果。

4. 事件經過:CP 有回報,Branch 後來又改掉狀態

以下時間均為 2026-09-25,時區為 Asia/Taipei。

時間 發生的事 與問題的關係
05:59:47 Branch 保存的上一筆 Heartbeat 時間。 後續離線檢查仍使用這個舊時間。
06:06:02 Branch 收到 BootNotification 並接受。 這是當時最後一次 BootNotification 時間。
06:08:01 CP003 的 WebSocket 因未及時收到 pong 而關閉。 觸發本次重連;為何未收到 pong 的底層原因尚未查明。
06:08:31 WebSocket 重連成功。CP 因 BootNotification 冷卻時間尚餘約 150 秒,略過再次發送 BootNotification。 Branch 的 Boot 時間仍停在 06:06:02。
06:08:42~06:08:50 CP 主動送出各 Connector 的 AVAILABLE StatusNotification;Branch 收到並回覆成功。 這證明 CP 有主動回報,而且 Branch 已經收到最新狀態。
06:11:56~06:11:57 Branch watchdog 判定 Heartbeat 與 BootNotification 均已過期,將 CP003 標成離線,並將 001、004、008 改成 UNAVAILABLE。 問題發生點:近期收到的 StatusNotification 沒有被納入存活判定,剛恢復的可用狀態又被覆寫。
06:13:01 CP 下一筆 Heartbeat 成功,其後每五分鐘持續成功。 CP 的連線狀態恢復,但 Heartbeat 本身不包含 Connector 狀態。
至 9/26 約 01:19 沒有再收到新的 StatusNotification,三支仍是 UNAVAILABLE。 設備端維持 AVAILABLE,沒有新的狀態變化可自然觸發通知;後台也沒有完成重新同步。

為什麼 CP003-005 沒有一起變成「無法使用」?

Branch log 明確記錄:005 當時的 currentTransactionId=865,觸發既有交易保護,因此略過不可用狀態的覆寫。這可以解釋為什麼同屬 CP003,只有 001、004、008 受到本次覆寫影響;但單靠這個交易指標,不能推論 005 當時一定有實際供電。

5. 原因分析:目前有兩個缺口

5.1 缺口一:Branch 沒有把其他有效 OCPP 訊息納入存活判斷

現行 watchdog 主要查看:

  • 最後 Heartbeat:lastHeartbeat。
  • 最後 BootNotification:lastBootNotification。
  • 兩者是否都超過離線門檻;現場門檻為 330 秒。

這個判斷會漏掉一種情況:CP 沒有新 Heartbeat,但剛剛確實透過同一條連線送來 StatusNotification 或 MeterValues。

本案在 06:08:42~50 收到狀態,06:11:56 就判離線,中間約三分鐘,仍在 330 秒範圍內。Branch 卻沒有使用這份新的通訊證據,而是依較舊的 Heartbeat/Boot 時間執行離線處理。

5.2 缺口二:連線恢復後,Connector 狀態沒有重新同步

Branch 將 Connector 改成 UNAVAILABLE,是後台自行做的離線處理,並不代表 CP 設備端也把自己的狀態改成 UNAVAILABLE。

因此,可能出現:

  • CP 自己一直是 AVAILABLE。
  • Branch 保存的是 UNAVAILABLE。
  • CP 後來繼續送 Heartbeat,但 Heartbeat 沒有 Connector 狀態。
  • CP 沒有發生新的設備狀態變化,也就沒有再次自然送出 StatusNotification。
  • Branch 的舊狀態因此一直保留。

所以本單所說的「補送設備狀態」,是重新請 CP 回報目前狀態,讓 Branch 有實際依據更新紀錄,並不是認定 CP 在 06:08 沒有回報過。

5.3 已確認與尚未確認的界線

已確認:狀態回報成功、Branch 後續以 heartbeat stale 覆寫、心跳恢復後狀態仍未同步。

尚未確認:

  • 造成 WebSocket pong timeout 的最底層原因,例如通訊延遲或程式處理阻塞。
  • A17 CP003 當時實際執行的 JAR 是否包含 #1456 全部修正;本次尚未比對正式 artifact。
  • 三支實際啟動充電後的物理行為;本次僅唯讀查核。

這些待查項目不能先寫成已證實的根因。

6. OCPP 1.6 規格如何要求

本單以專案保存的 OCPP 1.6 Edition 2 與 Errata 為依據。SHALL 表示規格要求必須遵守;SHOULD 表示原則上應遵守的建議;MAY 表示允許。

6.1 CP 要主動回報 Connector 狀態

依 §4.9 與 Errata §3.19,狀態變更時,CP 必須主動送出 StatusNotification,並考慮最短狀態持續時間。

依 Errata §3.22,BootNotification 被 CS 接受後,CP 必須回報 connectorId 0 及所有 Connectors 的目前狀態;connectorId 0 代表 CP 本體。

依 §4.9,若離線期間狀態有改變,重連後應回報目前狀態。但規格沒有要求在狀態完全不變時,每隔固定時間重送所有 Connector 狀態。因此不能只因 06:13 後沒有新通知,就判定 CP 違反「固定週期回報 Connector 狀態」的義務。

6.2 Branch 不應只靠 Heartbeat 判定是否仍有通訊

依 §4.6,若 CP 已在 Heartbeat interval 內送出其他 OCPP 訊息,允許省略該次 Heartbeat;CS 應將收到其他訊息視為仍有通訊的證據。

套用到本案,Branch 剛收到 StatusNotification,這也是一份有效通訊證據。修正時應另外保存「最後有效 OCPP 通訊時間」,而不是把它冒充成真正收到 Heartbeat 的時間。

6.3 Branch 可以主動要求最新狀態

依 §5.17,CS 可透過 TriggerMessage,要求 CP 送出 StatusNotification。但必須區分:

  • CP 回覆 Accepted:只表示接受這次要求。
  • Branch 收到後續 StatusNotification:才取得該 Connector 的實際狀態。

設備可能不支援、拒絕或逾時,不能在沒有實際通知時直接把 Connector 改成可用。

原始文件位置:

  • documents/OCPP_1.6_documentation/ocpp-1.6 edition 2.pdf。
  • documents/OCPP_1.6_documentation/ocpp-1.6-errata-sheet.pdf。

7. 本次要怎麼修改

以下為待確認的實作設計;本單尚未完成程式修改或部署。

7.1 增加「最後有效 OCPP 通訊時間」

建議在 e_charge_points 新增可為空的 last_ocpp_message_at 欄位。

用途是保存 Branch 實際收到有效 OCPP 訊息的時間。例如收到 StatusNotification、MeterValues 或有效的指令回覆時,都能建立新的通訊證據。Heartbeat 欄位仍只記錄真正的 Heartbeat,避免日後查 log 時無法分辨訊息來源。

必須限制證據來源:

  • 訊息必須來自該 CP 目前有效的連線。
  • 使用 Branch 的接收時間,不使用設備 payload 裡可能過舊或錯誤的時間。
  • 舊連線延遲送達的事件、格式錯誤訊息,以及 Branch 自己送出的指令,不能拿來延長 CP 的在線時間。
  • 不因收到未知 CP 的訊息而任意建立設備資料。

資料庫變更需提供可重複執行的 migration。既有資料不以部署當下時間回填,避免把離線設備假裝成剛有通訊。

7.2 修改 watchdog,防止把新狀態覆寫成不可用

Watchdog 應一起檢查最後 Heartbeat、BootNotification,以及有效 OCPP 通訊時間。

例如:最後 Heartbeat 已超過 330 秒,但兩分鐘前有收到有效 MeterValues,則不能只因 Heartbeat 過舊就判定設備離線。

另外,檢查與寫入之間可能剛好收到新訊息。因此必須保留現有加鎖後重查機制:準備寫入 OFFLINE 前,再確認最新通訊時間,避免使用數秒前的舊查詢結果覆寫新狀態。

真正沒有通訊、或目前連線確實關閉時,仍要正常執行離線處理;既有未完成交易的保護也要保留。

7.3 通訊恢復後,重新取得 Connector 的真實狀態

對因離線而被 Branch 標成 UNAVAILABLE 的 Connector,通訊恢復後安排狀態同步。也要涵蓋本次已經卡住的情況:CP 已 ONLINE,但仍有離線處理留下的 UNAVAILABLE。

建議使用標準 TriggerMessage(StatusNotification),請 CP 重新回報。同步動作必須在背景執行,不能卡住接收 OCPP 訊息的執行緒,否則可能連 CP 的回覆都收不到。

收到實際通知後,依原本的狀態處理流程更新:

  • CP 回報 AVAILABLE,就更新為可用。
  • CP 回報 FAULTED,就保留實際故障。
  • CP 回報 CHARGING,就依既有充電/交易規則處理。
  • CP 回報 UNAVAILABLE,也應視為設備真的回報不可用,不能為了讓列表恢復而強制改成 AVAILABLE。

此同步只處理狀態,不應開關繼電器、啟停充電、清除交易,或呼叫具有這些副作用的完整設備 Recovery 流程。

7.4 同步失敗要有明確結果,不能無限重試

同一 CP/連線只能有一組進行中的同步工作,避免每收到一筆 MeterValues 就再發一次要求。

需要處理:

  • CP 不支援 TriggerMessage。
  • CP 回覆 Rejected。
  • 指令沒有回覆。
  • CP 回覆 Accepted,但後續沒有送出 StatusNotification。
  • 同步途中再次斷線,之後由新連線接手。

每種情況都要有可追查的 log、逾時與重試上限。尚未取得真實狀態時保留未同步的事實,不假造成功。

8. 與 #1436、#1456 的關係,以及本單範圍

議題 已處理的內容 與本單的差別
#1436 Branch 除 Heartbeat 外,也考慮近期 BootNotification,提供重連後的寬限。 本案重連時 Boot 被冷卻機制略過,且有效 StatusNotification 尚未納入判斷。
#1456(已關閉) CP 重連後立即送 Heartbeat,成功後重新回報 Connector 實際狀態。 該次明確未修改 Branch watchdog;本單補 Branch 對其他有效 OCPP 通訊的判斷與恢復同步。
本單 #1517 修正 Branch 存活判定與 Connector 狀態恢復,補上本次事故的回歸驗證。 同時盤點 A17 各 CP instance 的 #1456 修正版是否確實部署。

本單主要修改 java/ems_branch。A17 有 CP001、CP002、CP003 多個 instance,部署驗收時要逐一核對,不能只因 CP001 已更新,就推定 CP003 也是同一版本。

本單不包含重寫 MeterValues 佇列,也不承諾解決尚未查明的 pong timeout 底層原因。正式環境的即時復原、服務重啟與部署,要依後續核准的步驟執行;本次診斷尚未做這些操作。

9. 修改後應如何驗收

每個案例都要同時核對 OCPP 訊息與後台保存的狀態,不能只看到 HTTP 200、容器執行中,或 CP 為 ONLINE 就算通過。

案例 測試情境 預期結果
近期有狀態回報 Heartbeat/Boot 已舊,但在離線門檻內收到 StatusNotification。 不誤判離線,也不把剛回報的狀態覆寫為 UNAVAILABLE。
近期有電表回報 Heartbeat/Boot 已舊,但仍持續收到有效 MeterValues。 通訊被視為仍有活動;Connector 狀態不因舊 Heartbeat 被改成不可用。
真正通訊逾時 所有存活證據都超過門檻,或目前連線確實關閉。 正常執行離線處理,保留既有交易保護。
查詢與寫入交錯 Watchdog 先查到候選設備,但寫入前剛收到新訊息。 加鎖後重查可看到新證據,取消過時的離線寫入。
舊連線或無效訊息 重連後舊連線仍有延遲事件,或收到格式錯誤內容。 不延長目前連線的存活時間,不污染設備狀態。
離線後恢復可用 Branch 已因離線標成 UNAVAILABLE,CP 恢復後回報 AVAILABLE。 Branch 根據實際回報恢復為可用。
離線後恢復但仍故障/充電 CP 恢復後回報 FAULTED 或 CHARGING。 真實狀態原樣處理,不一律改成 AVAILABLE,交易不被誤清除。
設備明確回報不可用 CP 回報 UNAVAILABLE。 保留設備真實不可用,不與後台殘留的離線狀態混淆。
接受指令但未回報 TriggerMessage 回覆 Accepted,卻一直沒有後續狀態通知。 到期記錄同步未完成,不假裝已恢復。
不支援、拒絕或無回覆 NotImplemented、Rejected、timeout。 有明確紀錄及有界處理,不無限重試或產生指令風暴。
同步途中再次重連 前一批要求尚未完成,CP 已換新連線。 舊連線的回覆/排程不影響新連線,同一時間不重複發起多批同步。
A17 原事故重播 重現 Boot cooldown、先回報 AVAILABLE、watchdog 判定、較晚 Heartbeat 的先後順序。 修正前能重現問題;修正後不誤覆寫,已離線者也能依實際通知恢復。

現場驗收另需確認 A17 CP001/002/003 的版本與行為,並確認狀態同步過程沒有造成繼電器操作、充電啟停或交易異動。

10. 測試目錄與執行安排

既有案例需更新:

  • OCP-001:離線判定及交易保護。
  • OCP-007:watchdog 存活證據與加鎖後重查。
  • OCP-008:新舊連線交錯。
  • REL-005:部署後 OCPP 通訊與狀態驗證。

新增回歸重點:

  • P0:Heartbeat 過舊,但近期其他 OCPP 訊息仍能防止誤判。
  • P0:watchdog 已先標成離線後,恢復真實 Connector 狀態且不改變供電或交易。
  • P1:舊連線/無效訊息不能刷新存活。
  • P1:狀態同步不支援、拒絕、逾時或只有 Accepted 時,不假成功也不無限重試。

案例在 OCPP 訊息處理、watchdog、session、重連、恢復同步、資料庫欄位或相關部署變更時執行。發版測試採 Major/OCPP 範圍:所有適用 P0、P1,以及受影響 P2。

目前分支的 OCP-018 已用於 #1459 的 Fortune 案例,與 #1456 歷史文件的編號有差異。新增時必須取目前目錄未使用的 ID,不得覆寫既有案例。需要實機或特定廠商的案例,在完成前保留 Gap/Conditional,不以單元測試通過替代。

11. 目前進度與交付資料

已完成:

  • A17 正式環境唯讀查核與事件時序整理。
  • 比對本地 OCPP 1.6 原始規格與 Errata。
  • 建立本 ticket,優先級 High。
  • 從最新 origin/main(4b0e412)建立獨立分支 feature/redmine-1517-ocpp-liveness。
  • 完成實作規劃,列出預計變動檔案、migration、風險及測試設計。
  • 既有 E2E 目錄格式檢核通過;這僅表示目錄格式正確,不代表本單修正或測試已通過。

相關文件:

  • 查核報告:test_report/20260926_001_a17_cp003_unavailable_readonly.md。
  • 實作規劃:documents/20260926/redmine-1517-implementation-plan.md。
  • Ticket 快照:redmine-tickets/1517.md。

2026-09-26 11:33:20 已依 Ken 指示完成 A17 三支的單次現場復原;永久修正的程式修改、整批測試與部署尚未完成。 本次採 SSH/MySQL 維運方式,依已鎖定的 edge AVAILABLE、最新電表資料與交易/命令檢查結果,直接校正 Branch 三筆 e_connectors;不是 CP 補送 StatusNotification。11:34:16 獨立複查確認三支 Branch/edge 均為 AVAILABLE、無交易,CP003-005 與 CP003-004 原離峰隊列未變動,沒有重啟或操作充電。由於未經應用事件流程,既有畫面可能需要重新整理。本次是現場資料復原,#1517 仍需完成永久修正。復原報告:test_report/20260926_002_redmine-1517-a17-status-recovery.md。

Ken 已明確要求本案不使用瀏覽器,未經其同意不得使用 Computer Use。後續實作仍依已列出的規劃確認及測試啟動流程進行。

是由 陳國瑋 於 5 天 前更新

收案與實作規劃已完成,待確認

  • 已從最新 origin/main(4b0e412)建立獨立 worktree 與分支 feature/redmine-1517-ocpp-liveness,完成 git pull --ff-only;原工作目錄既有變更保持原樣。
  • 規劃文件:documents/20260926/redmine-1517-implementation-plan.md,包含預計變動檔案、資料庫 migration、測試與發版風險。
  • 核心設計:新增 nullable last_ocpp_message_at,保留真實 Heartbeat 語意;有效 current-session 入站訊息刷新存活;watchdog query/row-lock 重查一併納入;離線恢復或既有 stale UNAVAILABLE 由非阻塞、有限重試的 TriggerMessage(StatusNotification) 協調器重新取得真實狀態。Accepted 不視為同步完成,必須收到實際狀態。
  • 保留 active transaction、真實 FAULTED/CHARGING、session race 保護;不觸發 relay、充電啟停、完整 Recovery 或資料清理。
  • E2E impact:Update OCP-001/007/008、REL-005;Add P0 非 Heartbeat 存活與 watchdog-first recovery,以及 P1 invalid/old-session、unsupported/timeout 回歸。Release pack 為 Major/OCPP。
  • 現有分支 OCP-018 已由 #1459 使用,與 #1456 歷史編號不同;新增案例將取現有空號,不覆寫。
  • Catalog validator PASS(178 cases);目前 Catalog 未修改,未執行測試計畫、未修改 production code、未部署。
  • 依專案 SOP 階段 2 等待 Ken 確認規劃後開始實作。

是由 陳國瑋 於 5 天 前更新

是由 陳國瑋 於 5 天 前更新

是由 陳國瑋 於 5 天 前更新

A17 現場狀態已復原(2026-09-26 11:33:20,Asia/Taipei)

依 Ken 明確指示,先恢復 CP003-001/004/008 的正確狀態。

  • 修改前:Branch 三支都是 UNAVAILABLE / OCPP heartbeat stale;edge 三支 AVAILABLE、電表資料新鮮、無未完成交易或進行中的遠端啟停命令。
  • 方法:SSH/MySQL 維運校正,先備份、在同一 transaction 鎖定相關紀錄並重新核對條件,僅 eligible_count=3 且 updated_count=3 時 COMMIT。更新狀態取自 edge,info 明確記錄人工 reconciliation #1517;沒有偽造 OCPP 訊息。
  • 結果:11:33:20 三支恢復 AVAILABLE / NOERROR;11:34:16 另開連線複查,Branch 與 edge 三支一致、無交易。
  • 沒有重啟 CP 或 Branch,沒有操作 relay/充電啟停,沒有變更交易。CP003-005 的既有 Branch 交易 865 保持原樣;004 原有 OFF_PEAK / eligible 隊列未變。
  • 限制:本次沒有走 StatusNotification handler,不宣稱推送 WebSocket/RabbitMQ;列表重新載入可取得 DB 新狀態。未用瀏覽器驗證畫面,未做實際充電測試。
  • 這是單次現場復原,永久修正尚未實作,ticket 保持開啟。
  • 報告及 before/SQL/result/after 證據:test_report/20260926_002_redmine-1517-a17-status-recovery.md;test_report/evidence/1517-recovery/。
  • Ken 操作限制:本案不用瀏覽器,未經其同意不得使用 Computer Use。
  • Catalog:此次人工復原無目錄變更,validator PASS;未執行 release pack/實體 E2E,不消除永久修正的 Gap/Conditional。

是由 陳國瑋 於 5 天 前更新

  • 狀態 從 New 變更為 In Progress

已依 Ken 指示開始實作。範圍為 Branch 有效 OCPP 入站存活證據、watchdog 重查與 Connector 真實狀態恢復;不使用瀏覽器或 Computer Use,不操作 A17 充電或部署。

是由 陳國瑋 於 5 天 前更新

首版實作完成,進入測試啟動等待

已在 feature/redmine-1517-ocpp-liveness 完成 Branch 首版實作:

  • 新增 e_charge_points.last_ocpp_message_at,保存目前 WebSocket session 的合法 inbound OCPP PDU 接收時間;不改寫或偽造 last_heartbeat。
  • Watchdog 候選查詢與 row-lock 重查均納入 Heartbeat、BootNotification、最後合法 OCPP PDU;任一證據在 cutoff 內即取消離線覆寫。
  • 已被新連線取代的舊 session 訊息不再進入 handler,也不能刷新存活或改寫 connector。
  • 離線投影後,下一筆合法 inbound PDU 會非阻塞送出 TriggerMessage(StatusNotification);同一 session 去重,預設 response timeout 30 秒、notification timeout 60 秒、最多 3 次、重試間隔 60 秒。
  • Accepted 只表示設備接受要求;Branch 必須收到實際 StatusNotification 才更新狀態。流程不操作 relay、不啟停充電、不清交易,也不直接改 queue。
  • 新增可重跑且不相容 schema fail-fast 的 migration:patch_20260926_redmine_1517_last_ocpp_message.sql。
  • E2E catalog 更新 OCP-007、OCP-008,新增 OCP-019;validator 通過:179 cases(P0=56、P1=71、P2=47、P3=5)。

目前驗證:

  • mvn -DskipTests package:PASS,production 與 test sources 均編譯成功。
  • 依 SOP 僅執行一個隔離 unit test method:1/1 PASS,確認其他合法 OCPP PDU 只更新獨立存活時間與 connection,不偽造 Heartbeat、不覆寫 FAULTED 等運作狀態。
  • 尚未執行整批 unit、integration、隔離 DB migration、simulator、A17 實機 E2E 或部署。

完整紀錄:test_report/20260926_003_redmine-1517-implementation.md。下一步依 SOP 先列出測試 command、範圍與環境風險,等待 Ken 明確下達「開始測試」。

是由 陳國瑋 於 4 天 前更新

相關但獨立的交易收斂問題

A17 CP003-005 無法再次充電的原因,已確認不是 #1517 所處理的 Connector 離線狀態殘留,而是交易 865 的 StopTransaction 在斷線與訊息 backlog 期間未送達 Branch;CP 重試三次後停止補送,造成 Branch 保留 ACTIVE 殭屍交易及 current_transaction_id=865。

此問題已另外建立 #1518 追蹤 Start/StopTransaction 優先補送、重連後重新排程、重試耗盡後收斂,以及 Branch 端安全對帳。

2026-09-27 已先依 CP 本機 COMPLETED 交易資料完成 CP003-005 的受控現場復原。Branch 交易 865 已收斂為 COMPLETED,Connector 的 current transaction 已清除;執行後確認 Branch/CP 均無 ACTIVE transaction,Connector 兩端皆為 AVAILABLE。

#1517 的程式實作依 Ken 指示維持暫停,避免把兩個根因混在同一張票處理。

是由 陳國瑋 於 4 天 前更新

2026-09-28 A17 已先在線套用共用 schema patch patch_20260928_redmine_1517_last_ocpp_message.sql。

執行內容:

  • 以 ALGORITHM=INPLACE, LOCK=NONE 新增 e_charge_points.last_ocpp_message_at DATETIME(6) NULL
  • 新增索引 idx_last_ocpp_message_at
  • patch 已重跑驗證,第二次執行為 no-op,確認可重複執行

執行期間未重新啟動 Branch 或 CP。A17 的 transaction 878 持續為 ACTIVE、Connector 維持 CHARGING,CP003 維持 OCPP ONLINE 且 heartbeat 正常。

目前正式環境的 Branch JAR 尚未包含 #1517 程式變更,因此 last_ocpp_message_at 目前仍為 NULL 是預期結果;要開始寫入此欄位,仍須等維護窗口部署 #1517 JAR 並重新啟動 Branch。

A17 主機執行證據:
/opt/ems/deployments/20260928-000830-redmine-1517-schema/

A17 是先行案場。其他案場部署 #1517 JAR 前,仍須各自套用同一個共用 patch 檔;檔名日期 20260928 是共用 migration 的發布/排序日期,不應依各案場實際施作日期重新命名。

動作

匯出至 Atom PDF