日期: 2026-03-13
作者: Claude + 用户协作
状态: 已批准
创建一个基于HSL Communication库的西门子S7 PLC模拟器系统,用于WCS系统的开发测试。
┌──────────────────────────────────────────────────────────────────────────┐
│ WIDESEAWCS_S7Simulator │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ Web管理界面 (Razor Pages/Blazor) │ │
│ │ - 服务器实例列表(卡片视图) │ │
│ │ - 实例创建/编辑表单 │ │
│ │ - 实例详情页(状态、内存、客户端) │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ ↕ HTTP API + SignalR │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ Web API 控制器 │ │
│ │ - SimulatorInstancesController (CRUD) │ │
│ │ - SimulatorInstanceController (启停控制) │ │
│ │ - MemoryController (内存读写) │ │
│ │ - ClientsController (客户端管理) │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ ↕ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ 实例管理器 │ │
│ │ Dictionary<string, IS7ServerInstance> 管理所有实例 │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ ↕ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ 每个实例包含: IS7ServerInstance + IMemoryStore │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ ↕ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ 多个HSL S7服务器实例 (不同端口) │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ ↕ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ S7客户端连接 (WCS/测试工具等) │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────┘
WIDESEAWCS_S7Simulator/
├── WIDESEAWCS_S7Simulator.sln
│
├── src/
│ ├── WIDESEAWCS_S7Simulator.Core/ # 核心领域层
│ │ ├── Entities/ # 实体
│ │ │ ├── SimulatorInstance.cs # 实例实体
│ │ │ ├── InstanceConfig.cs # 实例配置
│ │ │ ├── InstanceState.cs # 实例状态
│ │ │ └── S7ClientConnection.cs # 客户端连接
│ │ │
│ │ ├── Interfaces/ # 接口
│ │ │ ├── IS7ServerInstance.cs # 服务器实例接口
│ │ │ ├── IMemoryStore.cs # 内存存储接口
│ │ │ ├── IPersistenceService.cs # 持久化服务接口
│ │ │ └── ISimulatorInstanceManager.cs # 实例管理器接口
│ │ │
│ │ ├── Memory/ # 内存模拟
│ │ │ ├── MemoryStore.cs # 内存存储实现
│ │ │ ├── MemoryRegion.cs # 内存区域基类
│ │ │ ├── MRegion.cs # M区实现
│ │ │ ├── DBRegion.cs # DB区实现
│ │ │ ├── IRegion.cs # I区实现
│ │ │ ├── QRegion.cs # Q区实现
│ │ │ ├── TRegion.cs # T区实现
│ │ │ └── CRegion.cs # C区实现
│ │ │
│ │ ├── Server/ # S7服务器
│ │ │ └── S7ServerInstance.cs # 服务器实例实现
│ │ │
│ │ ├── Persistence/ # 数据持久化
│ │ │ ├── FilePersistenceService.cs # 文件持久化实现
│ │ │ └── Models/
│ │ │ └── InstanceDataModel.cs # 数据模型
│ │ │
│ │ ├── Manager/ # 管理器
│ │ │ └── SimulatorInstanceManager.cs # 实例管理器实现
│ │ │
│ │ └── Enums/ # 枚举
│ │ ├── SiemensPLCType.cs # PLC型号
│ │ └── InstanceStatus.cs # 实例状态
│ │
│ ├── WIDESEAWCS_S7Simulator.Application/ # 应用服务层
│ │ ├── DTOs/ # 数据传输对象
│ │ │ ├── InstanceDTO.cs
│ │ │ ├── CreateInstanceDTO.cs
│ │ │ ├── UpdateInstanceDTO.cs
│ │ │ ├── MemoryReadDTO.cs
│ │ │ ├── MemoryWriteDTO.cs
│ │ │ └── ClientConnectionDTO.cs
│ │ │
│ │ ├── Services/ # 应用服务
│ │ │ ├── SimulatorInstanceAppService.cs
│ │ │ ├── MemoryAppService.cs
│ │ │ └── ClientAppService.cs
│ │ │
│ │ └── Profiles/ # AutoMapper配置
│ │ └── MappingProfile.cs
│ │
│ ├── WIDESEAWCS_S7Simulator.Server/ # Web API Host
│ │ ├── Controllers/
│ │ │ ├── SimulatorInstancesController.cs
│ │ │ ├── SimulatorInstanceController.cs
│ │ │ ├── MemoryController.cs
│ │ │ └── ClientsController.cs
│ │ │
│ │ ├── Infrastructure/
│ │ │ ├── DependencyInjection.cs
│ │ │ └── Middleware/
│ │ │ └── ExceptionMiddleware.cs
│ │ │
│ │ ├── Hubs/ # SignalR Hub
│ │ │ └── SimulatorHub.cs # 实时状态推送
│ │ │
│ │ ├── Program.cs
│ │ ├── appsettings.json
│ │ └── WIDESEAWCS_S7Simulator.Server.csproj
│ │
│ └── WIDESEAWCS_S7Simulator.Web/ # Web管理界面
│ ├── Pages/ # Razor Pages
│ │ ├── Index.cshtml # 实例列表页
│ │ ├── Create.cshtml # 创建实例页
│ │ ├── Edit.cshtml # 编辑实例页
│ │ ├── Details.cshtml # 实例详情页
│ │ └── Shared/
│ │ ├── _Layout.cshtml
│ │ └── _Components/
│ │
│ ├── wwwroot/
│ │ ├── css/site.css
│ │ ├── js/site.js
│ │ └── lib/ # 前端库
│ │
│ └── WIDESEAWCS_S7Simulator.Web.csproj
│
├── tests/
│ ├── WIDESEAWCS_S7Simulator.UnitTests/
│ │ ├── Memory/
│ │ │ ├── MRegionTests.cs
│ │ │ ├── DBRegionTests.cs
│ │ │ └── MemoryStoreTests.cs
│ │ ├── Server/
│ │ │ └── S7ServerInstanceTests.cs
│ │ └── Persistence/
│ │ └── FilePersistenceServiceTests.cs
│ │
│ └── WIDESEAWCS_S7Simulator.IntegrationTests/
│ ├── S7ClientConnectionTests.cs
│ └── APIEndpointTests.cs
│
└── docs/
└── API.md
public class InstanceConfig
{
public string Id { get; set; }
public string Name { get; set; }
public SiemensPLCType PLCType { get; set; }
public int Port { get; set; }
public string ActivationKey { get; set; }
public bool AutoStart { get; set; }
public MemoryRegionConfig MemoryConfig { get; set; }
}
public class MemoryRegionConfig
{
public int MRegionSize { get; set; } = 1024;
public int DBBlockCount { get; set; } = 100;
public int DBBlockSize { get; set; } = 1024;
public int IRegionSize { get; set; } = 256;
public int QRegionSize { get; set; } = 256;
public int TRegionCount { get; set; } = 64;
public int CRegionCount { get; set; } = 64;
}
public class InstanceState
{
public string InstanceId { get; set; }
public InstanceStatus Status { get; set; }
public int ClientCount { get; set; }
public long TotalRequests { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? LastActivityTime { get; set; }
public List<S7ClientConnection> Clients { get; set; } = new();
}
public enum InstanceStatus
{
Stopped = 0,
Starting = 1,
Running = 2,
Stopping = 3,
Error = 4
}
public interface IS7ServerInstance : IDisposable
{
InstanceConfig Config { get; }
InstanceState State { get; }
IMemoryStore MemoryStore { get; }
Task<OperateResult> StartAsync();
Task<OperateResult> StopAsync();
Task<OperateResult> RestartAsync();
event EventHandler<InstanceStateEventArgs> StatusChanged;
event EventHandler<ClientConnectionEventArgs> ClientConnected;
event EventHandler<ClientConnectionEventArgs> ClientDisconnected;
}
public interface IMemoryStore
{
byte[] ReadBytes(string address, ushort length);
T Read<T>(string address) where T : struct;
void WriteBytes(string address, byte[] data);
void Write<T>(string address, T value) where T : struct;
IMemoryRegion GetRegion(string regionType);
void Clear();
Dictionary<string, byte[]> Export();
void Import(Dictionary<string, byte[]> data);
}
public interface IMemoryRegion
{
string RegionType { get; }
int Size { get; }
byte[] Read(ushort offset, ushort length);
void Write(ushort offset, byte[] data);
void Clear();
}
public interface IPersistenceService
{
Task SaveInstanceConfigAsync(InstanceConfig config);
Task<InstanceConfig> LoadInstanceConfigAsync(string instanceId);
Task<List<InstanceConfig>> LoadAllInstanceConfigsAsync();
Task DeleteInstanceConfigAsync(string instanceId);
Task SaveMemoryDataAsync(string instanceId, IMemoryStore memoryStore);
Task LoadMemoryDataAsync(string instanceId, IMemoryStore memoryStore);
}
Data/
├── instance-1/
│ ├── config.json
│ └── memory.json
├── instance-2/
│ ├── config.json
│ └── memory.json
public interface ISimulatorInstanceManager
{
IReadOnlyList<IS7ServerInstance> GetAllInstances();
IS7ServerInstance GetInstance(string instanceId);
Task<IS7ServerInstance> CreateInstanceAsync(CreateInstanceDTO createDto);
Task UpdateInstanceAsync(string instanceId, UpdateInstanceDTO updateDto);
Task DeleteInstanceAsync(string instanceId);
Task<OperateResult> StartInstanceAsync(string instanceId);
Task<OperateResult> StopInstanceAsync(string instanceId);
Task<OperateResult> RestartInstanceAsync(string instanceId);
Task StartAutoStartInstancesAsync();
Task StopAllInstancesAsync();
event EventHandler<InstanceStateEventArgs> InstanceStatusChanged;
}
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | /api/instances | 获取所有实例列表 |
| POST | /api/instances | 创建新实例 |
| GET | /api/instances/{id} | 获取指定实例详情 |
| PUT | /api/instances/{id} | 更新实例配置 |
| DELETE | /api/instances/{id} | 删除实例 |
| POST | /api/instances/{id}/start | 启动实例 |
| POST | /api/instances/{id}/stop | 停止实例 |
| POST | /api/instances/{id}/restart | 重启实例 |
| GET | /api/instances/{id}/memory | 读取内存数据 |
| POST | /api/instances/{id}/memory | 写入内存数据 |
| DELETE | /api/instances/{id}/memory | 清空内存数据 |
| POST | /api/instances/{id}/memory/save | 保存内存快照 |
| POST | /api/instances/{id}/memory/load | 加载内存快照 |
| GET | /api/instances/{id}/clients | 获取连接的客户端列表 |
| DELETE | /api/instances/{id}/clients/{clientId} | 断开指定客户端 |
| POST | /api/instances/start-all | 启动所有自动启动实例 |
| POST | /api/instances/stop-all | 停止所有实例 |
| 页面 | 功能 |
|---|---|
| Index | 实例列表卡片视图,显示所有实例状态 |
| Create | 创建新实例表单 |
| Edit | 编辑实例配置 |
| Details | 实例详情:状态信息、客户端列表、内存查看/编辑 |
{
"urls": "http://*:5000",
"S7Simulator": {
"DataPath": "Data",
"DefaultActivationKey": "4b86f3fc-f650-3b08-5924-b0f8278d6ed2",
"EnableAutoLoad": true,
"AutoStartInstances": true
},
"MemoryDefaults": {
"MRegionSize": 1024,
"DBBlockCount": 100,
"DBBlockSize": 1024,
"IRegionSize": 256,
"QRegionSize": 256,
"TRegionCount": 64,
"CRegionCount": 64
}
}
MemoryStoreTests - 内存读写、边界检查、并发访问MRegionTests - M区位操作、字节操作DBRegionTests - DB块读写、多块管理InstanceManagerTests - 实例创建、启动、停止、删除PersistenceServiceTests - 配置保存/加载、内存快照S7ServerIntegrationTests - 真实S7客户端连接测试APIIntegrationTests - Web API端到端测试MultiInstanceTests - 多实例并发运行测试| 包名 | 版本 | 用途 |
|---|---|---|
| HslCommunication | 12.6.3 | S7协议通信 |
| Microsoft.AspNetCore.SignalR | 最新 | 实时状态推送 |
| Serilog.AspNetCore | 最新 | 日志记录 |
| AutoMapper | 最新 | 对象映射 |
| xUnit | 最新 | 单元测试 |
本设计实现了一个功能完整的S7 PLC模拟器系统: