# 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 培訓教材,涵蓋三大重點:"}