mirror of
https://gitee.com/san-bing/JChargePointProtocol
synced 2026-07-19 13:17:53 +08:00
wiki生成
This commit is contained in:
338
docs/核心模块详解/协议实现模块/绿能协议实现/下行消息处理.md
Normal file
338
docs/核心模块详解/协议实现模块/绿能协议实现/下行消息处理.md
Normal file
@@ -0,0 +1,338 @@
|
||||
# 下行消息处理
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [LvnengDownlinkCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengDownlinkCmdExe.java)
|
||||
- [LvnengDownlinkCmdConverter.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/mapping/LvnengDownlinkCmdConverter.java)
|
||||
- [LvnengV340RemoteStopDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RemoteStopDLCmd.java)
|
||||
- [LvnengV340SetPricingModelDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340SetPricingModelDLCmd.java)
|
||||
- [AbstractLvnengCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/AbstractLvnengCmdExe.java)
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java)
|
||||
- [DefaultPileProtocolService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java)
|
||||
- [TcpSession.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpSession.java)
|
||||
- [ProtocolSession.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/ProtocolSession.java)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
|
||||
1. [引言](#引言)
|
||||
2. [gRPC调用接收与下行指令生成](#grpc调用接收与下行指令生成)
|
||||
3. [协议命令转换机制](#协议命令转换机制)
|
||||
4. [具体下行命令实现](#具体下行命令实现)
|
||||
5. [消息序列化过程](#消息序列化过程)
|
||||
6. [指令重试与超时处理](#指令重试与超时处理)
|
||||
7. [完整时序图与报文格式示例](#完整时序图与报文格式示例)
|
||||
8. [结论](#结论)
|
||||
|
||||
## 引言
|
||||
|
||||
本文档系统阐述了绿能协议v3.40的下行消息处理流程。重点分析了从gRPC请求到设备响应的完整处理链路,包括LvnengDownlinkCmdExe如何接收gRPC调用并生成相应的下行指令,LvnengDownlinkCmdConverter如何将通用的协议命令转换为绿能协议特有的命令码,以及具体下行命令的实现细节。同时描述了消息序列化过程、指令重试机制和超时处理策略,并提供了完整的时序图和报文格式示例。
|
||||
|
||||
**本文档引用的文件**
|
||||
|
||||
- [LvnengDownlinkCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengDownlinkCmdExe.java)
|
||||
- [LvnengDownlinkCmdConverter.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/mapping/LvnengDownlinkCmdConverter.java)
|
||||
- [LvnengV340RemoteStopDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RemoteStopDLCmd.java)
|
||||
- [LvnengV340SetPricingModelDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340SetPricingModelDLCmd.java)
|
||||
- [AbstractLvnengCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/AbstractLvnengCmdExe.java)
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java)
|
||||
- [DefaultPileProtocolService.java](file://jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java)
|
||||
- [TcpSession.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpSession.java)
|
||||
- [ProtocolSession.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/ProtocolSession.java)
|
||||
|
||||
## gRPC调用接收与下行指令生成
|
||||
|
||||
绿能协议v3.40的下行消息处理流程始于gRPC调用的接收。系统通过`DownlinkGrpcService`接收来自客户端的gRPC请求,这些请求被封装为
|
||||
`DownlinkRequestMessage`对象。当gRPC服务接收到请求时,会通过`ProtocolSession`的`onDownlink`方法将消息传递给协议处理器。
|
||||
|
||||
`LvnengProtocolMessageProcessor`作为核心处理器,负责处理所有下行消息。它通过`doDownlinkHandle`方法接收
|
||||
`SessionToHandlerMsg`对象,该对象包含了`DownlinkRequestMessage`和`TcpSession`。处理器首先从`DownlinkRequestMessage`中提取
|
||||
`downlinkCmd`字段,并通过`DownlinkCmdEnum.valueOf()`将其转换为枚举类型。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant GrpcService as "DownlinkGrpcService"
|
||||
participant ProtocolSession as "ProtocolSession"
|
||||
participant MessageProcessor as "LvnengProtocolMessageProcessor"
|
||||
Client->>GrpcService : 发送gRPC请求(DownlinkRequestMessage)
|
||||
GrpcService->>ProtocolSession : 调用onDownlink(DownlinkRequestMessage)
|
||||
ProtocolSession->>MessageProcessor : 传递SessionToHandlerMsg
|
||||
MessageProcessor->>MessageProcessor : 解析DownlinkCmdEnum
|
||||
MessageProcessor->>MessageProcessor : 转换为协议特定命令码
|
||||
MessageProcessor->>MessageProcessor : 执行具体命令处理器
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
|
||||
- [DownlinkGrpcService.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkGrpcService.java#L123-L151)
|
||||
- [ProtocolSession.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/ProtocolSession.java#L0-L77)
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L0-L186)
|
||||
|
||||
**本文档引用的文件**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java)
|
||||
- [DownlinkGrpcService.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/adapter/DownlinkGrpcService.java)
|
||||
- [ProtocolSession.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/ProtocolSession.java)
|
||||
|
||||
## 协议命令转换机制
|
||||
|
||||
绿能协议v3.40使用`LvnengDownlinkCmdConverter`类来实现通用协议命令到绿能协议特定命令码的转换。该类实现了
|
||||
`DownlinkCmdConverter`接口,采用单例模式确保全局唯一实例。
|
||||
|
||||
转换器内部使用`ConcurrentHashMap`存储命令映射关系,提供O(1)的查找性能。在静态初始化块中,预定义了绿能协议支持的所有命令映射:
|
||||
|
||||
```java
|
||||
static {
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.LOGIN_ACK, 105);
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.SYNC_TIME_REQUEST, 3);
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.TRANSACTION_RECORD_ACK, 201);
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.HEARTBEAT_ACK, 101);
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.REAL_TIME_DATA_ACK, 103);
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.SET_PRICING, 1103);
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.REMOTE_STOP_CHARGING, 5);
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.SET_QRCODE, 3);
|
||||
}
|
||||
```
|
||||
|
||||
当需要转换命令时,`convertToCmd`方法会根据传入的`DownlinkCmdEnum`
|
||||
返回对应的协议特定命令码。如果命令不被支持,则返回null。这种设计使得命令转换过程高效且易于维护,新增命令只需在静态块中添加映射关系即可。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class DownlinkCmdConverter {
|
||||
<<interface>>
|
||||
+convertToCmd(DownlinkCmdEnum) Integer
|
||||
+supports(DownlinkCmdEnum) boolean
|
||||
+getProtocolName() String
|
||||
}
|
||||
class LvnengDownlinkCmdConverter {
|
||||
-INSTANCE LvnengDownlinkCmdConverter
|
||||
-COMMAND_MAP Map~DownlinkCmdEnum, Integer~
|
||||
+getInstance() LvnengDownlinkCmdConverter
|
||||
+convertToCmd(DownlinkCmdEnum) Integer
|
||||
+getProtocolName() String
|
||||
}
|
||||
DownlinkCmdConverter <|.. LvnengDownlinkCmdConverter
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
|
||||
- [LvnengDownlinkCmdConverter.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/mapping/LvnengDownlinkCmdConverter.java#L0-L75)
|
||||
- [DownlinkCmdConverter.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/mapping/DownlinkCmdConverter.java#L0-L44)
|
||||
|
||||
**本文档引用的文件**
|
||||
|
||||
- [LvnengDownlinkCmdConverter.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/mapping/LvnengDownlinkCmdConverter.java)
|
||||
|
||||
## 具体下行命令实现
|
||||
|
||||
### 远程停止充电指令实现
|
||||
|
||||
`LvnengV340RemoteStopDLCmd`类负责处理远程停止充电指令。该类继承自`LvnengDownlinkCmdExe`,并使用`@ProtocolCmd`
|
||||
注解标记其支持的命令码为5,协议版本为V340。
|
||||
|
||||
在`execute`方法中,首先从`LvnengDwonlinkMessage`中提取`RemoteStopChargingRequest`对象,获取充电桩编码和充电枪号。然后构建消息体
|
||||
`ByteBuf`,按照协议规范填充数据:
|
||||
|
||||
1. 写入2字节预留字段(值为0x00)
|
||||
2. 写入1字节充电枪口编号
|
||||
3. 写入4字节启始命令地址(值为2)
|
||||
4. 写入1字节命令个数(值为1)
|
||||
5. 写入2字节命令参数长度(值为4)
|
||||
6. 写入4字节命令参数(值为0x55)
|
||||
|
||||
最后调用`encodeAndWriteFlush`方法将指令发送到设备。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始]) --> ExtractData["提取RemoteStopChargingRequest数据"]
|
||||
ExtractData --> CreateBuffer["创建44字节的ByteBuf"]
|
||||
CreateBuffer --> WriteReserved["写入2字节预留字段(0x00)"]
|
||||
WriteReserved --> WriteGunCode["写入充电枪口编号"]
|
||||
WriteGunCode --> WriteStartAddr["写入启始命令地址(2)"]
|
||||
WriteStartAddr --> WriteCmdCount["写入命令个数(1)"]
|
||||
WriteCmdCount --> WriteParamLen["写入命令参数长度(4)"]
|
||||
WriteParamLen --> WriteParam["写入命令参数(0x55)"]
|
||||
WriteParam --> Send["调用encodeAndWriteFlush发送"]
|
||||
Send --> End([结束])
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
|
||||
- [LvnengV340RemoteStopDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RemoteStopDLCmd.java#L0-L67)
|
||||
|
||||
**本文档引用的文件**
|
||||
|
||||
- [LvnengV340RemoteStopDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RemoteStopDLCmd.java)
|
||||
|
||||
### 电价设置报文实现
|
||||
|
||||
`LvnengV340SetPricingModelDLCmd`类负责生成电价设置报文。该类同样继承自`LvnengDownlinkCmdExe`,并使用`@ProtocolCmd`
|
||||
注解标记其支持的命令码为1103,协议版本为V340。
|
||||
|
||||
在`execute`方法中,首先从`SetPricingRequest`中提取计费模型信息。对于时段计价模式,遍历所有时间段,将每个时间段的开始时间、结束时间、电费和服务费编码到消息体中:
|
||||
|
||||
1. 将开始时间解析为`LocalTime`对象,分别写入小时和分钟
|
||||
2. 将结束时间解析为`LocalTime`对象,分别写入小时和分钟
|
||||
3. 将电费价格乘以10000后转换为整数,写入4字节
|
||||
4. 将服务费价格乘以10000后转换为整数,写入4字节
|
||||
|
||||
价格转换通过`buildPrice`方法实现,使用`BigDecimal`进行精确计算,避免浮点数精度问题。在发送指令前,将计费ID存入会话的请求缓存中,用于后续的响应匹配。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始]) --> ExtractData["提取SetPricingRequest数据"]
|
||||
ExtractData --> CheckPricing["检查计费模式"]
|
||||
CheckPricing --> |时段计价| ProcessPeriods["处理每个时间段"]
|
||||
ProcessPeriods --> ParseStartTime["解析开始时间"]
|
||||
ParseStartTime --> WriteStartHour["写入开始小时"]
|
||||
WriteStartHour --> WriteStartMinute["写入开始分钟"]
|
||||
WriteStartMinute --> ParseEndTime["解析结束时间"]
|
||||
ParseEndTime --> WriteEndHour["写入结束小时"]
|
||||
WriteEndHour --> WriteEndMinute["写入结束分钟"]
|
||||
WriteEndMinute --> ConvertElecPrice["转换电费价格"]
|
||||
ConvertElecPrice --> WriteElecPrice["写入4字节电费"]
|
||||
WriteElecPrice --> ConvertServPrice["转换服务费价格"]
|
||||
ConvertServPrice --> WriteServPrice["写入4字节服务费"]
|
||||
WriteServPrice --> NextPeriod{"还有更多时间段?"}
|
||||
NextPeriod --> |是| ProcessPeriods
|
||||
NextPeriod --> |否| CachePricingId["缓存计费ID"]
|
||||
CachePricingId --> Send["调用encodeAndWriteFlush发送"]
|
||||
Send --> End([结束])
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
|
||||
- [LvnengV340SetPricingModelDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340SetPricingModelDLCmd.java#L0-L98)
|
||||
|
||||
**本文档引用的文件**
|
||||
|
||||
- [LvnengV340SetPricingModelDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340SetPricingModelDLCmd.java)
|
||||
|
||||
## 消息序列化过程
|
||||
|
||||
绿能协议v3.40的消息序列化过程由`AbstractLvnengCmdExe`类的`encode`
|
||||
方法实现。该方法按照协议规范构建完整的下行消息帧,格式为:帧头(2) + 长度(2) + 加密标识(1) + 序号(1) + 命令字(2) + 数据域(
|
||||
n) + 校验和(1)。
|
||||
|
||||
序列化过程分为以下几个步骤:
|
||||
|
||||
1. 计算总长度:数据域长度 + 9字节固定头尾
|
||||
2. 构建消息头和数据域:依次写入帧头、长度、加密标识、序号、命令字和数据域
|
||||
3. 准备校验和计算数据:命令字 + 数据域
|
||||
4. 计算并写入校验和:使用`ByteUtil.calculateSum`方法计算累加和
|
||||
5. 转换为字节数组:使用`ByteUtil.toBytes`方法将`ByteBuf`转换为字节数组
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始]) --> CalculateLength["计算总长度 = 数据域长度 + 9"]
|
||||
CalculateLength --> BuildHeader["构建消息头"]
|
||||
BuildHeader --> WriteHead["写入帧头(0xAAF5)"]
|
||||
WriteHead --> WriteLength["写入长度(小端序)"]
|
||||
WriteLength --> WriteEncryption["写入加密标识(0x10)"]
|
||||
WriteEncryption --> WriteSeqNo["写入序号"]
|
||||
WriteSeqNo --> WriteCmd["写入命令字(小端序)"]
|
||||
WriteCmd --> WriteData["写入数据域"]
|
||||
WriteData --> PrepareSum["准备校验和数据(命令字+数据域)"]
|
||||
PrepareSum --> CalculateSum["计算累加和(ByteUtil.calculateSum)"]
|
||||
CalculateSum --> WriteSum["写入校验和"]
|
||||
WriteSum --> ConvertBytes["转换为字节数组(ByteUtil.toBytes)"]
|
||||
ConvertBytes --> End([结束])
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
|
||||
- [AbstractLvnengCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/AbstractLvnengCmdExe.java#L30-L60)
|
||||
|
||||
**本文档引用的文件**
|
||||
|
||||
- [AbstractLvnengCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/AbstractLvnengCmdExe.java)
|
||||
|
||||
## 指令重试与超时处理
|
||||
|
||||
绿能协议v3.40的指令重试与超时处理机制主要通过会话层的请求缓存和定时任务实现。`ProtocolSession`类维护了一个`requestCache`
|
||||
,用于存储待确认的请求。该缓存使用Caffeine构建,具有以下特性:
|
||||
|
||||
- 初始容量:1000
|
||||
- 最大容量:1000
|
||||
- 过期策略:访问后1分钟过期
|
||||
|
||||
当发送下行指令时,相关的请求ID和业务数据会被存入缓存。如果在规定时间内未收到设备的响应,缓存项将自动过期,触发重试逻辑。
|
||||
`TcpSession`类维护了一个原子整数`sequenceNumber`,用于生成消息序号,确保每条消息的唯一性。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class ProtocolSession {
|
||||
-requestCache Cache~String, Object~
|
||||
+onDownlink(DownlinkRequestMessage)
|
||||
+close(SessionCloseReason)
|
||||
}
|
||||
class TcpSession {
|
||||
-sequenceNumber AtomicInteger
|
||||
+nextSeqNo(SequenceNumberLength)
|
||||
+writeAndFlush(ByteBuf)
|
||||
}
|
||||
ProtocolSession "1" -- "1" TcpSession
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
|
||||
- [ProtocolSession.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/ProtocolSession.java#L46-L77)
|
||||
- [TcpSession.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpSession.java#L41-L98)
|
||||
|
||||
**本文档引用的文件**
|
||||
|
||||
- [ProtocolSession.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/ProtocolSession.java)
|
||||
- [TcpSession.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpSession.java)
|
||||
|
||||
## 完整时序图与报文格式示例
|
||||
|
||||
### 完整时序图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant AppService as "应用服务"
|
||||
participant ProtocolService as "协议服务"
|
||||
participant ProtocolProcessor as "协议处理器"
|
||||
participant Device as "设备"
|
||||
Client->>AppService : 调用setPricing(SetPricingDTO)
|
||||
AppService->>ProtocolService : 构建DownlinkRequestMessage
|
||||
ProtocolService->>ProtocolProcessor : 发送下行消息
|
||||
ProtocolProcessor->>ProtocolProcessor : 转换命令码
|
||||
ProtocolProcessor->>ProtocolProcessor : 构建消息体
|
||||
ProtocolProcessor->>ProtocolProcessor : 序列化消息
|
||||
ProtocolProcessor->>Device : 发送报文
|
||||
Device->>ProtocolProcessor : 返回响应
|
||||
ProtocolProcessor->>ProtocolService : 处理上行消息
|
||||
ProtocolService->>AppService : 通知结果
|
||||
AppService->>Client : 返回成功
|
||||
```
|
||||
|
||||
### 报文格式示例
|
||||
|
||||
以远程停止充电指令为例,完整的报文格式如下:
|
||||
|
||||
| 字段 | 长度(字节) | 值(十六进制) | 说明 |
|
||||
|------|--------|---------------------|----------------------|
|
||||
| 帧头 | 2 | AAF5 | 固定值 |
|
||||
| 长度 | 2 | 002C | 总长度44字节 |
|
||||
| 加密标识 | 1 | 10 | 固定值 |
|
||||
| 序号 | 1 | 01 | 消息序号 |
|
||||
| 命令字 | 2 | 0005 | REMOTE_STOP_CHARGING |
|
||||
| 数据域 | 44 | 0000010200010455... | 消息体 |
|
||||
| 校验和 | 1 | XX | 累加和校验 |
|
||||
|
||||
**本文档引用的文件**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java)
|
||||
- [AbstractLvnengCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/AbstractLvnengCmdExe.java)
|
||||
- [LvnengV340RemoteStopDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RemoteStopDLCmd.java)
|
||||
|
||||
## 结论
|
||||
|
||||
本文档详细阐述了绿能协议v3.40的下行消息处理流程。系统通过gRPC接口接收外部请求,经由`LvnengProtocolMessageProcessor`
|
||||
进行命令解析和路由,使用`LvnengDownlinkCmdConverter`将通用命令转换为协议特定命令码,并通过具体的命令执行器(如
|
||||
`LvnengV340RemoteStopDLCmd`和`LvnengV340SetPricingModelDLCmd`
|
||||
)生成相应的下行指令。消息序列化过程严格遵循协议规范,包含帧头、长度、加密标识、序号、命令字、数据域和校验和等字段。指令重试与超时处理通过会话层的请求缓存机制实现,确保了通信的可靠性。整个流程设计合理,模块职责清晰,为充电桩远程控制提供了稳定可靠的基础。
|
||||
522
docs/核心模块详解/协议实现模块/绿能协议实现/核心架构.md
Normal file
522
docs/核心模块详解/协议实现模块/绿能协议实现/核心架构.md
Normal file
@@ -0,0 +1,522 @@
|
||||
# 绿能协议v3.40核心架构设计
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java)
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java)
|
||||
- [LvnengProtocolConstants.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolConstants.java)
|
||||
- [ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java)
|
||||
- [ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java)
|
||||
- [LvnengUplinkMessage.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengUplinkMessage.java)
|
||||
- [LvnengDwonlinkMessage.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengDwonlinkMessage.java)
|
||||
- [LvnengUplinkCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengUplinkCmdExe.java)
|
||||
- [LvnengDownlinkCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengDownlinkCmdExe.java)
|
||||
- [AbstractLvnengCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/AbstractLvnengCmdExe.java)
|
||||
- [LvnengV340LoginULCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340LoginULCmd.java)
|
||||
- [LvnengV340RemoteStopDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RemoteStopDLCmd.java)
|
||||
- [TcpListener.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpListener.java)
|
||||
- [ProtocolCommandRouter.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/routing/ProtocolCommandRouter.java)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
|
||||
1. [引言](#引言)
|
||||
2. [项目结构概览](#项目结构概览)
|
||||
3. [核心组件架构](#核心组件架构)
|
||||
4. [协议启动器设计](#协议启动器设计)
|
||||
5. [消息处理机制](#消息处理机制)
|
||||
6. [协议帧结构设计](#协议帧结构设计)
|
||||
7. [命令路由系统](#命令路由系统)
|
||||
8. [组件交互时序](#组件交互时序)
|
||||
9. [性能优化考虑](#性能优化考虑)
|
||||
10. [总结](#总结)
|
||||
|
||||
## 引言
|
||||
|
||||
绿能协议v3.40是JCPP(充电点协议平台)中的一个重要组成部分,专门用于处理绿能品牌的充电设备通信协议。该协议采用模块化设计,通过继承和组合模式实现了高度可扩展的架构。本文档将深入分析其核心架构设计,包括协议启动器、消息处理器、帧结构设计以及组件间的协作机制。
|
||||
|
||||
## 项目结构概览
|
||||
|
||||
绿能协议v3.40的项目结构遵循分层架构原则,主要分为以下几个层次:
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "应用层"
|
||||
Bootstrap[LvnengV340ProtocolBootstrap<br/>协议启动器]
|
||||
end
|
||||
subgraph "业务层"
|
||||
Processor[LvnengProtocolMessageProcessor<br/>消息处理器]
|
||||
Constants[LvnengProtocolConstants<br/>协议常量]
|
||||
end
|
||||
subgraph "命令层"
|
||||
UplinkCmd[LvnengUplinkCmdExe<br/>上行命令基类]
|
||||
DownlinkCmd[LvnengDownlinkCmdExe<br/>下行命令基类]
|
||||
AbstractCmd[AbstractLvnengCmdExe<br/>协议基础类]
|
||||
end
|
||||
subgraph "数据模型层"
|
||||
UplinkMsg[LvnengUplinkMessage<br/>上行消息模型]
|
||||
DownlinkMsg[LvnengDwonlinkMessage<br/>下行消息模型]
|
||||
end
|
||||
subgraph "基础设施层"
|
||||
BaseBootstrap[ProtocolBootstrap<br/>基础启动器]
|
||||
BaseProcessor[ProtocolMessageProcessor<br/>基础消息处理器]
|
||||
Router[ProtocolCommandRouter<br/>命令路由器]
|
||||
end
|
||||
Bootstrap --> Processor
|
||||
Processor --> UplinkCmd
|
||||
Processor --> DownlinkCmd
|
||||
UplinkCmd --> AbstractCmd
|
||||
DownlinkCmd --> AbstractCmd
|
||||
Processor --> UplinkMsg
|
||||
Processor --> DownlinkMsg
|
||||
Bootstrap --> BaseBootstrap
|
||||
Processor --> BaseProcessor
|
||||
Processor --> Router
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L1-L42)
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L1-L187)
|
||||
- [ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java#L1-L127)
|
||||
|
||||
## 核心组件架构
|
||||
|
||||
### 组件关系图
|
||||
|
||||
绿能协议v3.40的核心架构采用了经典的分层设计模式,各组件之间通过接口进行解耦:
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class ProtocolBootstrap {
|
||||
<<abstract>>
|
||||
+ProtocolContext protocolContext
|
||||
+ProtocolCfg protocolCfg
|
||||
+Listener listener
|
||||
+Forwarder forwarder
|
||||
+init() void
|
||||
+destroy() void
|
||||
#getProtocolName()* String
|
||||
#_init()* void
|
||||
#_destroy()* void
|
||||
#messageProcessor()* ProtocolMessageProcessor
|
||||
}
|
||||
class LvnengV340ProtocolBootstrap {
|
||||
+String PROTOCOL_NAME
|
||||
+getProtocolName() String
|
||||
+_init() void
|
||||
+_destroy() void
|
||||
+messageProcessor() LvnengProtocolMessageProcessor
|
||||
}
|
||||
class ProtocolMessageProcessor {
|
||||
<<abstract>>
|
||||
+Forwarder forwarder
|
||||
+ProtocolContext protocolContext
|
||||
+uplinkHandleAsync() void
|
||||
+downlinkHandle() void
|
||||
#uplinkHandle()* void
|
||||
#doDownlinkHandle()* void
|
||||
}
|
||||
class LvnengProtocolMessageProcessor {
|
||||
-ProtocolCommandRouter~LvnengUplinkCmdExe~ uplinkRouter
|
||||
-ProtocolCommandRouter~LvnengDownlinkCmdExe~ downlinkRouter
|
||||
-DownlinkCmdConverter downlinkCmdConverter
|
||||
+uplinkHandle() void
|
||||
+doDownlinkHandle() void
|
||||
-exeCmd() void
|
||||
}
|
||||
class LvnengUplinkCmdExe {
|
||||
<<abstract>>
|
||||
+execute() void
|
||||
#uplinkMessageBuilder() Builder
|
||||
}
|
||||
class LvnengDownlinkCmdExe {
|
||||
<<abstract>>
|
||||
+execute() void
|
||||
}
|
||||
class AbstractLvnengCmdExe {
|
||||
#encode() byte[]
|
||||
#encodeAndWriteFlush() void
|
||||
}
|
||||
ProtocolBootstrap <|-- LvnengV340ProtocolBootstrap
|
||||
ProtocolMessageProcessor <|-- LvnengProtocolMessageProcessor
|
||||
LvnengUplinkCmdExe <|-- AbstractLvnengCmdExe
|
||||
LvnengDownlinkCmdExe <|-- AbstractLvnengCmdExe
|
||||
LvnengProtocolMessageProcessor --> LvnengUplinkCmdExe
|
||||
LvnengProtocolMessageProcessor --> LvnengDownlinkCmdExe
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java#L25-L127)
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L15-L42)
|
||||
- [ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java#L20-L78)
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java#L1-L127)
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L1-L42)
|
||||
- [ProtocolMessageProcessor.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolMessageProcessor.java#L1-L78)
|
||||
|
||||
## 协议启动器设计
|
||||
|
||||
### LvnengV340ProtocolBootstrap核心实现
|
||||
|
||||
LvnengV340ProtocolBootstrap作为绿能协议v3.40的主要入口点,继承自ProtocolBootstrap抽象类,并实现了协议特有的初始化和销毁逻辑。
|
||||
|
||||
#### 继承关系与方法实现
|
||||
|
||||
协议启动器通过以下方式实现核心功能:
|
||||
|
||||
1. **协议名称管理**:通过`getProtocolName()`方法返回协议标识
|
||||
2. **初始化逻辑**:重写了`_init()`方法,目前为空实现
|
||||
3. **资源清理**:重写了`_destroy()`方法,目前为空实现
|
||||
4. **消息处理器创建**:通过`messageProcessor()`方法创建具体的处理器实例
|
||||
|
||||
#### 启动流程时序图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as 应用程序
|
||||
participant Bootstrap as LvnengV340ProtocolBootstrap
|
||||
participant Base as ProtocolBootstrap
|
||||
participant Listener as TcpListener
|
||||
participant Forwarder as Forwarder
|
||||
participant Processor as LvnengProtocolMessageProcessor
|
||||
App->>Bootstrap : 实例化启动器
|
||||
App->>Base : 调用init()
|
||||
Base->>Base : 加载协议配置
|
||||
Base->>Forwarder : 创建转发器
|
||||
Base->>Listener : 创建TCP监听器
|
||||
Base->>Bootstrap : 调用_init()
|
||||
Bootstrap-->>Base : 初始化完成
|
||||
Base-->>App : 启动成功
|
||||
Note over App,Processor : 协议运行阶段
|
||||
App->>Listener : 接收客户端连接
|
||||
Listener->>Processor : 处理上行消息
|
||||
Processor->>Processor : 解析协议帧
|
||||
Processor->>Processor : 路由命令处理
|
||||
Processor-->>App : 返回处理结果
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L25-L42)
|
||||
- [ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java#L45-L85)
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L1-L42)
|
||||
- [ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java#L45-L85)
|
||||
|
||||
## 消息处理机制
|
||||
|
||||
### LvnengProtocolMessageProcessor核心功能
|
||||
|
||||
LvnengProtocolMessageProcessor是绿能协议的消息处理中心,负责处理上行和下行消息流。它继承自ProtocolMessageProcessor,并实现了协议特定的消息解析和路由逻辑。
|
||||
|
||||
#### 消息处理架构
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([接收原始消息]) --> ParseHeader[解析帧头信息]
|
||||
ParseHeader --> ValidateLength{验证消息长度}
|
||||
ValidateLength --> |长度异常| LogWarning[记录警告日志]
|
||||
ValidateLength --> |长度正常| ExtractBody[提取消息体]
|
||||
ExtractBody --> VerifyChecksum[验证校验和]
|
||||
VerifyChecksum --> ChecksumValid{校验和有效?}
|
||||
ChecksumValid --> |无效| LogError[记录错误日志]
|
||||
ChecksumValid --> |有效| BuildMessage[构建消息对象]
|
||||
BuildMessage --> RouteCommand[路由命令处理]
|
||||
RouteCommand --> ExecuteCmd[执行命令]
|
||||
ExecuteCmd --> SendResponse[发送响应]
|
||||
LogWarning --> End([处理结束])
|
||||
LogError --> End
|
||||
SendResponse --> End
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L55-L120)
|
||||
|
||||
#### 上行消息处理流程
|
||||
|
||||
上行消息处理包含以下关键步骤:
|
||||
|
||||
1. **帧头解析**:读取起始符、长度、加密标识、序列号和命令码
|
||||
2. **长度验证**:确保消息长度符合最小要求
|
||||
3. **消息体提取**:读取实际的数据内容
|
||||
4. **校验和验证**:使用CRC算法验证数据完整性
|
||||
5. **消息对象构建**:封装为LvnengUplinkMessage对象
|
||||
6. **命令路由**:根据命令类型路由到相应的处理器
|
||||
|
||||
#### 下行消息处理流程
|
||||
|
||||
下行消息处理采用统一的处理模式:
|
||||
|
||||
1. **命令转换**:将通用命令转换为协议特定命令
|
||||
2. **消息构建**:创建LvnengDwonlinkMessage对象
|
||||
3. **命令执行**:调用相应的命令处理器
|
||||
4. **响应发送**:将处理结果发送给客户端
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L55-L187)
|
||||
|
||||
## 协议帧结构设计
|
||||
|
||||
### 帧结构定义
|
||||
|
||||
绿能协议v3.40采用固定格式的帧结构,确保消息的可靠传输和解析:
|
||||
|
||||
| 字段 | 长度(字节) | 描述 |
|
||||
|------|--------|-------------------|
|
||||
| 起始符 | 2 | 固定值0xAAF5,标识帧开始 |
|
||||
| 长度 | 2 | 包含整个帧的总长度(小端序) |
|
||||
| 加密标识 | 1 | 0x10表示加密,0x00表示明文 |
|
||||
| 序列号 | 1 | 用于消息顺序控制 |
|
||||
| 命令码 | 2 | 指示消息类型(小端序) |
|
||||
| 数据域 | 变长 | 实际消息内容 |
|
||||
| 校验和 | 1 | CRC8校验值 |
|
||||
|
||||
#### 帧结构示例
|
||||
|
||||
```
|
||||
+------------------+------------------+------------------+------------------+
|
||||
| 起始符 | 长度 | 加密标识 | 序列号 | 命令码 |
|
||||
| (2字节) | (2字节) | (1字节) | (1字节) | (2字节) |
|
||||
+------------------+------------------+------------------+------------------+
|
||||
| |
|
||||
| 数据域 |
|
||||
| |
|
||||
+---------------------------------------------------------------+
|
||||
| 校验和 |
|
||||
| (1字节) |
|
||||
+--------------+
|
||||
```
|
||||
|
||||
### 校验和算法
|
||||
|
||||
协议采用CRC8算法进行数据完整性验证:
|
||||
|
||||
1. **校验和计算**:对命令码和数据域进行CRC8计算
|
||||
2. **校验和验证**:接收端重新计算并比较
|
||||
3. **错误处理**:校验失败时记录日志并丢弃消息
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L30-L35)
|
||||
- [AbstractLvnengCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/AbstractLvnengCmdExe.java#L50-L70)
|
||||
|
||||
## 命令路由系统
|
||||
|
||||
### ProtocolCommandRouter设计
|
||||
|
||||
ProtocolCommandRouter提供了基于协议名和命令字的智能路由功能,支持多版本协议的统一管理:
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class ProtocolCommandRouter {
|
||||
-Map~String,T~ executorMap
|
||||
+ProtocolCommandRouter(scanBaseClass, executorFilter)
|
||||
+getExecutor(protocolName, cmd) T
|
||||
-initializeRoutes() void
|
||||
-registerExecutor() void
|
||||
-buildKey() String
|
||||
}
|
||||
class ProtocolCmd {
|
||||
<<annotation>>
|
||||
+int value()
|
||||
+String[] protocolNames()
|
||||
}
|
||||
class LvnengUplinkCmdExe {
|
||||
<<abstract>>
|
||||
+execute() void
|
||||
}
|
||||
class LvnengV340LoginULCmd {
|
||||
+execute() void
|
||||
}
|
||||
ProtocolCommandRouter --> LvnengUplinkCmdExe
|
||||
LvnengUplinkCmdExe --> ProtocolCmd
|
||||
LvnengV340LoginULCmd --|> LvnengUplinkCmdExe
|
||||
ProtocolCmd --> LvnengV340LoginULCmd
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [ProtocolCommandRouter.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/routing/ProtocolCommandRouter.java#L25-L105)
|
||||
- [LvnengUplinkCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengUplinkCmdExe.java#L19-L39)
|
||||
|
||||
### 命令执行器层次结构
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AbstractLvnengCmdExe {
|
||||
#byte[] encode()
|
||||
#encodeAndWriteFlush()
|
||||
#DOWNLINK_CMD_CONVERTER
|
||||
#LVNENG_HEAD
|
||||
#LVNENG_ENCRYPTION_FLAG
|
||||
}
|
||||
class LvnengUplinkCmdExe {
|
||||
<<abstract>>
|
||||
+execute() void
|
||||
#uplinkMessageBuilder()
|
||||
}
|
||||
class LvnengDownlinkCmdExe {
|
||||
<<abstract>>
|
||||
+execute() void
|
||||
}
|
||||
class LvnengV340LoginULCmd {
|
||||
+execute() void
|
||||
}
|
||||
class LvnengV340RemoteStopDLCmd {
|
||||
+execute() void
|
||||
}
|
||||
AbstractLvnengCmdExe <|-- LvnengUplinkCmdExe
|
||||
AbstractLvnengCmdExe <|-- LvnengDownlinkCmdExe
|
||||
LvnengUplinkCmdExe <|-- LvnengV340LoginULCmd
|
||||
LvnengDownlinkCmdExe <|-- LvnengV340RemoteStopDLCmd
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [AbstractLvnengCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/AbstractLvnengCmdExe.java#L18-L120)
|
||||
- [LvnengUplinkCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengUplinkCmdExe.java#L19-L39)
|
||||
- [LvnengDownlinkCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengDownlinkCmdExe.java#L14-L18)
|
||||
|
||||
### 命令处理时序图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Session as TcpSession
|
||||
participant Processor as LvnengProtocolMessageProcessor
|
||||
participant Router as ProtocolCommandRouter
|
||||
participant Executor as 命令执行器
|
||||
participant Forwarder as Forwarder
|
||||
Session->>Processor : uplinkHandleAsync()
|
||||
Processor->>Processor : 解析消息帧
|
||||
Processor->>Router : getExecutor(protocolName, cmd)
|
||||
Router-->>Processor : 返回命令执行器
|
||||
Processor->>Executor : execute(session, message, context)
|
||||
Executor->>Executor : 处理业务逻辑
|
||||
Executor->>Forwarder : 发送上行消息
|
||||
Forwarder-->>Session : 返回处理结果
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L150-L187)
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [ProtocolCommandRouter.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/routing/ProtocolCommandRouter.java#L25-L105)
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L150-L187)
|
||||
|
||||
## 组件交互时序
|
||||
|
||||
### 协议初始化时序
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as 应用程序
|
||||
participant Bootstrap as LvnengV340ProtocolBootstrap
|
||||
participant Config as ProtocolContext
|
||||
participant Forwarder as Forwarder
|
||||
participant Listener as TcpListener
|
||||
participant Processor as LvnengProtocolMessageProcessor
|
||||
App->>Bootstrap : 实例化
|
||||
App->>Bootstrap : init()
|
||||
Bootstrap->>Config : loadConfig(protocolName)
|
||||
Config-->>Bootstrap : 返回配置信息
|
||||
Bootstrap->>Forwarder : 创建转发器
|
||||
Forwarder-->>Bootstrap : 转发器实例
|
||||
Bootstrap->>Listener : 创建TCP监听器
|
||||
Listener->>Processor : 创建消息处理器
|
||||
Processor->>Processor : 初始化命令路由器
|
||||
Processor-->>Listener : 处理器就绪
|
||||
Listener-->>Bootstrap : 监听器就绪
|
||||
Bootstrap->>Bootstrap : _init()
|
||||
Bootstrap-->>App : 初始化完成
|
||||
Note over App,Processor : 协议服务已启动
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L25-L42)
|
||||
- [ProtocolBootstrap.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/ProtocolBootstrap.java#L45-L85)
|
||||
|
||||
### 消息处理时序
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as 客户端
|
||||
participant Listener as TcpListener
|
||||
participant Processor as LvnengProtocolMessageProcessor
|
||||
participant Router as ProtocolCommandRouter
|
||||
participant CmdExe as 命令执行器
|
||||
participant Forwarder as Forwarder
|
||||
Client->>Listener : 发送原始消息
|
||||
Listener->>Processor : uplinkHandleAsync()
|
||||
Processor->>Processor : 解析协议帧
|
||||
Processor->>Processor : 验证校验和
|
||||
Processor->>Router : getExecutor(protocolName, cmd)
|
||||
Router-->>Processor : 返回执行器
|
||||
Processor->>CmdExe : execute(session, message, context)
|
||||
CmdExe->>CmdExe : 处理业务逻辑
|
||||
CmdExe->>Forwarder : sendMessage(uplinkQueueMessage)
|
||||
Forwarder-->>Client : 返回处理结果
|
||||
Note over Client,Forwarder : 异步处理流程
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L55-L120)
|
||||
- [TcpListener.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/listener/tcp/TcpListener.java#L40-L70)
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L25-L42)
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L55-L120)
|
||||
|
||||
## 性能优化考虑
|
||||
|
||||
### 异步处理机制
|
||||
|
||||
协议采用异步处理模式,通过线程池管理消息处理:
|
||||
|
||||
1. **线程池隔离**:使用分片线程池避免资源竞争
|
||||
2. **异步消息处理**:上行消息处理采用异步模式
|
||||
3. **内存管理**:及时释放ByteBuf资源
|
||||
|
||||
### 内存优化策略
|
||||
|
||||
1. **对象复用**:重用消息对象减少GC压力
|
||||
2. **缓冲区管理**:合理设置TCP缓冲区大小
|
||||
3. **序列号管理**:维护序列号状态避免重复
|
||||
|
||||
### 并发控制
|
||||
|
||||
1. **无锁设计**:使用ConcurrentHashMap实现线程安全
|
||||
2. **原子操作**:利用CAS操作提高并发性能
|
||||
3. **批量处理**:支持批量消息处理
|
||||
|
||||
## 总结
|
||||
|
||||
绿能协议v3.40的核心架构展现了优秀的软件设计原则:
|
||||
|
||||
### 设计亮点
|
||||
|
||||
1. **模块化设计**:清晰的分层架构,职责分离明确
|
||||
2. **可扩展性**:基于注解的命令路由系统,易于添加新命令
|
||||
3. **可靠性**:完善的错误处理和校验机制
|
||||
4. **性能优化**:异步处理和资源管理策略
|
||||
|
||||
### 架构优势
|
||||
|
||||
1. **高内聚低耦合**:各组件职责单一,依赖关系清晰
|
||||
2. **可测试性**:良好的接口设计便于单元测试
|
||||
3. **可维护性**:清晰的代码结构和文档
|
||||
4. **可监控性**:完整的健康检查和统计指标
|
||||
|
||||
该架构为绿能协议v3.40提供了稳定、高效、可扩展的通信基础,能够满足现代充电站系统的复杂需求。
|
||||
526
docs/核心模块详解/协议实现模块/绿能协议实现/绿能协议实现.md
Normal file
526
docs/核心模块详解/协议实现模块/绿能协议实现/绿能协议实现.md
Normal file
@@ -0,0 +1,526 @@
|
||||
# 绿能协议实现
|
||||
|
||||
<cite>
|
||||
**本文档中引用的文件**
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java)
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java)
|
||||
- [LvnengUplinkCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengUplinkCmdExe.java)
|
||||
- [LvnengDownlinkCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengDownlinkCmdExe.java)
|
||||
- [LvnengDownlinkCmdConverter.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/mapping/LvnengDownlinkCmdConverter.java)
|
||||
- [LvnengV340RealTimeDataULCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RealTimeDataULCmd.java)
|
||||
- [LvnengUplinkMessage.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengUplinkMessage.java)
|
||||
- [LvnengDwonlinkMessage.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengDwonlinkMessage.java)
|
||||
- [LvnengProtocolConstants.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolConstants.java)
|
||||
- [ProtocolCommandRouter.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/routing/ProtocolCommandRouter.java)
|
||||
- [AbstractLvnengCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/AbstractLvnengCmdExe.java)
|
||||
- [LvnengV340SetPricingModelDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340SetPricingModelDLCmd.java)
|
||||
- [LvnengV340RemoteStopDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RemoteStopDLCmd.java)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概览](#架构概览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [协议消息处理流程](#协议消息处理流程)
|
||||
7. [命令路由机制](#命令路由机制)
|
||||
8. [数据包格式与处理](#数据包格式与处理)
|
||||
9. [实际应用示例](#实际应用示例)
|
||||
10. [性能考虑](#性能考虑)
|
||||
11. [故障排除指南](#故障排除指南)
|
||||
12. [总结](#总结)
|
||||
|
||||
## 简介
|
||||
|
||||
绿能协议(v3.40)是一个专为电动汽车充电站设计的通信协议,实现了充电桩与服务器之间的可靠数据交换。该协议采用TCP传输层,具有严格的消息帧结构、校验和验证机制和完善的命令处理体系。
|
||||
|
||||
本文档深入分析了绿能协议v3.40的实现细节,重点关注LvnengV340ProtocolBootstrap的配置机制、消息帧结构的设计、以及LvnengProtocolMessageProcessor的处理逻辑。同时详细阐述了上行命令处理器和下行指令生成机制,展示了从gRPC调用到协议报文构建的完整流程。
|
||||
|
||||
## 项目结构
|
||||
|
||||
绿能协议模块采用分层架构设计,主要包含以下核心包结构:
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "协议核心模块"
|
||||
A[jcpp-protocol-lvneng]
|
||||
A --> B[v340 - 协议版本实现]
|
||||
A --> C[mapping - 命令映射]
|
||||
A --> D[enums - 枚举定义]
|
||||
A --> E[cmd - 命令处理器]
|
||||
end
|
||||
subgraph "基础框架"
|
||||
F[jcpp-protocol-api]
|
||||
G[jcpp-protocol-bootstrap]
|
||||
H[jcpp-protocol-yunkuaichong]
|
||||
end
|
||||
subgraph "基础设施"
|
||||
I[jcpp-infrastructure-util]
|
||||
J[jcpp-infrastructure-cache]
|
||||
K[jcpp-infrastructure-queue]
|
||||
end
|
||||
A --> F
|
||||
F --> I
|
||||
F --> J
|
||||
F --> K
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L1-L42)
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L1-L187)
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L1-L42)
|
||||
- [LvnengProtocolConstants.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolConstants.java#L1-L38)
|
||||
|
||||
## 核心组件
|
||||
|
||||
绿能协议的核心组件包括协议引导器、消息处理器、命令执行器和命令转换器等关键模块。这些组件协同工作,实现了完整的协议栈功能。
|
||||
|
||||
### 协议引导器(LvnengV340ProtocolBootstrap)
|
||||
|
||||
协议引导器负责初始化和配置整个协议栈,它继承自基础的ProtocolBootstrap类,提供了协议特定的初始化逻辑。
|
||||
|
||||
### 消息处理器(LvnengProtocolMessageProcessor)
|
||||
|
||||
消息处理器是协议的核心,负责解析和处理所有上行和下行消息。它实现了严格的帧结构解析、校验和验证和命令路由功能。
|
||||
|
||||
### 命令执行器基类
|
||||
|
||||
系统提供了两个抽象基类:LvnengUplinkCmdExe用于处理上行命令,LvnengDownlinkCmdExe用于处理下行命令。它们都继承自AbstractLvnengCmdExe,提供了统一的编码和发送机制。
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L15-L42)
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L25-L50)
|
||||
|
||||
## 架构概览
|
||||
|
||||
绿能协议采用事件驱动的异步处理架构,通过Netty框架实现高效的网络通信。整个架构分为消息接收层、协议处理层、命令执行层和业务逻辑层。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "网络层"
|
||||
A[TCP连接] --> B[消息解码器]
|
||||
B --> C[帧解析器]
|
||||
end
|
||||
subgraph "协议处理层"
|
||||
C --> D[LvnengProtocolMessageProcessor]
|
||||
D --> E[上行命令路由]
|
||||
D --> F[下行命令路由]
|
||||
end
|
||||
subgraph "命令执行层"
|
||||
E --> G[LvnengUplinkCmdExe]
|
||||
F --> H[LvnengDownlinkCmdExe]
|
||||
G --> I[业务逻辑处理]
|
||||
H --> J[协议报文生成]
|
||||
end
|
||||
subgraph "数据转换层"
|
||||
K[LvnengDownlinkCmdConverter] --> H
|
||||
L[消息对象封装] --> G
|
||||
L --> H
|
||||
end
|
||||
subgraph "输出层"
|
||||
I --> M[UplinkQueueMessage]
|
||||
J --> N[编码后的字节数组]
|
||||
end
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L40-L80)
|
||||
- [ProtocolCommandRouter.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/routing/ProtocolCommandRouter.java#L20-L60)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### LvnengV340ProtocolBootstrap配置机制
|
||||
|
||||
LvnengV340ProtocolBootstrap作为协议的入口点,负责建立TCP监听器和初始化协议上下文。它通过注解@ProtocolComponent标记协议名称,并重写父类方法提供具体的初始化逻辑。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class LvnengV340ProtocolBootstrap {
|
||||
+String PROTOCOL_NAME
|
||||
+getProtocolName() String
|
||||
+_init() void
|
||||
+_destroy() void
|
||||
+messageProcessor() ProtocolMessageProcessor
|
||||
}
|
||||
class ProtocolBootstrap {
|
||||
<<abstract>>
|
||||
+forwarder Forwarder
|
||||
+protocolContext ProtocolContext
|
||||
+messageProcessor() ProtocolMessageProcessor
|
||||
}
|
||||
class LvnengProtocolMessageProcessor {
|
||||
+uplinkRouter ProtocolCommandRouter
|
||||
+downlinkRouter ProtocolCommandRouter
|
||||
+downlinkCmdConverter DownlinkCmdConverter
|
||||
+uplinkHandle(ListenerToHandlerMsg) void
|
||||
+doDownlinkHandle(SessionToHandlerMsg) void
|
||||
}
|
||||
LvnengV340ProtocolBootstrap --|> ProtocolBootstrap
|
||||
LvnengV340ProtocolBootstrap --> LvnengProtocolMessageProcessor : creates
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengV340ProtocolBootstrap.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/LvnengV340ProtocolBootstrap.java#L15-L42)
|
||||
|
||||
### 消息帧结构设计
|
||||
|
||||
绿能协议采用严格的帧结构设计,确保消息的可靠传输和完整性验证。帧结构包括起始标志、长度字段、加密标识、序列号、命令字和校验和等关键字段。
|
||||
|
||||
| 字段名称 | 长度(字节) | 描述 |
|
||||
|------|--------|-------------------|
|
||||
| 起始标志 | 2 | 固定值0xAAF5,标识帧开始 |
|
||||
| 数据长度 | 2 | 包含头部和校验和在内的总长度 |
|
||||
| 加密标识 | 1 | 0x10表示加密,0x00表示明文 |
|
||||
| 序列号 | 1 | 用于消息顺序控制 |
|
||||
| 命令字 | 2 | 标识具体命令类型 |
|
||||
| 数据域 | 可变 | 实际消息内容 |
|
||||
| 校验和 | 1 | 对命令字和数据域的校验 |
|
||||
|
||||
### LvnengProtocolMessageProcessor消息处理
|
||||
|
||||
消息处理器实现了复杂的消息解析逻辑,包括帧头解析、长度验证、校验和计算和命令路由等功能。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as 客户端
|
||||
participant Processor as LvnengProtocolMessageProcessor
|
||||
participant Router as 命令路由器
|
||||
participant Executor as 命令执行器
|
||||
participant Forwarder as 消息转发器
|
||||
Client->>Processor : 接收原始消息
|
||||
Processor->>Processor : 解析帧头信息
|
||||
Processor->>Processor : 验证消息长度
|
||||
Processor->>Processor : 读取消息体
|
||||
Processor->>Processor : 计算并验证校验和
|
||||
Processor->>Router : 查找命令执行器
|
||||
Router->>Executor : 返回匹配的执行器
|
||||
Executor->>Executor : 执行业务逻辑
|
||||
Executor->>Forwarder : 转发处理结果
|
||||
Forwarder->>Client : 发送响应消息
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L50-L120)
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L25-L187)
|
||||
|
||||
## 协议消息处理流程
|
||||
|
||||
### 上行消息处理流程
|
||||
|
||||
上行消息处理涉及复杂的帧解析和命令执行过程。处理器首先验证消息格式,然后提取各个字段,最后通过命令路由机制找到对应的执行器。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([接收上行消息]) --> ParseHeader["解析帧头信息<br/>起始标志 + 长度 + 加密标识 + 序列号 + 命令字"]
|
||||
ParseHeader --> ValidateLength{"验证消息长度<br/>dataLength >= 9?"}
|
||||
ValidateLength --> |否| LogWarning["记录警告日志"]
|
||||
ValidateLength --> |是| ReadBody["读取消息体<br/>msgBodyLength = dataLength - 9"]
|
||||
ReadBody --> CalcChecksum["计算校验和<br/>sumData = 命令字 + 数据域"]
|
||||
CalcChecksum --> VerifyChecksum{"校验和验证"}
|
||||
VerifyChecksum --> |失败| LogError["记录错误日志"]
|
||||
VerifyChecksum --> |成功| BuildMessage["构建LvnengUplinkMessage对象"]
|
||||
BuildMessage --> RouteCommand["命令路由查找"]
|
||||
RouteCommand --> ExecuteCmd["执行命令处理器"]
|
||||
ExecuteCmd --> SendResponse["发送响应消息"]
|
||||
LogWarning --> End([处理结束])
|
||||
LogError --> End
|
||||
SendResponse --> End
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L50-L120)
|
||||
|
||||
### 下行消息处理流程
|
||||
|
||||
下行消息处理从gRPC调用开始,经过命令转换、消息构建和协议编码等步骤,最终生成符合绿能协议规范的报文。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([接收gRPC调用]) --> ConvertCmd["命令转换<br/>DownlinkCmdEnum -> 协议命令字"]
|
||||
ConvertCmd --> ValidateSupport{"验证命令支持"}
|
||||
ValidateSupport --> |不支持| LogUnsupported["记录不支持命令"]
|
||||
ValidateSupport --> |支持| BuildMessage["构建LvnengDwonlinkMessage"]
|
||||
BuildMessage --> ExtractData["提取请求数据"]
|
||||
ExtractData --> RouteCommand["命令路由查找"]
|
||||
RouteCommand --> ExecuteCmd["执行命令处理器"]
|
||||
ExecuteCmd --> EncodeMsg["编码协议消息<br/>帧头 + 长度 + 加密 + 序列号 + 命令字 + 数据域 + 校验和"]
|
||||
EncodeMsg --> SendMsg["发送到TCP会话"]
|
||||
LogUnsupported --> End([处理结束])
|
||||
SendMsg --> End
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L120-L187)
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L50-L187)
|
||||
|
||||
## 命令路由机制
|
||||
|
||||
### ProtocolCommandRouter实现
|
||||
|
||||
ProtocolCommandRouter提供了基于协议名和命令字的智能路由功能,支持自动扫描和注册命令执行器,实现了松耦合的命令处理架构。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class ProtocolCommandRouter~T~ {
|
||||
-Map~String,T~ executorMap
|
||||
+ProtocolCommandRouter(Class, Predicate)
|
||||
+getExecutor(String, int) T
|
||||
-initializeRoutes(Class, Predicate) void
|
||||
-registerExecutor(Class) void
|
||||
-buildKey(String, int) String
|
||||
}
|
||||
class LvnengUplinkCmdExe {
|
||||
<<abstract>>
|
||||
+execute(TcpSession, LvnengUplinkMessage, ProtocolContext) void
|
||||
#uplinkMessageBuilder(String, TcpSession, LvnengUplinkMessage) UplinkQueueMessage.Builder
|
||||
}
|
||||
class LvnengDownlinkCmdExe {
|
||||
<<abstract>>
|
||||
+execute(TcpSession, LvnengDwonlinkMessage, ProtocolContext) void
|
||||
}
|
||||
class LvnengV340RealTimeDataULCmd {
|
||||
+execute(TcpSession, LvnengUplinkMessage, ProtocolContext) void
|
||||
}
|
||||
class LvnengV340SetPricingModelDLCmd {
|
||||
+execute(TcpSession, LvnengDwonlinkMessage, ProtocolContext) void
|
||||
}
|
||||
ProtocolCommandRouter --> LvnengUplinkCmdExe : routes
|
||||
ProtocolCommandRouter --> LvnengDownlinkCmdExe : routes
|
||||
LvnengUplinkCmdExe <|-- LvnengV340RealTimeDataULCmd
|
||||
LvnengDownlinkCmdExe <|-- LvnengV340SetPricingModelDLCmd
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [ProtocolCommandRouter.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/routing/ProtocolCommandRouter.java#L20-L105)
|
||||
- [LvnengUplinkCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengUplinkCmdExe.java#L15-L40)
|
||||
|
||||
### 命令注册机制
|
||||
|
||||
系统通过@ProtocolCmd注解自动发现和注册命令执行器,每个执行器可以支持多个协议版本。这种设计使得协议升级更加灵活。
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [ProtocolCommandRouter.java](file://jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/routing/ProtocolCommandRouter.java#L20-L105)
|
||||
- [LvnengUplinkCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengUplinkCmdExe.java#L15-L40)
|
||||
|
||||
## 数据包格式与处理
|
||||
|
||||
### 上行命令处理示例:实时数据上报
|
||||
|
||||
LvnengV340RealTimeDataULCmd展示了典型的上行命令处理流程,包括数据解析、状态更新和消息转发。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Pile as 充电桩
|
||||
participant Cmd as LvnengV340RealTimeDataULCmd
|
||||
participant Session as TCP会话
|
||||
participant Context as 协议上下文
|
||||
participant Forwarder as 消息转发器
|
||||
Pile->>Cmd : 接收实时数据上报
|
||||
Cmd->>Cmd : 解析消息体<br/>充电桩编码 + 枪口数量 + 枪口号
|
||||
Cmd->>Cmd : 提取状态信息<br/>工作状态 + SOC + 告警码
|
||||
Cmd->>Cmd : 解析电气参数<br/>电压、电流、电量
|
||||
Cmd->>Session : 更新会话信息
|
||||
Cmd->>Context : 注册会话
|
||||
Cmd->>Cmd : 构建状态消息<br/>GunRunStatusProto
|
||||
Cmd->>Forwarder : 转发状态信息
|
||||
Cmd->>Cmd : 构建充电进度消息<br/>ChargingProgressProto
|
||||
Cmd->>Forwarder : 转发充电进度
|
||||
Cmd->>Cmd : 发送应答消息<br/>REAL_TIME_DATA_ACK
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengV340RealTimeDataULCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RealTimeDataULCmd.java#L35-L316)
|
||||
|
||||
### 下行命令处理示例:设置定价模型
|
||||
|
||||
LvnengV340SetPricingModelDLCmd演示了下行命令的处理流程,包括参数解析、数据转换和响应生成。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Server as 服务器
|
||||
participant Cmd as LvnengV340SetPricingModelDLCmd
|
||||
participant Session as TCP会话
|
||||
participant Cache as 请求缓存
|
||||
Server->>Cmd : 接收定价模型设置
|
||||
Cmd->>Cmd : 验证消息格式<br/>SetPricingRequest
|
||||
Cmd->>Cmd : 解析计费规则<br/>时段计价或阶梯计价
|
||||
Cmd->>Cmd : 构建响应数据<br/>48个时间段 * 12字节
|
||||
Cmd->>Cache : 存储请求ID
|
||||
Cmd->>Session : 发送应答消息<br/>SET_PRICING_ACK
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengV340SetPricingModelDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340SetPricingModelDLCmd.java#L35-L98)
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [LvnengV340RealTimeDataULCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RealTimeDataULCmd.java#L35-L316)
|
||||
- [LvnengV340SetPricingModelDLCmd.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340SetPricingModelDLCmd.java#L35-L98)
|
||||
|
||||
## 实际应用示例
|
||||
|
||||
### 协议命令转换机制
|
||||
|
||||
LvnengDownlinkCmdConverter作为命令转换器,建立了通用命令与协议特定命令字之间的映射关系。这种设计确保了协议的可扩展性和向后兼容性。
|
||||
|
||||
| 通用命令 | 绿能协议命令字 | 描述 |
|
||||
|------------------------|---------|--------|
|
||||
| LOGIN_ACK | 105 | 登录应答 |
|
||||
| SYNC_TIME_REQUEST | 3 | 时间同步请求 |
|
||||
| TRANSACTION_RECORD_ACK | 201 | 交易记录应答 |
|
||||
| HEARTBEAT_ACK | 101 | 心跳应答 |
|
||||
| REAL_TIME_DATA_ACK | 103 | 实时数据应答 |
|
||||
| SET_PRICING | 1103 | 设置定价模型 |
|
||||
| REMOTE_STOP_CHARGING | 5 | 远程停止充电 |
|
||||
| SET_QRCODE | 3 | 设置二维码 |
|
||||
|
||||
### 消息对象结构
|
||||
|
||||
系统定义了专门的消息对象来封装协议数据,提供了类型安全的数据访问接口。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class LvnengUplinkMessage {
|
||||
-UUID id
|
||||
-int head
|
||||
-int dataLength
|
||||
-int sequenceNumber
|
||||
-int encryptionFlag
|
||||
-int cmd
|
||||
-byte[] msgBody
|
||||
-int checkSum
|
||||
-byte[] rawFrame
|
||||
+getId() UUID
|
||||
+getCmd() int
|
||||
+getMsgBody() byte[]
|
||||
+getRawFrame() byte[]
|
||||
}
|
||||
class LvnengDwonlinkMessage {
|
||||
-UUID id
|
||||
-UUID requestId
|
||||
-int cmd
|
||||
-DownlinkRequestMessage msg
|
||||
-LvnengUplinkMessage requestData
|
||||
+getId() UUID
|
||||
+getCmd() int
|
||||
+getRequestId() UUID
|
||||
+getMsg() DownlinkRequestMessage
|
||||
}
|
||||
class AbstractLvnengCmdExe {
|
||||
#encode(int, int, int, ByteBuf) byte[]
|
||||
#encodeAndWriteFlush(int, ByteBuf, TcpSession) void
|
||||
#encodeAndWriteFlush(DownlinkCmdEnum, ByteBuf, TcpSession) void
|
||||
}
|
||||
LvnengDwonlinkMessage --> LvnengUplinkMessage : requestData
|
||||
AbstractLvnengCmdExe --> LvnengUplinkMessage : processes
|
||||
AbstractLvnengCmdExe --> LvnengDwonlinkMessage : processes
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
|
||||
- [LvnengUplinkMessage.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengUplinkMessage.java#L15-L54)
|
||||
- [LvnengDwonlinkMessage.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengDwonlinkMessage.java#L15-L42)
|
||||
- [AbstractLvnengCmdExe.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/AbstractLvnengCmdExe.java#L15-L120)
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [LvnengDownlinkCmdConverter.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/mapping/LvnengDownlinkCmdConverter.java#L25-L75)
|
||||
- [LvnengUplinkMessage.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengUplinkMessage.java#L15-L54)
|
||||
- [LvnengDwonlinkMessage.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengDwonlinkMessage.java#L15-L42)
|
||||
|
||||
## 性能考虑
|
||||
|
||||
绿能协议在设计时充分考虑了性能优化,采用了多种技术手段来提高系统的响应速度和吞吐量。
|
||||
|
||||
### 异步处理机制
|
||||
|
||||
系统采用Netty框架实现异步I/O操作,避免了线程阻塞,提高了并发处理能力。消息处理完全基于事件驱动,能够高效处理大量并发连接。
|
||||
|
||||
### 内存管理优化
|
||||
|
||||
- 使用ByteBuf进行零拷贝操作,减少内存分配和垃圾回收压力
|
||||
- 采用对象池技术复用消息对象,降低GC频率
|
||||
- 合理设计消息结构,减少不必要的数据复制
|
||||
|
||||
### 缓存策略
|
||||
|
||||
- 命令路由表采用ConcurrentHashMap实现,提供O(1)的查找性能
|
||||
- 请求ID缓存机制避免重复处理相同请求
|
||||
- 会话状态信息本地化存储,减少数据库访问
|
||||
|
||||
## 故障排除指南
|
||||
|
||||
### 常见问题诊断
|
||||
|
||||
#### 消息解析失败
|
||||
|
||||
- 检查帧头是否为0xAAF5
|
||||
- 验证消息长度是否正确
|
||||
- 确认校验和计算是否准确
|
||||
|
||||
#### 命令路由失败
|
||||
|
||||
- 确认命令执行器是否正确注册
|
||||
- 检查@ProtocolCmd注解配置
|
||||
- 验证协议名称匹配
|
||||
|
||||
#### 连接异常
|
||||
|
||||
- 检查TCP连接状态
|
||||
- 验证网络防火墙设置
|
||||
- 确认端口监听状态
|
||||
|
||||
### 日志分析
|
||||
|
||||
系统提供了详细的日志记录,帮助快速定位问题:
|
||||
|
||||
- WARN级别:消息格式异常、校验和失败
|
||||
- ERROR级别:命令执行异常、系统内部错误
|
||||
- DEBUG级别:消息处理流程跟踪
|
||||
|
||||
**章节来源**
|
||||
|
||||
- [LvnengProtocolMessageProcessor.java](file://jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/LvnengProtocolMessageProcessor.java#L70-L100)
|
||||
|
||||
## 总结
|
||||
|
||||
绿能协议v3.40实现了一个功能完整、性能优异的电动汽车充电站通信协议。通过模块化的架构设计、严格的帧结构规范和智能的命令路由机制,系统实现了高可靠性的消息传输和处理。
|
||||
|
||||
### 主要特性
|
||||
|
||||
1. **严格的协议规范**:采用标准的帧结构和校验机制,确保消息传输的可靠性
|
||||
2. **灵活的命令处理**:支持多种命令类型,具备良好的扩展性
|
||||
3. **高性能架构**:基于Netty的异步处理,支持高并发场景
|
||||
4. **完善的错误处理**:提供详细的日志记录和异常处理机制
|
||||
5. **类型安全设计**:使用强类型的消息对象,减少运行时错误
|
||||
|
||||
### 技术优势
|
||||
|
||||
- **模块化设计**:各组件职责明确,便于维护和扩展
|
||||
- **自动化注册**:通过注解机制自动发现和注册命令执行器
|
||||
- **性能优化**:采用多种优化技术,确保系统高效运行
|
||||
- **向后兼容**:支持协议版本升级,保证系统稳定性
|
||||
|
||||
该协议实现为电动汽车充电站提供了稳定可靠的通信基础,支撑了大规模充电网络的运营需求。通过持续的优化和改进,系统能够适应不断发展的行业需求和技术进步。
|
||||
Reference in New Issue
Block a user