Feature #1397 » redmine-1382-driver-state-offpeak-requirements-zh-TW.md
Redmine #1382 車主狀態與離峰充電需求規格
狀態:需求審查草稿
日期:2026-07-29
範圍:Branch/HQ API 契約與 LIFF 端到端行為。本文件尚未授權進入實作。
1. 目標
driverState 必須描述車主目前實際面對的情況,以及現在可以執行的操作。它不能只是 raw OCPP Connector status 的中文翻譯。
本次設計需要保留 #1382 之前的使用者體驗,同時正確處理:
- 公樁與私樁。
- 手動充電與長期離峰充電。
- 私樁 Charge Group slots 與排隊。
- CloudLink 與 Fortune 的廠牌差異。
- RemoteStart/StartTransaction 與 RemoteStop/StopTransaction 的非同步流程。
- OCPP 離線、故障、服務重啟、逾時與晚到事件。
- 共用 WebSocket 狀態與個別使用者的 API 授權。
2. 系統責任邊界
2.1 Branch
Branch 是下列資料的唯一判斷來源:
-
driverState。 -
driverState.actions所提供的操作能力。 - Remote operation 的生命週期。
- 手動排隊與離峰排程狀態。
- Command API 最終的狀態檢查與使用者授權。
- 車主可理解的操作結果與目前阻擋原因。
Branch 必須綜合判斷:
- raw Connector status。
- OCPP connection status。
- Branch 與 CP 的 active transaction。
-
e_connector_priority。 - 長期離峰設定。
- 已持久化的 RemoteStart/RemoteStop operation。
2.2 HQ
HQ 必須:
- 從 LINE 身分取得已驗證的車主。
- 將可信任的 Branch user identity 傳給 Branch。
- 原樣傳遞 Branch 的
driverState與 operation result,不建立第二套狀態機。 - WebSocket initial data 與後續 connector event 都使用同一份 Branch presentation。
HQ 不得信任 LIFF 任意傳入的 userId。
2.3 LIFF
本次 Backend 工作不修改 FE 程式碼,但 API 必須提供 FE 完成需求所需的資訊。
LIFF 負責:
- 顯示 Branch 提供的 title、description 與 actions。
-
areaType=public時不顯示離峰 switch。 - 發送 command,並顯示結構化的成功或拒絕結果。
- WebSocket 連線正常時才允許操作。
- 在指定情境顯示確認 modal。
當 driverState 存在時,LIFF 不得再用 raw status 推導是否可以充電。
3. 領域名詞
3.1 公樁(PUBLIC Connector)
- 不參與私樁 rotation queue。
- 不顯示離峰 switch。
- 合法的公樁使用者不需要經過私樁 Charge Group 排隊即可要求啟動。
- Charge Group 計算 slots 時,已預先保留公樁容量。
- 公樁正在充電時,只有該 Transaction 的使用者可以停止;最終由 Command API 判斷。
範例:
Charge Group 實體總容量 = 7 slots
PUBLIC Connector = 2
PRIVATE 可排程容量 = 5 slots
公樁 slot 是依照設定在 Charge Group 內的公樁數量保留,不會因公樁目前離線、故障或未充電而暫時釋放給私樁。
3.2 私樁(PRIVATE Connector)
- 透過
e_connector_user與一位或多位 Branch user 關聯。 - 參與 Charge Group slot allocation 與 rotation queue。
- 支援長期離峰設定。
- 目前仍與該 Connector 關聯的任一住戶,都可以停止私樁充電、取消手動排隊、取消離峰等待,或取消廠牌支援的 PREPARING。
- 即使 Transaction 或離峰模式由另一位關聯住戶建立,也必須記錄真正執行停止或取消的人。
現有程式中的 owner 用語並不精確。Connector 目前只有「關聯住戶」,沒有正式的 owner role。
3.3 離峰充電
離峰充電是長期偏好,不是單次 ChargingRequest。
-
enableOffPeak=true表示 Connector 會持續參加未來的離峰時段。 - 開啟離峰時,必須記錄是哪一位關聯住戶開啟。
- 只有進入適用離峰時段、scheduler 實際評估後,才建立 queue record。
- 完成充電、暫時故障/離線,或目前 window 被抑制時,長期偏好仍維持開啟。
- 關閉離峰必須是明確的使用者操作。
3.4 離峰 window
一段連續的 tariff OFF_PEAK 區間,就是一個 window。
- 跨越午夜但時間連續,仍屬同一個 window。
- 同一天兩段不連續的 OFF_PEAK 區間,屬於兩個 window。
- Current-window suppression 到該連續 OFF_PEAK 區間結束時失效。
- 離峰時段結束只影響「是否可自動開始」,不能強制停止已經進行中的 Transaction。
4. DriverState 核心規則
Raw OCPP PREPARING 不等於 driverState=PREPARING。
只有 Branch 已送出 RemoteStart,
而且仍在等待 StartTransaction 時,
driverState 才是 PREPARING。
這項規則用來保留「先插槍、再開 App」的體驗:
| 廠牌 | 已插槍但未送 RemoteStart | Raw status | 手動模式 driverState |
|---|---|---|---|
| Fortune | 是 | 通常為 PREPARING
|
READY |
| CloudLink | 是 | 通常為 AVAILABLE
|
READY |
在離峰模式下,同樣只是插槍但尚未 dispatch 的 Connector,應依 Priority 是否真的存在顯示 OFF_PEAK_WAITING 或 QUEUED。
5. DriverState codes
| Code | 車主語意 | 主要操作 |
|---|---|---|
READY |
沒有 active transaction、queue 或 remote operation,可手動開始 | 開始充電 |
OFF_PEAK_WAITING |
長期離峰已開啟,但目前不在可派發 queue 中 | 關閉離峰/取消等待 |
QUEUED |
已存在真正的手動或離峰 queue record,等待派發 | 取消對應來源的排隊 |
PREPARING |
RemoteStart 已送出或已接受,等待 StartTransaction | 廠牌支援時可取消啟動 |
CHARGING |
Branch 或 CP 有 active transaction | 停止充電 |
FINISHING |
RemoteStop 已送出或已接受,等待 StopTransaction | 不可重複停止 |
OFFLINE_CHARGING |
OCPP 離線,但 Branch/CP 證據顯示可能仍在充電 | 不可遠端操作 |
OFFLINE_UNAVAILABLE |
OCPP 離線,且沒有 active transaction 證據 | 不可開始或停止 |
FAULTED |
Connector 故障,且沒有更強的 active transaction 狀態 | 不可開始充電 |
UNAVAILABLE |
Connector 因其他原因不可用 | 不可執行充電 command |
UNKNOWN |
Branch 無法安全判斷 | 不可執行充電 command |
BLOCKED、PAUSED、ELIGIBLE、NOT_PLUGGED 等 ConnectorPriority 內部狀態,不應直接變成公開的 driverState code。
6. 狀態優先順序
實作可以使用 decision service 或狀態機,但必須遵守以下規則:
- 只要存在 active transaction 證據,就不能顯示
READY。 - 未完成的 STOP operation 顯示
FINISHING。 - 未完成的 START operation 顯示
PREPARING。 - OCPP 離線且沒有 active transaction 時,顯示
OFFLINE_UNAVAILABLE。 - OCPP 離線但有 active transaction 證據時,顯示
OFFLINE_CHARGING。 -
FAULTED/OCPP offline 不得被OFF_PEAK_WAITING或QUEUED遮蔽。 - 真正且適用的 queue record 才可顯示
QUEUED。 - 長期離峰已開啟、但尚無適用 queue record 時,顯示
OFF_PEAK_WAITING。 - Fortune raw
PREPARING若沒有 RemoteStart operation,回到對應的手動或離峰狀態。
7. Actions
API 應提供具備明確業務語意的 action,FE 不應再從 start/stop label 猜測用途。
建議 action code:
START_CHARGINGSTOP_CHARGINGCANCEL_STARTCANCEL_MANUAL_STARTDISABLE_OFF_PEAK
每個 action 至少提供:
{
"code": "CANCEL_START",
"enabled": true,
"label": "取消啟動",
"disabledMessage": null,
"requiresConfirmation": true
}
現有 start/stop 欄位可暫時保留做相容,但它們無法區分:
- 取消手動 queue。
- 關閉長期離峰。
- 取消仍在等待 StartTransaction 的啟動。
WebSocket 中的共用 actions 表達設備與流程能力,不代表目前使用者一定有權執行。Command API 仍需做最後授權。
8. 手動充電流程
8.1 可立即開始
READY
-> 車主要求 START_CHARGING
-> RemoteStart operation SENT/ACCEPTED
-> PREPARING
-> 收到 StartTransaction
-> CHARGING
8.2 私樁 slots 已滿
READY
-> 車主要求 START_CHARGING
-> PRIVATE slots 已滿
-> 建立 MANUAL queue request
-> QUEUED
Queue 必須保存:
source = MANUAL
requestedByUserId = 原始要求開始的車主
Slot 釋放後,scheduler 必須使用原始 requester 的 IdTag dispatch,不能再選 Connector 關聯住戶中的第一人。
CANCEL_MANUAL_START 只刪除手動 queue,不得修改 enableOffPeak。
8.3 手動啟動失敗
- 手動 RemoteStart 不自動重試。
-
REJECTED、FAILED或最終TIMED_OUT後回READY。 - 失敗結果與目前 driverState 分開回傳。
- 如果 timeout 後仍收到晚到的 StartTransaction,實際 Transaction 優先,driverState 改為
CHARGING。
9. PREPARING 行為
以下 operation status 都顯示 PREPARING:
SENTACCEPTED
廠牌取消能力:
| 廠牌 | PREPARING action |
|---|---|
| CloudLink |
CANCEL_START 可用;Branch 可執行既有的 waiting-mode exit 流程 |
| Fortune |
CANCEL_START 不可用,並提供原因;車主需拔槍或等待 timeout |
取消成功後:
- 手動來源回
READY。 - 離峰來源同時關閉長期離峰、移除相關 Priority,回到手動模式。
RemoteStart 明確收到 Rejected:
- 手動來源回
READY。 - 離峰來源停止本 window 重試,回
OFF_PEAK_WAITING。 - reason 使用
START_REJECTED_FOR_CURRENT_WINDOW。 - 下一個獨立 off-peak window 可以重新排程。
RemoteStart 沒有回應:
- 在廠牌 start deadline 之前維持
PREPARING。 - Operation 未完成期間不得盲目重送。
- 離峰的 transient timeout 可回
QUEUED,在之後正常 scheduler cycle 重試。 - 同一 Connector 不得同時存在重疊 START operation。
- 目前 window 結束後停止重試。
10. CHARGING 與 FINISHING
CHARGING
-> 車主確認 STOP_CHARGING
-> RemoteStop operation SENT/ACCEPTED
-> FINISHING
-> 收到 StopTransaction
-> Transaction 完成
FINISHING 期間:
- Start 停用。
- Stop 停用。
- Off-peak switch command 由 API 拒絕。
- Branch 重啟後必須從持久化 operation 還原 FINISHING。
RemoteStop 沒有回應時:
- Stop deadline 以前保持
FINISHING。 - 不自動重送 RemoteStop。
- 期間收到 StopTransaction 就正常完成。
- Deadline 到期時重新查實際 Transaction。
- Transaction 仍為 ACTIVE:operation 標記
TIMED_OUT,driverState 回CHARGING,顯示失敗並允許新的明確停止要求。 - Transaction 已完成:視為晚到或對應延遲,進行成功 reconciliation。
離峰 current-window suppression 只有在 Transaction 確認停止後才生效。
11. 長期離峰流程
11.1 開啟離峰
私樁 off-peak ON 成功後立即:
enableOffPeak = true
enabledByUserId = 已驗證的關聯住戶
driverState = OFF_PEAK_WAITING
API 不等待 e_connector_priority 建立才回應。
11.2 進入適用離峰時段
Scheduler 在適用 window 評估 Connector 後:
建立或更新 source=OFF_PEAK 的 Priority
driverState = QUEUED
OFF_PEAK_WAITING 與 OFF_PEAK QUEUED 都提供 DISABLE_OFF_PEAK,LIFF 顯示「取消排隊」。
11.3 尚無充電需求
若 dispatch 後沒有建立充電需求:
driverState = QUEUED
reason = NO_CHARGING_DEMAND
這是中性狀態,不是錯誤。Description 不得暗示「充電槍沒有正確連接」。
因為車輛可能稍晚才到,scheduler 可以在同一 window 的後續正常 cycle 再試。
11.4 已開始充電
收到 StartTransaction:
driverState = CHARGING
SUSPENDED_EV 與 SUSPENDED_EVSE 仍屬 charging-like,因為 Transaction 還是 ACTIVE。此時不得建立另一筆 RemoteStart。
11.5 車主停止離峰充電
LIFF modal 必須清楚告知:
- 將停止目前的 active transaction。
- 本次離峰 window 不會再自動啟動。
- 長期離峰偏好不會因此關閉。
收到 StopTransaction、確認停止後:
enableOffPeak = true
driverState = OFF_PEAK_WAITING
reason = USER_CANCELLED_FOR_CURRENT_WINDOW
車主若要在同一 window 重新加入排程,必須先將離峰 switch OFF,再切回 ON。
11.6 Transaction 因其他原因結束
OCPP 1.6 沒有可靠的 FullyCharged StopReason,A17 也無法可靠區分滿電或拔槍:
- A17 MeterValues 沒有 SoC。
- CP stop detector 可能把持續低電流寫成
EVDisconnected。
因此 UI 不得宣稱「已充滿」或「已拔槍」。
如果本 off-peak window 內確實建立過 Transaction,之後收到 StopTransaction:
enableOffPeak = true
driverState = OFF_PEAK_WAITING
reason = TRANSACTION_ENDED_FOR_CURRENT_WINDOW
本 window 不再自動啟動,下一個 off-peak window 正常重新排程。
若只有 SUSPENDED_EV、沒有 StopTransaction,表示 Transaction 尚未結束,不適用本規則。
11.7 Current-window suppression
Suppression 必須持久化。原因是現有 scheduler 會在後續 cycle 重設非 CHARGING 的 Priority。
Suppression reason 至少包含:
USER_CANCELLED_FOR_CURRENT_WINDOWSTART_REJECTED_FOR_CURRENT_WINDOWTRANSACTION_ENDED_FOR_CURRENT_WINDOW
Suppression 一直維持到目前連續 OFF_PEAK tariff range 結束。
12. 離峰 switch command
12.1 FE 行為
- PUBLIC:不顯示 switch。
- PRIVATE 且 WebSocket 已連線:switch 可維持可點擊。
- WebSocket 斷線:不得使用舊 actions 或舊 switch state 發送 command。
FE 不維護複雜的 business-state enabled/disabled matrix。
12.2 API 是最終判斷者
Switch request 送出後,Branch 以最新資料驗證並回傳:
- 成功:實際
enableOffPeak、最新driverState,並發布 event。 - 拒絕:結構化 error code/message、未變更的實際
enableOffPeak、最新driverState。
API 拒絕以下操作:
- PUBLIC Connector。
- Active
PREPARING、CHARGING或FINISHING。 - 存在 MANUAL queue 時要求開啟 off-peak。
- 非合法關聯住戶。
- 永久或結構性的設定錯誤。
12.3 開啟時必須立即拒絕的情況
- Connector 不是 PRIVATE。
- 使用者不是目前關聯住戶。
- 沒有 Charge Group。
- 沒有有效 tariff 或 tariff 沒有 OFF_PEAK range。
- 開啟者沒有 IdTag。
- 開啟者的 IdTag 未授權。
12.4 不應阻止開啟的暫時情況
- 目前不在離峰時段。
- 目前沒有 slot。
- 沒有車或沒有充電需求。
- OCPP offline。
- Connector faulted。
12.5 開啟後資料發生變化
- 開啟者失去 Connector 關聯:關閉離峰、清除 Priority 與 enabled actor,不轉移給其他住戶。
- Connector 沒有任何關聯住戶:關閉離峰並清除 Priority。
- 開啟者 IdTag 之後失效,但仍保持關聯:保留長期偏好與 actor,暫停自動啟動,顯示原因;授權恢復後自動恢復排程。
- Tariff 之後失效或停用:保留長期偏好並暫停;有效設定恢復後自動恢復。
- Connector 從 PRIVATE 改成 PUBLIC:關閉離峰並清除相關狀態。
Charge Group 刪除保護另由 Redmine #1395 處理。
PUBLIC slot 設定 guard 與 runtime slots==0 防線另由 Redmine #1396 處理。
13. Queue 來源與取消語意
e_connector_priority 必須區分:
source = MANUAL | OFF_PEAK
requestedByUserId
| Queue 來源 | LIFF 顯示 | Command | 實際效果 |
|---|---|---|---|
MANUAL |
取消排隊 | CANCEL_MANUAL_START |
只刪除手動 request |
OFF_PEAK |
取消排隊 | DISABLE_OFF_PEAK |
enableOffPeak=false、刪除 Priority、清除 enabled actor 與 suppression |
現有語意不明確的 dequeue 行為不能再當作 source of truth。
Priority row 已 FINISHED 或已被 current-window suppression 抑制時,不能只因 row 還存在就顯示 QUEUED。
14. 使用者授權
14.1 共用 presentation
MQ/WebSocket 的 driverState.actions 是共用的設備與流程能力,不依每個 WebSocket session 個人化。
這可以避免 MQ 狀態產生器與個別使用者授權高度耦合。
14.2 Command API
Command API 必須重新檢查:
- 已驗證的使用者。
- Connector area 與住戶關聯。
- 目前 Transaction/request actor。
- 最新 operation 與 driverState。
- 最新 off-peak 與 queue 狀態。
- OCPP connection 與廠牌能力。
不允許的操作使用結構化 403/409 回應。
14.3 停止規則
- PUBLIC:只有 Transaction user 可以停止;其他使用者收到
TRANSACTION_OWNED_BY_OTHER_USER。 - PRIVATE:任一目前關聯住戶都可以停止;保留原 Transaction owner,並 audit
stopRequestedBy。 - PRIVATE queue/off-peak/PREPARING:任一目前關聯住戶都可以取消,並 audit
cancelledBy或disabledBy。
15. Remote operation 持久化
15.1 A17 現況
e_remote_transaction_log 已經會為每次 remote command 保存一筆資料。
A17 驗證結果:
-
START/SUCCESS:17,508 筆。 -
START/REJECTED:761 筆。 - 現有
SUCCESS只代表 RemoteStart.confAccepted,不代表已收到 StartTransaction。 - 即使後續真的建立 Transaction,現有
transaction_id仍可能是 NULL。
因此現有 row 適合擴充,但目前的 status 無法表達完整 operation lifecycle。
15.2 決定方向
優先擴充 e_remote_transaction_log,不新增第二張 operation table;除非 implementation review 發現無法相容的外部限制。
保留現有 command response status,另外新增 business lifecycle status。
建議新增:
source MANUAL / OFF_PEAK
requested_by_user_id 實際已驗證的操作人
operation_status SENT / ACCEPTED / STARTED / STARTED_LATE /
REJECTED / TIMED_OUT / CANCELLED / FAILED /
STOPPED
deadline_at
completed_at
failure_code
transaction_id StartTransaction 對應成功後回填
需要支援的查詢:
- Connector 最新未完成 START。
- Connector/Transaction 最新未完成 STOP。
-
lastOperation所需的最新 operation result。 - 同一 Connector 最多只能有一筆適用的未完成 START;同一 Transaction 最多一筆未完成 STOP。
依 repository 慣例,使用普通 index 支援查詢;正確性由 service transaction 控制。若要新增 DB UNIQUE constraint,必須另外說明並取得同意。
15.3 生命週期
RemoteStart:
SENT -> ACCEPTED -> STARTED
| |
| +-> REJECTED / TIMED_OUT / CANCELLED / FAILED
+-> FAILED
RemoteStop:
SENT -> ACCEPTED -> STOPPED
| |
| +-> REJECTED / TIMED_OUT / FAILED
+-> FAILED
Branch 重啟後,依未完成 operation 與 deadline 還原 PREPARING/FINISHING。
舊資料沒有新增 lifecycle 欄位時,只視為歷史紀錄,不能拿來判定目前 operation。
16. Operation result API
目前狀態與最近一次操作結果必須分開。
範例:
{
"driverState": {
"code": "READY",
"title": "可開始充電",
"description": "充電樁已待命,可以開始充電",
"actions": [
{
"code": "START_CHARGING",
"enabled": true,
"label": "開始充電",
"disabledMessage": null,
"requiresConfirmation": false
}
]
},
"lastOperation": {
"operationId": "18456",
"type": "START_CHARGING",
"source": "MANUAL",
"status": "REJECTED",
"errorCode": "REMOTE_START_REJECTED",
"message": "充電樁未接受啟動指令",
"retryable": true,
"occurredAt": "2026-07-29T14:27:41",
"nextRetryAt": null
}
}
規則:
- 手動 command 的立即失敗由 command response 顯示。
- 離峰非同步失敗透過 WebSocket 傳送。
- 已恢復的 transient failure,之後重新開頁時不得顯示過期 modal。
- 尚未解除的永久問題,繼續反映在目前 driverState/reason。
-
operationId用於去重與事件對應。 - 實際 StartTransaction/StopTransaction 的事實優先於先前 timeout presentation。
17. WebSocket Connector 詳細頁
17.1 第一次開啟
- Connector 詳細頁不另外呼叫 REST detail API。
- Connector 資訊與
driverState由 WebSocket initial data 提供。 - 不使用 polling。
WebSocket initial connection 失敗時:
- 進行一次短時間 reconnect。
- 再次失敗就返回 Connector list。
- 顯示 modal,告知目前無法取得即時 Connector 資訊。
- 不使用 REST detail fallback。
17.2 已連線後斷線
- 立即停止使用舊
driverState.actions。 - 停用 Start、Stop 與 off-peak 操作。
- 嘗試 reconnect 一次。
- 只有收到新的 initial snapshot 後才恢復操作。
- Reconnect 失敗就返回 list 並顯示 modal。
18. 失敗與重試分類
18.1 手動來源
- 不自動重試。
- 明確通知車主操作結果。
- 回到最新且安全的 driverState。
18.2 可恢復的離峰失敗
- 不建立 immediate retry loop。
- 每個正常 scheduler cycle 最多嘗試一次。
- 不允許重疊 operation。
- 只有目前 off-peak window 仍適用時才可重試。
-
NO_CHARGING_DEMAND是中性狀態,可在同一 window 後續重試。 - Timeout 在沒有 suppression 時,可於之後 cycle 重試。
18.3 本 window 終止
- RemoteStart 明確
Rejected。 - 車主要求停止,且已收到 StopTransaction。
- 本 window 已建立 Transaction,之後 Transaction 結束。
以上狀態顯示 OFF_PEAK_WAITING,附帶 current-window reason;只有下一個 window 或車主明確 OFF -> ON 才重新加入。
18.4 永久/設定問題暫停
- 開啟後 IdTag 授權失效。
- 開啟後 tariff 失效或停用。
- 其他只靠等待不會成功的結構性問題。
依已確認規則保留長期偏好、停止重複 command,並提供目前可理解的 reason。
19. FE 必須能完成的畫面行為
雖然 FE 實作不屬於本 Backend 工作,但 API 必須支援:
- 依 semantic action 顯示 label。
- Operation-backed PREPARING 顯示「準備中」。
- Operation-backed FINISHING 顯示「停止中」。
-
OFF_PEAK_WAITING與 OFF_PEAKQUEUED都顯示「取消排隊」。 - 手動 queue cancellation 與 off-peak disable 使用不同 command。
- 停止 active off-peak charging 前顯示確認 modal。
- PUBLIC 不顯示 off-peak switch。
- PRIVATE switch command 交由 API 判斷,不在 FE 複製 business matrix。
- WebSocket 斷線時停用所有 operation。
- Command 被拒絕時顯示結構化 modal,且 switch/driverState 不做錯誤的 optimistic update。
20. 必要回歸測試範圍
本需求涉及使用者可見行為、API DTO、schema、queue、off-peak scheduler、OCPP 與 WebSocket。E2E Catalog impact 為 Add 與 Update。
後續 implementation plan 至少必須涵蓋:
- CloudLink 公/私樁手動 RemoteStart -> PREPARING -> CHARGING。
- Fortune 先插槍的 raw PREPARING,在 RemoteStart 前仍顯示 READY。
- PREPARING 取消:CloudLink 支援、Fortune 不支援。
- Branch 重啟後可還原 PREPARING 與 FINISHING。
- 私樁 slots full 的手動 queue 保存 requester 並可取消。
- Off-peak ON 在 Priority 建立前立即回 OFF_PEAK_WAITING。
- Off-peak Priority 顯示 QUEUED 並可執行 DISABLE_OFF_PEAK。
- NO_CHARGING_DEMAND 使用中性文案,且可在同一 window 後續重試。
- Off-peak RemoteStart 明確 Rejected 後抑制目前 window。
- 車主停止離峰,只有 StopTransaction 後才抑制目前 window。
- Transaction 結束後不再發生 A17 每 10 分鐘重送 RemoteStart。
- SuspendedEV 保持 active transaction,不建立另一筆 Start。
- RemoteStop pending 顯示 FINISHING 並阻止重複 Stop。
- Offline/fault 保留長期 off-peak,並阻止不安全 remote operation。
- PUBLIC Transaction stop 授權與 PRIVATE 關聯住戶 stop 行為。
- PRIVATE off-peak switch API 成功/拒絕都回實際狀態。
- WebSocket initial failure 與 established disconnect 不使用 stale actions。
- 晚到 StartTransaction/StopTransaction 以實際 Transaction 狀態完成 reconciliation。
Release pack 與 P0-P3 分級,等需求文件確認後在 implementation plan gate 決定。
21. 不在本次範圍
- FE source implementation。
- Charge Group 刪除 guard:Redmine #1395。
- PUBLIC slot 設定 guard 與 runtime
slots==0防線:Redmine #1396。 - 重新設計 raw OCPP ConnectorStatus enum。
- 宣稱 StopTransaction 能證明滿電或拔槍。
- 新增 polling。
22. Review gate
進入實作前:
- Ken 以本文件一次審查需求與狀態契約。
- 所有修正先更新至本文件。
- 另外產出 implementation plan,列出確切程式、schema、測試檔案與 E2E impact。
- Implementation plan 明確同意後才開始 coding。