mirror of
https://gitee.com/san-bing/JChargePointProtocol
synced 2026-07-18 04:37:55 +08:00
699 lines
22 KiB
Markdown
699 lines
22 KiB
Markdown
|
|
# 充电桩管理
|
|||
|
|
|
|||
|
|
<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
|
|||
|
|
API,DefaultPileService处理业务逻辑,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>
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
"pileName": "直流快充桩1号",
|
|||
|
|
"pileCode": "DCP001",
|
|||
|
|
"protocol": "LVNENG_V340",
|
|||
|
|
"stationId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
|
|||
|
|
"brand": "特来电",
|
|||
|
|
"model": "DC-80KW",
|
|||
|
|
"manufacturer": "特来电新能源有限公司",
|
|||
|
|
"type": "DC"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
响应:
|
|||
|
|
|
|||
|
|
```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>
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
"method": "startCharge",
|
|||
|
|
"parameter": {
|
|||
|
|
"pileCode": "DCP001",
|
|||
|
|
"gunNo": "1",
|
|||
|
|
"limitYuan": 50.00,
|
|||
|
|
"orderNo": "ORD202401011001",
|
|||
|
|
"logicalCardNo": "CARD123456789012"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**节源**
|
|||
|
|
|
|||
|
|
- [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)
|