# 充电桩报文分离解析使用示例

## 概述

系统现在支持**发送报文**和**接收报文**分开解析，然后自动合并更新到充电桩管理界面。

## 数据流向图

```
┌─────────────────┐
│   应用程序      │
└────────┬────────┘
         │ 发送充电指令
         ▼
┌─────────────────────────────────────────────┐
│  CommunicationMessageService                │
│  ┌─────────────────────────────────────┐   │
│  │ AddSendMessage()                    │   │
│  │  ├─ 记录发送报文                    │   │
│  │  └─ ParseSendDataAndUpdateStation() │   │
│  │      ├─ 解析设定电压                │   │
│  │      ├─ 解析设定电流                │   │
│  │      └─ 更新充电桩设定值            │   │
│  └─────────────────────────────────────┘   │
└─────────────────┬───────────────────────────┘
                  │
                  ▼
         ┌────────────────┐
         │ ChargeStation  │ ◄─── 设定值已更新
         │   SetVoltage   │
         │   SetCurrent   │
         └────────┬───────┘
                  │
                  │ 同时...
                  │
┌─────────────────▼───────────────────────────┐
│  ChargeUdpService (监听端口40001)           │
│  ├─ 接收充电桩返回的UDP报文                 │
│  └─ 调用 AddReceiveMessage()                │
└─────────────────┬───────────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────────┐
│  CommunicationMessageService                │
│  ┌─────────────────────────────────────┐   │
│  │ AddReceiveMessage()                 │   │
│  │  ├─ 记录接收报文                    │   │
│  │  └─ ParseReceiveDataAndUpdateStation()│ │
│  │      ├─ 解析实时电压                │   │
│  │      ├─ 解析实时电流                │   │
│  │      ├─ 解析充电状态                │   │
│  │      ├─ 解析机构状态                │   │
│  │      └─ 更新充电桩实时数据          │   │
│  └─────────────────────────────────────┘   │
└─────────────────┬───────────────────────────┘
                  │
                  ▼
         ┌────────────────┐
         │ ChargeStation  │ ◄─── 实时值已更新
         │ RealTimeVoltage│
         │ RealTimeCurrent│
         │ Status         │
         │ MechanismStatus│
         └────────┬───────┘
                  │
                  ▼
    ┌─────────────────────────────┐
    │ ChargeStationManagementForm │
    │  (每2秒自动刷新)             │
    │  显示：                      │
    │  - 设定电压 vs 实时电压      │
    │  - 设定电流 vs 实时电流      │
    │  - 充电状态                  │
    │  - 机构状态                  │
    └─────────────────────────────┘
```

## 代码示例

### 1. 发送充电指令（自动解析发送报文）

```csharp
// 在充电桩类中发送充电指令
public void StartCharging(double voltage, double current)
{
    // 构造发送报文
    byte[] sendData = new byte[10];
    sendData[5] = 1; // 充电指令：启动
    sendData[6] = (byte)((int)(voltage * 10) >> 8); // 设定电压高字节
    sendData[7] = (byte)((int)(voltage * 10) & 0xFF); // 设定电压低字节
    sendData[8] = (byte)((int)(current * 10) >> 8); // 设定电流高字节
    sendData[9] = (byte)((int)(current * 10) & 0xFF); // 设定电流低字节
    
    // 发送UDP报文
    udpClient.Send(sendData, sendData.Length, endPoint);
    
    // 记录发送报文（自动解析并更新设定值）
    var messageService = CommunicationMessageService.Instance;
    messageService.AddSendMessage(
        ipAddress: endPoint.Address.ToString(),
        port: endPoint.Port,
        rawData: string.Join(",", sendData),
        stationId: this.StationId
    );
    
    // ✅ 此时充电桩的 SetVoltage 和 SetCurrent 已自动更新
}
```

### 2. 接收充电桩反馈（自动解析接收报文）

```csharp
// 在 ChargeUdpService 中接收报文
private static async void ListenerProcess()
{
    var messageService = CommunicationMessageService.Instance;
    using (UdpClient udpListener = new UdpClient(40001))
    {
        while (true)
        {
            var result = await udpListener.ReceiveAsync();
            var remoteEndPoint = result.RemoteEndPoint;
            var message = result.Buffer;
            
            // 记录接收报文（自动解析并更新实时数据）
            messageService.AddReceiveMessage(
                ipAddress: remoteEndPoint.Address.ToString(),
                port: 40001,
                rawData: string.Join(",", message)
            );
            
            // ✅ 此时充电桩的实时数据已自动更新：
            //    - RealTimeVoltage（实时电压）
            //    - RealTimeCurrent（实时电流）
            //    - Status（充电状态）
            //    - MechanismStatus（机构状态）
            //    - BatteryLevel（电量百分比）
            //    - 等等...
        }
    }
}
```

### 3. 在充电桩管理界面查看合并后的数据

```csharp
// 在 ChargeStationManagementForm 中显示数据
private void LoadStations()
{
    var stations = ChargeStationDataService.Instance.GetAllStations();
    
    foreach (var station in stations)
    {
        // 显示设定值（来自发送报文解析）
        Console.WriteLine($"设定电压: {station.SetVoltage}V");
        Console.WriteLine($"设定电流: {station.SetElectricCurrent}A");
        
        // 显示实时值（来自接收报文解析）
        Console.WriteLine($"实时电压: {station.RealTimeVoltage}V");
        Console.WriteLine($"实时电流: {station.RealTimeCurrent}A");
        Console.WriteLine($"充电状态: {GetStatusText(station.Status)}");
        Console.WriteLine($"机构状态: {GetMechanismStatusText(station.MechanismStatus)}");
        Console.WriteLine($"电量: {station.BatteryLevel}%");
        
        // 显示通讯时间
        Console.WriteLine($"最后发送: {station.LastSendTime}");
        Console.WriteLine($"最后接收: {station.LastReceiveTime}");
    }
}
```

## 解析流程详解

### 发送报文解析流程

```
AddSendMessage()
    ↓
ParseSendDataAndUpdateStation()
    ↓
ParseSendRawData()  ← 解析发送报文
    ├─ ChargeCommand (字节5)
    ├─ SetVoltage (字节6-7)
    └─ SetCurrent (字节8-9)
    ↓
UpdateStationFromSendData()  ← 更新设定值
    ├─ station.SetVoltage = parsedData.SetVoltage
    ├─ station.SetElectricCurrent = parsedData.SetCurrent
    ├─ station.LastSendTime = parsedData.SendTime
    └─ station.ChargeCommandStatus = ...
```

### 接收报文解析流程

```
AddReceiveMessage()
    ↓
ParseReceiveDataAndUpdateStation()
    ↓
ParseReceiveRawData()  ← 解析接收报文
    ├─ CommStatus (字节28)
    ├─ ChargeCommandStatus (字节10)
    ├─ MechanismStatus (字节11)
    ├─ RealTimeVoltage (字节12-13)
    ├─ RealTimeCurrent (字节14-15)
    ├─ BatteryLevel (字节16)
    ├─ HasAlarm (字节20)
    ├─ Status (字节25)
    └─ CurrentVehicleId (字节26-29)
    ↓
UpdateStationFromReceiveData()  ← 更新实时值
    ├─ station.RealTimeVoltage = parsedData.RealTimeVoltage
    ├─ station.RealTimeCurrent = parsedData.RealTimeCurrent
    ├─ station.Status = parsedData.Status
    ├─ station.MechanismStatus = parsedData.MechanismStatus
    ├─ station.BatteryLevel = parsedData.BatteryLevel
    ├─ station.LastReceiveTime = parsedData.ReceiveTime
    └─ ...
```

## 数据对比示例

| 数据项 | 来源 | 更新时机 | 用途 |
|-------|------|---------|------|
| SetVoltage | 发送报文 | 发送充电指令时 | 显示设定的目标电压 |
| RealTimeVoltage | 接收报文 | 接收充电桩反馈时 | 显示当前实际电压 |
| SetElectricCurrent | 发送报文 | 发送充电指令时 | 显示设定的目标电流 |
| RealTimeCurrent | 接收报文 | 接收充电桩反馈时 | 显示当前实际电流 |
| ChargeCommandStatus | 发送+接收 | 发送指令时更新，接收反馈时确认 | 显示充电指令执行状态 |
| Status | 接收报文 | 接收充电桩反馈时 | 显示充电桩当前状态 |
| MechanismStatus | 接收报文 | 接收充电桩反馈时 | 显示机构伸缩状态 |
| BatteryLevel | 接收报文 | 接收充电桩反馈时 | 显示电池电量百分比 |
| LastSendTime | 发送报文 | 发送充电指令时 | 显示最后发送时间 |
| LastReceiveTime | 接收报文 | 接收充电桩反馈时 | 显示最后接收时间 |

## 优势

✅ **数据分离**：发送和接收数据各自独立，不会互相覆盖  
✅ **完整记录**：同时保留设定值和实时值，便于对比分析  
✅ **自动合并**：系统自动将两种数据合并到同一个充电桩对象  
✅ **实时更新**：界面每2秒自动刷新，显示最新数据  
✅ **易于调试**：可以清楚看到发送的指令和接收的反馈  

## 调试技巧

### 1. 查看报文记录

```csharp
var messageService = CommunicationMessageService.Instance;

// 查看所有报文
var allMessages = messageService.GetAllMessages();

// 查看某个IP的报文
var ipMessages = messageService.GetMessagesByIp("192.168.1.101");

// 查看某个充电桩的报文
var stationMessages = messageService.GetMessagesByStationId("1");

foreach (var msg in allMessages)
{
    Console.WriteLine($"[{msg.Direction}] {msg.IpAddress}:{msg.Port}");
    Console.WriteLine($"时间: {msg.Timestamp}");
    Console.WriteLine($"数据: {msg.RawData}");
    Console.WriteLine("---");
}
```

### 2. 对比设定值与实时值

```csharp
var station = ChargeStationDataService.Instance.GetStationByIp("192.168.1.101");

if (station != null)
{
    // 电压对比
    double voltageDiff = Math.Abs(station.SetVoltage - station.RealTimeVoltage);
    Console.WriteLine($"电压偏差: {voltageDiff}V");
    
    // 电流对比
    double currentDiff = Math.Abs(station.SetElectricCurrent - station.RealTimeCurrent);
    Console.WriteLine($"电流偏差: {currentDiff}A");
    
    // 通讯延迟
    if (station.LastSendTime != null && station.LastReceiveTime != null)
    {
        var delay = station.LastReceiveTime.Value - station.LastSendTime.Value;
        Console.WriteLine($"通讯延迟: {delay.TotalMilliseconds}ms");
    }
}
```

### 3. 监控解析错误

如果数据没有更新，检查以下几点：

1. **IP地址是否匹配**：确保充电桩的IP地址在管理列表中
2. **报文长度是否足够**：发送报文至少10字节，接收报文至少30字节
3. **字节位置是否正确**：根据实际协议调整字节位置
4. **数据类型是否正确**：检查高低字节顺序、单位换算等

## 注意事项

⚠️ **字节位置**：示例中的字节位置仅供参考，请根据实际通讯协议调整  
⚠️ **报文格式**：确保发送和接收的报文格式与解析规则一致  
⚠️ **异常处理**：解析失败不会影响报文记录，但数据不会更新  
⚠️ **线程安全**：`CommunicationMessageService` 使用单例模式，内部已做线程同步  

## 总结

通过分离解析发送和接收报文，系统可以：
- 准确记录每次发送的指令参数
- 准确获取充电桩的实时反馈
- 自动合并两种数据到充电桩管理界面
- 便于对比分析和故障诊断

这种设计使得充电桩管理更加精确和可靠！



