# OCPP 1.6 工程師培訓手冊 ## 現場服務人員必備知識 --- ## 第一章:什麼是 OCPP?(概念性理解) ### 1.1 OCPP 的定位與目的 OCPP 全名是 **Open Charge Point Protocol**(開放式充電點協定),由 Open Charge Alliance (OCA) 組織制定。它解決了一個關鍵的產業問題:**不同廠牌的充電樁如何與不同廠商的管理平台互通?** 想像一下這個場景:如果每家充電樁廠商都使用自己專屬的通訊協定,那麼營運商就必須為每個品牌建置專屬的後台系統,這會造成巨大的成本和複雜度。OCPP 就是這個問題的解決方案——它定義了一套**通用語言**,讓任何支援 OCPP 的充電樁都能與任何支援 OCPP 的中央系統對話。 ### 1.2 通訊架構:兩個主角 OCPP 的通訊只涉及兩個角色: **Charge Point (CP) - 充電樁** 這是現場的物理設備,負責實際執行充電操作。它是「hands on the ground」——在地面上執行工作的設備。每台充電樁可以有一個或多個 **Connector(連接器/槍頭)**,每個 Connector 可以獨立服務一輛電動車。 **Central System (CS) - 中央系統/後台平台** 這是雲端或機房中的管理系統,負責:授權使用者身份、追蹤交易紀錄、監控設備狀態、下發控制命令。它是整個充電網路的「大腦」。 ``` ┌─────────────┐ ┌─────────────┐ │ │ OCPP 1.6 (WebSocket) │ │ │ Charge Point│◄────────────────────────────►│Central System│ │ (充電樁) │ 雙向通訊 │ (後台平台) │ │ │ │ │ └─────────────┘ └─────────────┘ ``` 📚 **引用:** ocpp-1.6 edition 2.pdf, Chapter 1 (Introduction) & Section 2.1 (Scope) ### 1.3 通訊方式:JSON over WebSocket OCPP 1.6 有兩種實作方式:SOAP/XML 和 **JSON over WebSocket (OCPP-J)**。現代實作幾乎都採用 JSON 版本,因為它更輕量、更適合嵌入式設備。 **關鍵特性:** **WebSocket 是持久連線**:不像傳統 HTTP 的「問一次答一次」,WebSocket 建立後會持續保持開啟,雙方都可以主動發送訊息。這很重要——因為 Central System 需要能夠主動向充電樁下達命令(例如遠端停止充電)。 **訊息是非同步的**:發送一個請求後,不需要等待回應就可以發送下一個請求。不過,每個請求最終都必須收到一個對應的回應。 📚 **引用:** ocpp-j-1.6-errata-sheet.pdf, Section 4.1.1 - 補充說明 Central System 可以同時對多台充電樁發送訊息,不需要等待前一台的回應。 ### 1.4 訊息的三種類型 OCPP-J 使用 JSON-RPC 風格的訊息框架,定義了三種訊息類型: | 類型編號 | 名稱 | 用途 | 範例 | |---------|------|------|------| | 2 | **CALL** | 發起請求 | `[2, "19223201", "BootNotification", {...}]` | | 3 | **CALLRESULT** | 成功回應 | `[3, "19223201", {...}]` | | 4 | **CALLERROR** | 錯誤回應 | `[4, "19223201", "NotSupported", "...", {}]` | 每個 CALL 訊息都有一個**唯一的 messageId**(最大 36 字元,通常使用 UUID),用來將請求和回應配對起來。 📚 **引用:** ocpp-j-1.6-errata-sheet.pdf, Section 4.1.4 & Section 3.7 - Message ID 必須在同一個充電站的所有 WebSocket 連線中唯一(包含重連後)。 ### 1.5 誰發起什麼訊息? 這是理解 OCPP 的關鍵概念。有些訊息是**充電樁主動發起**的,有些是**中央系統主動發起**的: **充電樁 → 中央系統(CP-initiated):** - BootNotification(開機通知) - Heartbeat(心跳) - StatusNotification(狀態通知) - Authorize(授權請求) - StartTransaction(開始交易) - StopTransaction(停止交易) - MeterValues(電表數值) **中央系統 → 充電樁(CS-initiated):** - RemoteStartTransaction(遠端啟動) - RemoteStopTransaction(遠端停止) - Reset(重設) - UnlockConnector(解鎖連接器) - ChangeConfiguration(更改配置) - GetConfiguration(取得配置) - TriggerMessage(觸發訊息) 📚 **引用:** ocpp-1.6 edition 2.pdf, Section 3.3 (Feature Profiles) - 此章節為「規範性 (normative)」而非「資訊性 (informative)」,依據 ocpp-1.6-errata-sheet.pdf Section 3.3 修正。 --- ## 第二章:充電樁連接平台的完整流程 ### 2.1 重要觀念:BootNotification 不只是「第一次」! 這是一個常見的誤解。很多人以為 BootNotification 只在充電樁第一次上線時發送一次,之後就不再發送。**這是錯誤的理解。** 根據規範和 Errata Sheet 的明確說明: > "After a restart (for instance due to a remote reset command, power outage, firmware update, software error etc.) the Charge Point **MUST** again contact the Central System and **SHALL** send a BootNotification request." 翻譯:在任何重啟之後(包括遠端重設命令、斷電恢復、韌體更新、軟體錯誤等),充電樁**必須**再次聯繫中央系統,並且**必須**發送 BootNotification 請求。 📚 **引用:** ocpp-1.6-errata-sheet.pdf, Section 3.11 (Page 35, section 4.2) ### 2.2 連線流程時序圖 ``` 充電樁 中央系統 │ │ │ ══════════ 階段 1:建立 WebSocket ══════════ │ │ │ │────── WebSocket Connection Request ──────────►│ │◄───── HTTP 101 Switching Protocols ──────────│ │ (連線建立成功) │ │ │ │ ══════════ 階段 2:身份註冊 ══════════════ │ │ │ │────── BootNotification.req ──────────────────►│ │ (我是誰、我的型號、韌體版本) │ │◄───── BootNotification.conf ─────────────────│ │ (Accepted/Pending/Rejected + 時間 + 間隔)│ │ │ │ ══════════ 階段 3:狀態回報 ══════════════ │ │ (只有在收到 Accepted 後才執行) │ │ │ │────── StatusNotification.req (connector 0) ──►│ │◄───── StatusNotification.conf ───────────────│ │────── StatusNotification.req (connector 1) ──►│ │◄───── StatusNotification.conf ───────────────│ │ (每個 connector 都要報告狀態) │ │ │ │ ══════════ 階段 4:正常運作 ══════════════ │ │ │ │────── Heartbeat.req ─────────────────────────►│ ┐ │◄───── Heartbeat.conf (currentTime) ──────────│ │ 週期性 │ ...每隔 interval 秒重複... │ ┘ │ │ ``` ### 2.3 BootNotification 詳解 **Request 內容 (充電樁發送):** | 欄位 | 必填 | 最大長度 | 說明 | |------|------|---------|------| | chargePointVendor | ✅ 必填 | 20 | 充電樁製造商名稱 | | chargePointModel | ✅ 必填 | 20 | 充電樁型號 | | chargePointSerialNumber | 選填 | 25 | 充電樁序號 | | chargeBoxSerialNumber | 選填 | 25 | 充電箱序號 | | firmwareVersion | 選填 | 50 | 韌體版本 | | iccid | 選填 | 20 | SIM 卡 ICCID | | imsi | 選填 | 20 | SIM 卡 IMSI | | meterType | 選填 | 25 | 電表類型 | | meterSerialNumber | 選填 | 25 | 電表序號 | 實際 JSON 範例: ```json [2, "boot-001", "BootNotification", { "chargePointVendor": "StarCharge", "chargePointModel": "SC-DC-120", "chargePointSerialNumber": "SC2024001234", "firmwareVersion": "1.2.5", "meterType": "ABB", "meterSerialNumber": "MTR2024001" }] ``` 📚 **引用:** ocpp-1.6 edition 2.pdf, Section 6.3 (BootNotificationRequest) **Response 內容 (中央系統回應):** | 欄位 | 說明 | |------|------| | status | **Accepted** / **Pending** / **Rejected** | | currentTime | 中央系統目前時間 (ISO 8601 格式) | | interval | 間隔秒數(用途取決於 status) | 實際 JSON 範例: ```json [3, "boot-001", { "status": "Accepted", "currentTime": "2024-12-05T10:30:00.000Z", "interval": 300 }] ``` ### 2.4 三種回應狀態的處理邏輯 這是工程師必須理解的關鍵邏輯: **Accepted(已接受)** - 充電樁已被系統認可,可以開始正常運作 - `interval` = Heartbeat 發送間隔(秒) - 充電樁接下來**必須**立即發送 StatusNotification 回報所有 connector 的狀態 **Pending(等待中)** - 中央系統尚未決定是否接受(可能需要人工審核) - `interval` = 重新發送 BootNotification 的等待時間(秒) - 充電樁必須等待指定秒數後再次發送 BootNotification - 在此期間,充電樁**不應該**接受任何充電交易 **Rejected(被拒絕)** - 中央系統明確拒絕此充電樁 - `interval` = 重新嘗試的等待時間(秒) - 可能原因:IMSI 未知、設備未在系統中註冊、配置錯誤等 - 充電樁應該等待指定秒數後再次嘗試 📚 **引用:** ocpp-1.6 edition 2.pdf, Section 4.2 (Boot Notification); ocpp-1.6-errata-sheet.pdf, Section 3.68 - 修正 Rejected 的範例描述,因為在 OCPP-J 中未知充電樁會收到 HTTP 404 而非 Rejected。 ### 2.5 BootNotification 被接受後的必要動作 根據 Errata Sheet 的補充說明,這是**強制要求**: > "After the Central System accept a Charge Point by sending a BootNotification.conf with a status Accepted, the Charge Point **SHALL** send a StatusNotification.req PDU for connectorId 0 and all connectors with the current status." 這意味著: 1. 收到 Accepted 後 2. 立即發送 `StatusNotification.req` 給 **connectorId = 0**(代表充電樁整體) 3. 然後發送 `StatusNotification.req` 給**每一個實際的 connector**(connectorId = 1, 2, ...) 📚 **引用:** ocpp-1.6-errata-sheet.pdf, Section 3.22 (Page 43, section 4.9) ### 2.6 連線失敗的處理 如果充電樁嘗試連線但中央系統不認識它(例如設備 ID 未在系統中註冊),中央系統可能回應 **HTTP 404**。根據 Errata Sheet: > "The Charge Point SHALL retry with an appropriate back-off mechanism to prevent overloading the Central System." 充電樁必須使用適當的退避機制重試,以避免對中央系統造成過載。 📚 **引用:** ocpp-j-1.6-errata-sheet.pdf, Section 3.4 (Page 8, section 3.2) ### 2.7 現場工程師檢查清單 當充電樁無法連線到平台時,請依序檢查: 1. **網路連通性**:充電樁是否有網路連線?能否 ping 通平台 IP? 2. **WebSocket URL**:連線 URL 是否正確設定?格式通常為 `ws://host:port/ocpp/{chargeBoxId}` 或 `wss://...` 3. **設備 ID**:chargeBoxId 是否已在平台系統中註冊? 4. **查看日誌**: - 有收到 HTTP 404?→ 設備未在系統中註冊 - 有收到 Rejected?→ 可能是 IMSI 或其他識別資訊不符 - 有收到 Pending?→ 系統需要人工審核或配置中 5. **時間同步**:充電樁時間是否正確?若差異過大可能影響 TLS 憑證驗證 --- ## 第三章:週期性資料與監控訊息 ### 3.1 Heartbeat(心跳) Heartbeat 是最簡單但最重要的週期性訊息。它的目的是: 1. 證明充電樁還活著、連線仍然有效 2. 讓充電樁同步中央系統的時間 **Request (充電樁發送):** ```json [2, "hb-001", "Heartbeat", {}] ``` 沒錯,**Request 的 payload 是空的**!Heartbeat.req 不需要任何參數。 **Response (中央系統回應):** ```json [3, "hb-001", { "currentTime": "2024-12-05T10:35:00.000Z" }] ``` 中央系統回傳目前時間,充電樁應該用這個時間來校正自己的內部時鐘。 📚 **引用:** ocpp-1.6 edition 2.pdf, Section 4.6 (Heartbeat); Heartbeat.json & HeartbeatResponse.json **發送頻率**:由 BootNotification.conf 中的 `interval` 決定(當 status = Accepted 時)。 **重要提醒**:如果中央系統長時間沒有收到某台充電樁的 Heartbeat,通常表示該充電樁已經離線。平台會將其狀態標記為「離線」或「失聯」。 ### 3.2 StatusNotification(狀態通知) StatusNotification 用於回報 connector 的狀態變化。根據 Errata Sheet 的強化要求: > "a Charge Point **SHALL** send a StatusNotification.req PDU to the Central System, taking into account some minimum status duration." 這表示狀態變化時**必須**發送通知(原規範用的是 MAY,已修正為 SHALL)。 📚 **引用:** ocpp-1.6-errata-sheet.pdf, Section 3.19 (Page 38, section 4.9) **Request 結構:** ```json [2, "status-001", "StatusNotification", { "connectorId": 1, "errorCode": "NoError", "status": "Available", "timestamp": "2024-12-05T10:30:00.000Z" }] ``` **Connector 狀態 (ChargePointStatus) 完整列表:** | 狀態 | 說明 | 典型情境 | |------|------|---------| | **Available** | 可用,準備接受新使用者 | 閒置等待中 | | **Preparing** | 有使用者互動,但交易尚未開始 | 刷卡後、插槍前 | | **Charging** | 正在充電中 | 能量傳輸進行中 | | **SuspendedEV** | 充電暫停,由 EV 端發起 | 電池已滿、EV 端暫停 | | **SuspendedEVSE** | 充電暫停,由充電樁發起 | Smart Charging 限制、負載平衡 | | **Finishing** | 交易已結束,但 connector 尚未釋放 | 等待拔槍 | | **Reserved** | 已被預約 | 有預約尚未到達 | | **Unavailable** | 不可用 | 維護中、手動停用 | | **Faulted** | 故障 | 硬體或軟體錯誤 | 📚 **引用:** ocpp-1.6 edition 2.pdf, Section 7.7 (ChargePointStatus); ocpp-1.6-errata-sheet.pdf, Section 3.20 - 補充 B6 轉換(Preparing → Finishing,當授權逾時) **錯誤代碼 (ChargePointErrorCode):** | 錯誤碼 | 說明 | |--------|------| | NoError | 無錯誤(正常狀態變化使用此值) | | ConnectorLockFailure | 連接器鎖定失敗 | | EVCommunicationError | 與 EV 通訊錯誤 | | GroundFailure | 接地故障 | | HighTemperature | 高溫警告 | | InternalError | 內部錯誤 | | OverCurrentFailure | 過電流 | | OverVoltage | 過電壓 | | UnderVoltage | 欠電壓 | | PowerMeterFailure | 電表故障 | | ReaderFailure | 讀卡機故障 | | WeakSignal | 訊號弱 | 📚 **引用:** ocpp-1.6 edition 2.pdf, Section 7.6 (ChargePointErrorCode) ### 3.3 MeterValues(電表數值)- 重點詳解 MeterValues 是充電監控的核心,它提供充電過程中的各種量測數據。這是理解充電樁數據最重要的部分。 #### 3.3.1 兩種 MeterValues 類型 **Sampled Data(取樣數據)** - **目的**:提供即時充電進度給使用者(透過 App 顯示充電速度、已充電量等) - **觸發時機**:每隔 `MeterValueSampleInterval` 秒發送一次 - **Context**:`Sample.Periodic` - **配置鍵**: - `MeterValueSampleInterval`:取樣間隔(秒),設為 0 表示不發送 - `MeterValuesSampledData`:要取樣的量測項目(逗號分隔清單) **Clock-Aligned Data(時鐘對齊數據)** - **目的**:提供電網計費所需的精確時間點數據(如每 15 分鐘一筆) - **觸發時機**:在固定時間點發送(如 00:00, 00:15, 00:30, 00:45) - **Context**:`Sample.Clock` - **配置鍵**: - `ClockAlignedDataInterval`:對齊間隔(秒),例如 900 = 15 分鐘 - `MeterValuesAlignedData`:要記錄的量測項目 📚 **引用:** ocpp-1.6-errata-sheet.pdf, Section 3.14 (新增的 Metering Data 章節) #### 3.3.2 MeterValues.req 結構 ```json [2, "mv-001", "MeterValues", { "connectorId": 1, "transactionId": 12345, "meterValue": [{ "timestamp": "2024-12-05T10:35:00.000Z", "sampledValue": [ { "value": "15234", "context": "Sample.Periodic", "measurand": "Energy.Active.Import.Register", "unit": "Wh" }, { "value": "32500", "context": "Sample.Periodic", "measurand": "Power.Active.Import", "unit": "W" }, { "value": "48", "context": "Sample.Periodic", "measurand": "Current.Import", "phase": "L1", "unit": "A" } ] }] } ``` #### 3.3.3 常見 Measurand(量測項目) | Measurand | 說明 | 單位 | 用途 | |-----------|------|------|------| | **Energy.Active.Import.Register** | 輸入有功電能(累計) | Wh, kWh | **計費依據** | | **Energy.Active.Export.Register** | 輸出有功電能(V2G) | Wh, kWh | V2G 回饋電網 | | **Power.Active.Import** | 瞬時輸入功率 | W, kW | 充電速度顯示 | | **Current.Import** | 輸入電流 | A | 負載監控 | | **Voltage** | 電壓 | V | 電網品質監控 | | **SoC** | 電池充電狀態 | Percent | EV 電量百分比 | | **Temperature** | 溫度 | Celsius, K | 熱管理監控 | 📚 **引用:** ocpp-1.6 edition 2.pdf, Section 7.31 (Measurand); ocpp-1.6-errata-sheet.pdf, Section 3.78-3.79 (Import/Export 定義改善) #### 3.3.4 Context(上下文)的意義 | Context | 說明 | 觸發時機 | |---------|------|---------| | Sample.Periodic | 週期性取樣 | 每隔 MeterValueSampleInterval | | Sample.Clock | 時鐘對齊取樣 | 每隔 ClockAlignedDataInterval | | Transaction.Begin | 交易開始 | StartTransaction 時 | | Transaction.End | 交易結束 | StopTransaction 時 | | Trigger | 被觸發 | 收到 TriggerMessage 時 | | Interruption.Begin | 中斷開始 | 充電中斷時 | | Interruption.End | 中斷結束 | 充電恢復時 | #### 3.3.5 重要的電表值處理原則 根據 Errata Sheet 的建議: > "If a Charge Point contains a Meter that has a register that can be read, It is RECOMMENDED to send this register value in every MeterValue send instead of starting at 0 for every transaction." 如果充電樁有可讀取的電表暫存器,建議發送實際的暫存器值,而不是每筆交易都從 0 開始。這樣可以避免數據不一致的問題。 📚 **引用:** ocpp-1.6-errata-sheet.pdf, Section 3.9 (Page 29) #### 3.3.6 MeterValues 配置強制要求 根據 Errata Sheet 的補充: > "When the value of the configuration variable MeterValueSampleInterval and/or ClockAlignedDataInterval has been set to a value greater than zero, the Charge Point **SHALL** send MeterValues at the given interval(s)." 當取樣間隔設為大於 0 的值時,發送 MeterValues 是**強制性**的,不是可選的。 📚 **引用:** ocpp-1.6-errata-sheet.pdf, Section 3.15 (Page 36, section 4.7) ### 3.4 週期性訊息總覽 | 訊息類型 | 發起方 | 觸發條件 | 頻率控制 | |---------|--------|---------|---------| | Heartbeat | CP → CS | 定時觸發 | BootNotification.conf 的 interval | | MeterValues (Sampled) | CP → CS | 交易進行中 | MeterValueSampleInterval 配置 | | MeterValues (Clock-Aligned) | CP → CS | 交易進行中 | ClockAlignedDataInterval 配置 | | StatusNotification | CP → CS | 狀態變化時 | 事件驅動(非週期) | ### 3.5 現場問題排查指南 **問題:平台顯示充電樁離線** - 檢查 Heartbeat 是否正常發送 - 確認 interval 設定值(過長的 interval 會導致平台誤判離線) - 檢查網路連線穩定性 **問題:充電中但看不到即時數據** - 確認 `MeterValueSampleInterval` 是否設為 0(0 表示不發送) - 確認 `MeterValuesSampledData` 有設定要取樣的項目 - 檢查充電樁是否有電表功能 **問題:計費數據不準確** - 檢查 `ClockAlignedDataInterval` 設定 - 確認 Transaction.Begin 和 Transaction.End 的數據有被記錄 - 根據 Errata Sheet,Start/Stop 數值**絕不應該被丟棄** 📚 **引用:** ocpp-1.6-errata-sheet.pdf, Section 3.91 (StopTransactionMaxMeterValues) - 當記憶體不足需要丟棄中間值時,Start 和 Stop 值絕不能丟棄。 --- ## 附錄:快速參考表 ### 重要 Configuration Keys | Key | 說明 | 預設建議值 | |-----|------|-----------| | HeartbeatInterval | Heartbeat 間隔 | 300 秒 | | MeterValueSampleInterval | 電表取樣間隔 | 60 秒 | | ClockAlignedDataInterval | 時鐘對齊間隔 | 900 秒 (15分鐘) | | MeterValuesSampledData | 取樣項目清單 | Energy.Active.Import.Register,Power.Active.Import | | ConnectionTimeOut | 連線逾時 | 30 秒 | ### 文件引用索引 | 主題 | OCPP 1.6 Ed.2 章節 | Errata Sheet 章節 | |------|-------------------|------------------| | BootNotification | 4.2, 6.3, 6.4 | 3.11, 3.68, 4.6 | | Heartbeat | 4.6 | - | | StatusNotification | 4.9, 7.6, 7.7 | 3.19, 3.20, 3.22 | | MeterValues | 4.7, 7.31, Chapter 9 | 3.9, 3.14, 3.15, 3.78 | | 訊息框架 (OCPP-J) | - | ocpp-j: 3.1-3.11, 4.1 | ---
{"title":"OCPP 1.6 工程師培訓手冊","contributors":"[{\"id\":\"8805d760-20df-4ce4-9e48-53578a98c68c\",\"add\":14807,\"del\":334,\"latestUpdatedAt\":1765355095452}]","description":"讓我先搜索專案知識庫以獲取更完整的規範內容,確保引用準確:根據專案知識庫的搜索結果,我為您撰寫一份針對外出工程師的 OCPP 培訓教材,涵蓋三大重點:"}
Expand menu