Files
2026-06-14 11:19:15 +08:00

414 lines
11 KiB
Markdown
Raw Permalink 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.
# 🚀 充电桩管理系统 - 快速启动指南
## 📦 文件清单
已创建的文件:
```
Charge/
├── ChargeStation.cs # 充电桩数据模型
├── ChargeStationDataService.cs # 数据服务(单例)
├── ChargeStationManagementForm.cs # 管理窗口主类
├── ChargeStationManagementForm.Designer.cs # 窗口UI设计
├── ChargeStationManagementExample.cs # 示例代码
├── README_ChargeStationManagement.md # 详细使用说明
└── QUICKSTART.md # 本文件
```
## ⚡ 5分钟快速上手
### 步骤1:在主窗口添加菜单(推荐方式)
如果您的主窗口有菜单栏,添加一个菜单项:
```csharp
// 在主窗口的 InitializeComponent() 或构造函数中添加
// 方法1: 如果有工具栏
var btnChargeManagement = new ToolStripButton("充电桩管理");
btnChargeManagement.Click += (s, e) => {
var form = new StandardScene.Charge.ChargeStationManagementForm();
form.Show();
};
toolStrip.Items.Add(btnChargeManagement);
// 方法2: 如果有菜单栏
var menuItemCharge = new ToolStripMenuItem("充电桩管理(&C)");
menuItemCharge.Click += (s, e) => {
var form = new StandardScene.Charge.ChargeStationManagementForm();
form.Show();
};
menuStrip.Items.Add(menuItemCharge);
// 方法3: 如果有按钮面板
var btnChargeManagement = new Button
{
Text = "充电桩管理",
Size = new Size(120, 40),
Location = new Point(10, 10)
};
btnChargeManagement.Click += (s, e) => {
var form = new StandardScene.Charge.ChargeStationManagementForm();
form.Show();
};
this.Controls.Add(btnChargeManagement);
```
### 步骤2:初始化测试数据(首次运行)
在程序启动时或通过菜单调用:
```csharp
// 在主窗口的 Load 事件或启动代码中
StandardScene.Charge.ChargeStationManagementExample.InitializeTestData();
```
### 步骤3:打开管理窗口
点击您添加的菜单项或按钮,即可打开充电桩管理窗口。
---
## 🎯 集成到 AbstractChargeMission
如果您想将充电桩数据与充电任务关联,在 `AbstractChargeMission.cs` 中添加:
### 1. 引用命名空间
```csharp
using StandardScene.Charge;
```
### 2. 在选择充电站点时使用充电桩数据
```csharp
// 在 Execute() 方法的充电决策部分
var dataService = ChargeStationDataService.Instance;
// 获取空闲的充电桩
var idleStations = dataService.GetIdleStations();
// 根据充电桩的站点ID筛选
targetPlan = Commons.GetNearestPlan((Car)car, site =>
site.fields.ContainsKey("group") &&
site.fields.ContainsKey("Charge") &&
GetChargeType(car).Contains(site.fields["group"]) &&
idleStations.Any(s => s.SiteId == site.id) // 确保站点有空闲充电桩
);
```
### 3. 在开始充电时更新充电桩状态
```csharp
// 在车辆到达充电站时
public override void ArriveAction(Car car, Site site)
{
var dataService = ChargeStationDataService.Instance;
var station = dataService.GetAllStations()
.FirstOrDefault(s => s.SiteId == site.id && s.Status == ChargeStationStatus.Idle);
if (station != null)
{
dataService.UpdateStationStatus(station.StationId, ChargeStationStatus.Charging);
car.tags.Add("chargingStationId", station.StationId);
Diagnosis.Log($"车辆 {car.name} 开始在充电桩 {station.Name} 充电",
"Charge", true);
}
}
```
### 4. 在离开充电站时更新充电桩状态
```csharp
// 在车辆离开充电站时
public override void LeaveAction(Car car, Site site)
{
if (car.tags.TryGetValue("chargingStationId", out var stationId))
{
var dataService = ChargeStationDataService.Instance;
dataService.UpdateStationStatus(stationId, ChargeStationStatus.Idle);
car.tags.Remove("chargingStationId");
Diagnosis.Log($"车辆 {car.name} 充电完成,充电桩 {stationId} 恢复空闲",
"Charge", true);
}
}
```
---
## 📊 在主界面显示充电桩统计
在主窗口添加实时统计显示:
```csharp
// 添加一个 Timer 定时更新统计信息
private Timer chargeStationStatusTimer;
private Label lblChargeStationStatus;
private void InitializeChargeStationMonitor()
{
// 创建状态标签
lblChargeStationStatus = new Label
{
Text = "充电桩: 加载中...",
AutoSize = true,
Location = new Point(10, 10),
Font = new Font("微软雅黑", 10F, FontStyle.Bold)
};
this.Controls.Add(lblChargeStationStatus);
// 创建定时器(每3秒更新一次)
chargeStationStatusTimer = new Timer
{
Interval = 3000,
Enabled = true
};
chargeStationStatusTimer.Tick += UpdateChargeStationStatus;
chargeStationStatusTimer.Start();
}
private void UpdateChargeStationStatus(object sender, EventArgs e)
{
try
{
var dataService = StandardScene.Charge.ChargeStationDataService.Instance;
var stations = dataService.GetAllStations();
var idle = stations.Count(s => s.Status == StandardScene.Charge.ChargeStationStatus.Idle);
var charging = stations.Count(s => s.Status == StandardScene.Charge.ChargeStationStatus.Charging);
var fault = stations.Count(s => s.Status == StandardScene.Charge.ChargeStationStatus.Fault);
lblChargeStationStatus.Text = $"充电桩: 总数 {stations.Count} | " +
$"空闲 {idle} | 充电中 {charging} | 故障 {fault}";
// 根据状态设置颜色
if (fault > 0)
lblChargeStationStatus.ForeColor = Color.Red;
else if (idle == 0 && charging > 0)
lblChargeStationStatus.ForeColor = Color.Orange;
else
lblChargeStationStatus.ForeColor = Color.Green;
}
catch (Exception ex)
{
lblChargeStationStatus.Text = $"充电桩: 获取状态失败 - {ex.Message}";
lblChargeStationStatus.ForeColor = Color.Gray;
}
}
```
---
## 🔧 配置充电桩与站点的映射
### 方式1: 在站点属性中添加充电桩编号
修改地图站点的 `fields`
```csharp
// 为站点添加充电桩编号
site.fields.Add("ChargeStationId", "CS20240115123456");
```
### 方式2: 在充电桩管理界面直接设置站点ID
在充电桩管理窗口中,编辑充电桩时填写"站点ID"字段。
### 方式3: 自动关联(代码实现)
```csharp
// 自动将充电桩与最近的充电站点关联
public void AutoAssignStationsToSites()
{
var dataService = ChargeStationDataService.Instance;
var allStations = dataService.GetAllStations();
var chargeSites = SimpleLib.GetAllSites()
.Where(s => s.fields.ContainsKey("Charge"))
.ToList();
foreach (var station in allStations)
{
if (station.SiteId == null || station.SiteId == 0)
{
// 根据名称或其他规则自动匹配站点
var matchedSite = chargeSites.FirstOrDefault(s =>
s.fields.ContainsKey("name") &&
s.fields["name"].Contains(station.Name)
);
if (matchedSite != null)
{
station.SiteId = matchedSite.id;
dataService.UpdateStation(station, out _);
Diagnosis.Log($"自动关联充电桩 {station.Name} 到站点 {matchedSite.id}",
"ChargeStation", true);
}
}
}
}
```
---
## 📱 添加快捷键
为管理窗口添加快捷键(在主窗口):
```csharp
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// Ctrl+C 打开充电桩管理
if (keyData == (Keys.Control | Keys.C))
{
var form = new StandardScene.Charge.ChargeStationManagementForm();
form.Show();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
```
---
## 🎨 自定义界面样式
如果需要调整窗口样式,修改 `ChargeStationManagementForm.Designer.cs`
```csharp
// 修改窗口大小
this.Size = new Size(1400, 800);
// 修改按钮颜色
btnAdd.BackColor = Color.FromArgb(144, 238, 144); // 浅绿色
btnSave.BackColor = Color.FromArgb(135, 206, 250); // 浅蓝色
btnDelete.BackColor = Color.FromArgb(255, 182, 193); // 浅红色
// 修改字体
this.Font = new Font("微软雅黑", 9F);
```
---
## 🐛 常见问题
### Q1: 窗口打不开
**A**: 检查是否正确引用了命名空间:
```csharp
using StandardScene.Charge;
```
### Q2: 数据保存失败
**A**: 确保 `Data` 文件夹有写入权限:
```bash
# Windows
右键 Data 文件夹 -> 属性 -> 安全 -> 确保当前用户有"写入"权限
```
### Q3: 找不到充电桩数据
**A**: 首次运行时需要初始化数据:
```csharp
ChargeStationManagementExample.InitializeTestData();
```
### Q4: 充电桩状态不更新
**A**: 手动刷新数据:
```csharp
ChargeStationDataService.Instance.Reload();
```
---
## 📚 进阶功能
### 实时监控充电桩通信状态
```csharp
// 定期 Ping 充电桩 IP
private async Task<bool> PingChargeStation(string ip, int port)
{
try
{
using (var client = new System.Net.Sockets.TcpClient())
{
var result = client.BeginConnect(ip, port, null, null);
var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(3));
if (success)
{
client.EndConnect(result);
return true;
}
return false;
}
}
catch
{
return false;
}
}
```
### 充电桩数据可视化
```csharp
// 在主界面添加充电桩状态图表
private void DrawChargeStationChart(Graphics g)
{
var dataService = ChargeStationDataService.Instance;
var stations = dataService.GetAllStations();
int x = 10, y = 10, size = 40;
foreach (var station in stations)
{
Color color = station.Status switch
{
ChargeStationStatus.Idle => Color.Green,
ChargeStationStatus.Charging => Color.Yellow,
ChargeStationStatus.Fault => Color.Red,
ChargeStationStatus.Offline => Color.Gray,
_ => Color.White
};
g.FillRectangle(new SolidBrush(color), x, y, size, size);
g.DrawString(station.Name, this.Font, Brushes.Black, x, y + size + 5);
x += size + 10;
if (x > this.Width - 100)
{
x = 10;
y += size + 30;
}
}
}
```
---
## 🎉 完成
现在您已经完成了充电桩管理系统的集成!
**下一步**
1. ✅ 添加菜单项或按钮
2. ✅ 初始化测试数据
3. ✅ 打开管理窗口测试
4. ✅ 将充电桩数据集成到充电任务
5. ✅ 添加实时监控和统计
**需要帮助?**
- 查看 `README_ChargeStationManagement.md` 获取详细文档
- 参考 `ChargeStationManagementExample.cs` 查看示例代码
- 检查日志中的 `ChargeStation` 标签
---
**版本**: 1.0.0
**最后更新**: 2024-01-15