Files
JChargePointProtocol/docs/核心模块详解/设备管理模块/充电桩管理.md
2025-10-28 14:39:06 +08:00

699 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 充电桩管理
<cite>
**本文档引用的文件**
- [Pile.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/entity/Pile.java)
- [PileController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java)
- [PileCreateRequest.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/request/PileCreateRequest.java)
- [PileUpdateRequest.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/request/PileUpdateRequest.java)
- [PileWithStatusResponse.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/response/PileWithStatusResponse.java)
- [DefaultPileService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileService.java)
- [PileRepository.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/repository/PileRepository.java)
- [PileRepositoryImpl.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/repository/impl/PileRepositoryImpl.java)
- [PileStatusEnum.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/PileStatusEnum.java)
- [PileTypeEnum.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/PileTypeEnum.java)
- [StartChargeDTO.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/StartChargeDTO.java)
- [RestartPileDTO.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/RestartPileDTO.java)
- [DefaultPileProtocolService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java)
- [RpcController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java)
</cite>
## 目录
1. [简介](#简介)
2. [数据模型](#数据模型)
3. [RESTful API](#restful-api)
4. [业务逻辑处理](#业务逻辑处理)
5. [远程控制操作](#远程控制操作)
6. [使用示例](#使用示例)
7. [状态机与实时同步](#状态机与实时同步)
## 简介
本文档详细阐述了充电桩管理功能的实现包括充电桩实体的数据模型、RESTful
API接口、业务逻辑处理以及远程控制操作。系统采用分层架构通过Pile实体表示充电桩PileController提供RESTful
APIDefaultPileService处理业务逻辑PileRepository负责数据持久化DownlinkCallService实现远程控制指令的发送。
## 数据模型
充电桩管理功能的核心是Pile实体它表示一个物理充电桩包含其基本信息、状态和与充电站的关系。
```mermaid
erDiagram
PILE {
uuid id PK
timestamp createdTime
timestamp updatedTime
string pileName
string pileCode UK
string protocol
uuid stationId FK
string brand
string model
string manufacturer
string type
integer version
json additionalInfo
}
STATION {
uuid id PK
string stationName
string stationCode UK
}
PILE ||--o{ STATION : "属于"
```
**图源**
- [Pile.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/entity/Pile.java#L1-L63)
- [PileTypeEnum.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/PileTypeEnum.java#L1-L22)
### Pile实体核心属性
Pile实体定义了充电桩的核心属性这些属性在数据库中持久化存储。
| 属性名 | 类型 | 描述 | 约束 |
|----------------|---------------|----------|--------------|
| id | UUID | 充电桩唯一标识符 | 主键 |
| pileName | String | 充电桩名称 | 非空防XSS攻击 |
| pileCode | String | 充电桩编号 | 唯一非空防XSS攻击 |
| protocol | String | 通信协议类型 | 非空防XSS攻击 |
| stationId | UUID | 所属充电站ID | 外键,非空 |
| brand | String | 品牌 | 防XSS攻击 |
| model | String | 型号 | 防XSS攻击 |
| manufacturer | String | 制造商 | 防XSS攻击 |
| type | PileTypeEnum | 充电桩类型 | 枚举值 |
| createdTime | LocalDateTime | 创建时间 | 自动填充 |
| updatedTime | LocalDateTime | 更新时间 | 自动填充 |
| additionalInfo | JsonNode | 附加信息 | JSON格式 |
| version | Integer | 版本号 | 用于乐观锁 |
**节源**
- [Pile.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/entity/Pile.java#L1-L63)
### PileStatusEnum状态枚举
充电桩状态枚举定义了充电桩的在线/离线状态,独立于充电枪的工作状态。
```mermaid
stateDiagram-v2
[*] --> OFFLINE
OFFLINE --> ONLINE : 设备登录成功
OFFLINE --> ONLINE : 心跳正常
ONLINE --> OFFLINE : 设备断开连接
ONLINE --> OFFLINE : 心跳超时
OFFLINE --> OFFLINE : 设备未登录
ONLINE --> ONLINE : 能正常通信
```
充电桩状态设计原则:
- 状态独立于充电枪状态,不受枪的工作状态影响
- 只关注设备的网络连接状态和基础可用性
- 状态转换由设备登录、心跳和连接状态决定
**节源**
- [PileStatusEnum.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/PileStatusEnum.java#L1-L50)
### PileTypeEnum类型枚举
充电桩类型枚举定义了充电桩的类型,目前支持交流和直流两种类型。
```mermaid
classDiagram
class PileTypeEnum {
+AC : PileTypeEnum
+DC : PileTypeEnum
+getValue() String
}
```
| 枚举值 | 描述 |
|-----|-------|
| AC | 交流充电桩 |
| DC | 直流充电桩 |
**节源**
- [PileTypeEnum.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/config/ibatis/enums/PileTypeEnum.java#L1-L22)
### 与Station的多对一关系
每个充电桩属于一个充电站形成多对一的关系。这种关系通过Pile实体中的stationId字段实现该字段是外键指向Station实体的id。
```mermaid
classDiagram
class Pile {
-UUID id
-String pileName
-String pileCode
-UUID stationId
+getStationId() UUID
}
class Station {
-UUID id
-String stationName
-String stationCode
+getId() UUID
}
Pile --> Station : "属于"
```
**图源**
- [Pile.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/entity/Pile.java#L1-L63)
## RESTful API
PileController类暴露了充电桩管理的RESTful API提供了对充电桩的增删改查和远程控制操作。
```mermaid
graph TB
subgraph "PileController"
A[POST /piles]
B[GET /piles]
C[PUT /piles/{id}]
D[DELETE /piles/{id}]
E[GET /piles/{id}]
F[POST /piles/{id}/start-charge]
G[POST /piles/{id}/restart]
end
Client --> A
Client --> B
Client --> C
Client --> D
Client --> E
Client --> F
Client --> G
```
**图源**
- [PileController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java#L1-L111)
### 创建充电桩 (POST /piles)
创建新的充电桩,需要提供充电桩的基本信息。
#### 请求
- **方法**: POST
- **路径**: /api/piles
- **认证**: 需要有效的JWT令牌
- **授权**: 需要管理员权限
#### 请求DTO (PileCreateRequest)
```mermaid
classDiagram
class PileCreateRequest {
+pileName : String
+pileCode : String
+protocol : String
+stationId : UUID
+brand : String
+model : String
+manufacturer : String
+type : PileTypeEnum
}
```
| 字段 | 类型 | 必填 | 描述 |
|--------------|--------------|----|-------------|
| pileName | String | 是 | 充电桩名称 |
| pileCode | String | 是 | 充电桩编号 |
| protocol | String | 是 | 通信协议 |
| stationId | UUID | 是 | 所属充电站ID |
| brand | String | 否 | 品牌 |
| model | String | 否 | 型号 |
| manufacturer | String | 否 | 制造商 |
| type | PileTypeEnum | 否 | 充电桩类型默认为DC |
#### 响应
- **成功**: HTTP 200返回创建的Pile实体
- **失败**: HTTP 400参数验证失败HTTP 409充电桩编号已存在
**节源**
- [PileController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java#L25-L34)
- [PileCreateRequest.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/request/PileCreateRequest.java#L1-L45)
### 分页查询充电桩 (GET /piles)
分页查询充电桩列表,支持多种查询条件。
#### 请求
- **方法**: GET
- **路径**: /api/piles
- **认证**: 需要有效的JWT令牌
- **授权**: 需要查看权限
#### 请求参数 (PileQueryRequest)
| 参数 | 类型 | 描述 |
|--------------|----------------|-------------|
| page | Integer | 页码从1开始 |
| size | Integer | 每页大小 |
| pileName | String | 充电桩名称(模糊查询) |
| pileCode | String | 充电桩编号 |
| protocol | String | 通信协议 |
| stationId | UUID | 所属充电站ID |
| brand | String | 品牌 |
| model | String | 型号 |
| manufacturer | String | 制造商 |
| type | PileTypeEnum | 充电桩类型 |
| status | PileStatusEnum | 充电桩状态 |
#### 响应DTO (PileWithStatusResponse)
```mermaid
classDiagram
class PileWithStatusResponse {
+id : UUID
+createdTime : LocalDateTime
+updatedTime : LocalDateTime
+pileName : String
+pileCode : String
+protocol : String
+stationId : UUID
+brand : String
+model : String
+manufacturer : String
+type : PileTypeEnum
+status : PileStatusEnum
+connectedAt : Long
+disconnectedAt : Long
+lastActiveTime : Long
+gunCount : Long
}
```
响应包含分页信息和充电桩列表,每个充电桩都包含其状态信息。
#### 响应
- **成功**: HTTP 200返回PageResponse<PileWithStatusResponse>
- **失败**: HTTP 400参数验证失败
**节源**
- [PileController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java#L68-L77)
- [PileQueryRequest.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/request/PileQueryRequest.java#L1-L36)
- [PileWithStatusResponse.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/response/PileWithStatusResponse.java#L1-L116)
### 更新充电桩 (PUT /piles/{id})
更新现有充电桩的信息。
#### 请求
- **方法**: PUT
- **路径**: /api/piles/{id}
- **认证**: 需要有效的JWT令牌
- **授权**: 需要编辑权限
#### 请求DTO (PileUpdateRequest)
```mermaid
classDiagram
class PileUpdateRequest {
+pileName : String
+protocol : String
+brand : String
+model : String
+manufacturer : String
+type : PileTypeEnum
}
```
| 字段 | 类型 | 必填 | 描述 |
|--------------|--------------|----|-------|
| pileName | String | 是 | 充电桩名称 |
| protocol | String | 是 | 通信协议 |
| brand | String | 否 | 品牌 |
| model | String | 否 | 型号 |
| manufacturer | String | 否 | 制造商 |
| type | PileTypeEnum | 否 | 充电桩类型 |
#### 响应
- **成功**: HTTP 200返回更新后的Pile实体
- **失败**: HTTP 404充电桩不存在HTTP 400参数验证失败
**节源**
- [PileController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java#L40-L50)
- [PileUpdateRequest.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/request/PileUpdateRequest.java#L1-L35)
### 删除充电桩 (DELETE /piles/{id})
删除指定ID的充电桩。
#### 请求
- **方法**: DELETE
- **路径**: /api/piles/{id}
- **认证**: 需要有效的JWT令牌
- **授权**: 需要删除权限
#### 响应
- **成功**: HTTP 200返回成功消息
- **失败**: HTTP 404充电桩不存在HTTP 409充电桩下有充电枪
**节源**
- [PileController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java#L52-L60)
## 业务逻辑处理
DefaultPileService类负责处理充电桩管理的核心业务逻辑包括数据持久化、缓存交互和状态管理。
```mermaid
sequenceDiagram
participant Client as "客户端"
participant Controller as "PileController"
participant Service as "DefaultPileService"
participant Repository as "PileRepository"
participant Cache as "PileRedisCache"
participant DB as "数据库"
Client->>Controller : POST /piles
Controller->>Service : createPile(request)
Service->>Repository : findPileByCode(code)
Repository->>Cache : get(pileCode)
Cache-->>Repository : null
Repository->>DB : selectByCode(code)
DB-->>Repository : null
Repository-->>Service : null
Service->>DB : insert(pile)
DB-->>Service : success
Service-->>Controller : Pile
Controller-->>Client : 200 OK
```
**图源**
- [DefaultPileService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileService.java#L1-L329)
- [PileRepositoryImpl.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/repository/impl/PileRepositoryImpl.java#L1-L49)
### DefaultPileService核心功能
DefaultPileService实现了PileService接口处理充电桩的业务逻辑。
| 方法 | 描述 |
|------------------------|----------------|
| createPile | 创建充电桩,检查编号唯一性 |
| findById | 根据ID查找充电桩 |
| findByPileCode | 根据编号查找充电桩 |
| updatePile | 更新充电桩信息 |
| deletePile | 删除充电桩,检查是否有充电枪 |
| queryPilesWithStatus | 分页查询充电桩及状态 |
| updatePileStatus | 更新充电桩状态 |
| handlePileLogin | 处理充电桩登录 |
| handlePileHeartbeat | 处理充电桩心跳 |
| handlePileSessionClose | 处理充电桩会话关闭 |
**节源**
- [DefaultPileService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileService.java#L1-L329)
### 数据持久化 (PileRepository)
PileRepository接口定义了充电桩的数据访问方法PileRepositoryImpl实现了该接口并提供了缓存支持。
```mermaid
classDiagram
class PileRepository {
+findPileByCode(pileCode : String) : Pile
}
class PileRepositoryImpl {
-pileMapper : PileMapper
-cache : PileRedisCache
+findPileByCode(pileCode : String) : Pile
+handleEvictEvent(event : PileCacheEvictEvent) : void
}
class PileMapper {
+selectByCode(pileCode : String) : Pile
+insert(pile : Pile) : int
+updateById(pile : Pile) : int
+deleteById(id : UUID) : int
}
PileRepository <|-- PileRepositoryImpl
PileRepositoryImpl --> PileMapper : "使用"
PileRepositoryImpl --> PileRedisCache : "使用"
```
PileRepositoryImpl通过继承CachedVersionedEntityRepository获得了缓存功能实现了基于Redis的缓存机制。当充电桩数据发生变化时通过@TransactionalEventListener监听事件并清除缓存
**图源**
- [PileRepository.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/repository/PileRepository.java#L1-L16)
- [PileRepositoryImpl.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/repository/impl/PileRepositoryImpl.java#L1-L49)
### 缓存交互 (PileRedisCache)
系统使用Redis作为缓存存储PileRedisCache负责充电桩数据的缓存操作。PileRepositoryImpl通过cache字段与PileRedisCache交互实现了读取时的缓存命中和写入时的缓存失效。
缓存键使用PileCacheKey支持通过ID和编号两种方式缓存充电桩数据。当充电桩被更新或删除时PileRepositoryImpl会发布PileCacheEvictEvent事件触发缓存清除。
**节源**
- [PileRepositoryImpl.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/dal/repository/impl/PileRepositoryImpl.java#L1-L49)
## 远程控制操作
系统支持对充电桩进行远程控制操作如启动充电、重启等。这些操作通过RPC机制实现由RpcController接收请求调用PileProtocolService执行。
```mermaid
sequenceDiagram
participant Client as "客户端"
participant RpcController as "RpcController"
participant PileProtocolService as "DefaultPileProtocolService"
participant DownlinkCallService as "DownlinkCallService"
participant Protocol as "协议层"
Client->>RpcController : RPC startCharge
RpcController->>RpcController : handleStartCharge()
RpcController->>PileProtocolService : startCharge(dto)
PileProtocolService->>DownlinkCallService : sendDownlinkMessage()
DownlinkCallService->>Protocol : 发送指令
Protocol-->>DownlinkCallService : 发送成功
DownlinkCallService-->>PileProtocolService : 回调
PileProtocolService-->>RpcController : 返回
RpcController-->>Client : 响应
```
**图源**
- [RpcController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java#L107-L145)
- [DefaultPileProtocolService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java#L412-L440)
### 启动充电 (POST /piles/{id}/start-charge)
远程启动充电桩的充电操作。
#### 实现流程
1. RpcController接收启动充电的RPC请求
2. 解析StartChargeDTO参数
3. 调用PileProtocolService.startCharge方法
4. 构造下行消息RemoteStartChargingRequest
5. 通过DownlinkCallService发送到协议层
6. 协议层将指令发送到充电桩
#### 请求DTO (StartChargeDTO)
```mermaid
classDiagram
class StartChargeDTO {
+pileCode : String
+gunNo : String
+limitYuan : BigDecimal
+orderNo : String
+logicalCardNo : String
+physicalCardNo : String
+parallelNo : String
}
```
| 字段 | 类型 | 必填 | 描述 |
|----------------|------------|----|---------|
| pileCode | String | 是 | 充电桩编号 |
| gunNo | String | 是 | 充电枪编号 |
| limitYuan | BigDecimal | 是 | 限制金额(元) |
| orderNo | String | 是 | 订单号 |
| logicalCardNo | String | 否 | 逻辑卡号 |
| physicalCardNo | String | 否 | 物理卡号 |
| parallelNo | String | 否 | 并充序号 |
**节源**
- [StartChargeDTO.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/StartChargeDTO.java#L1-L61)
- [DefaultPileProtocolService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java#L412-L440)
### 重启充电桩 (POST /piles/{id}/restart)
远程重启充电桩。
#### 实现流程
1. RpcController接收重启充电桩的RPC请求
2. 解析RestartPileDTO参数
3. 调用PileProtocolService.restartPile方法
4. 构造下行消息RestartPileRequest
5. 通过DownlinkCallService发送到协议层
6. 协议层将指令发送到充电桩
#### 请求DTO (RestartPileDTO)
```mermaid
classDiagram
class RestartPileDTO {
+pileCode : String
+type : Integer
}
```
| 字段 | 类型 | 必填 | 描述 |
|----------|---------|----|-------|
| pileCode | String | 是 | 充电桩编号 |
| type | Integer | 是 | 重启类型 |
**节源**
- [RestartPileDTO.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/RestartPileDTO.java#L1-L32)
- [DefaultPileProtocolService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java#L506-L531)
## 使用示例
以下示例演示如何为一个充电站添加充电桩并远程启动充电。
### 为充电站添加充电桩
```http
POST /api/piles HTTP/1.1
Content-Type: application/json
Authorization: Bearer <token>
```
响应:
```json
{
"code": 200,
"message": "创建成功",
"data": {
"id": "f1e2d3c4-b5a6-9876-5432-10fedcba9876",
"createdTime": "2024-01-01T10:00:00",
"pileName": "直流快充桩1号",
"pileCode": "DCP001",
"protocol": "LVNENG_V340",
"stationId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"brand": "特来电",
"model": "DC-80KW",
"manufacturer": "特来电新能源有限公司",
"type": "DC"
}
}
```
### 远程启动充电
```http
POST /rpc HTTP/1.1
Content-Type: application/json
Authorization: Bearer <token>
```
**节源**
- [PileController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java#L25-L34)
- [RpcController.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java#L107-L145)
## 状态机与实时同步
充电桩状态机管理充电桩的在线/离线状态,通过实时同步机制确保状态的准确性。
```mermaid
stateDiagram-v2
[*] --> OFFLINE
OFFLINE --> ONLINE : login
ONLINE --> OFFLINE : session close
ONLINE --> ONLINE : heartbeat
OFFLINE --> OFFLINE : no activity
note right of ONLINE
状态属性 :
- status : ONLINE
- connectedAt : 时间戳
- lastActiveTime : 时间戳
end note
note right of OFFLINE
状态属性 :
- status : OFFLINE
- disconnectedAt : 时间戳
end note
```
### 状态机实现
充电桩状态机基于三个核心事件实现:登录、心跳和会话关闭。
| 事件 | 当前状态 | 新状态 | 更新的属性 |
|------|--------|---------|-------------------------------------|
| 登录 | 任意 | ONLINE | status, connectedAt, lastActiveTime |
| 心跳 | ONLINE | ONLINE | status, lastActiveTime |
| 会话关闭 | ONLINE | OFFLINE | status, disconnectedAt |
**节源**
- [DefaultPileService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileService.java#L240-L300)
### 实时状态同步
系统通过AttributeService将充电桩状态存储在Redis中实现状态的实时同步。
```mermaid
flowchart TD
A[充电桩登录] --> B[调用handlePileLogin]
B --> C[更新状态属性]
C --> D[保存到Redis]
D --> E[状态同步完成]
F[充电桩心跳] --> G[调用handlePileHeartbeat]
G --> H[更新状态属性]
H --> D
I[会话关闭] --> J[调用handlePileSessionClose]
J --> K[更新状态属性]
K --> D
```
状态属性存储在Redis的哈希结构中键名为`pile:attributes:{pileId}`,字段名为状态属性名,如`STATUS``CONNECTED_AT`
等。这种设计支持高效的状态查询和更新。
**节源**
- [DefaultPileService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileService.java#L240-L300)