利用Cursor编写工业WebScada-002创建Demo

 本次目的主要是利用ai生成项目整个框架,最终实现能够modbus tcp采集显示实时数据,查询历史数据。

 

1.利用AI生成提示词-创建一个项目

建议创建一个新的项目文件夹,我的文件夹名称是IndustrialWebScada,然后用Cursor打开

 

image

 

输入第一句提示词

你现在是我的 C# 工业 WebSCADA 软件架构师和高级开发工程师。

请基于 .NET 8 帮我创建一个完整的 IndustrialWebScada 项目。

软件目标:

1. Web 页面显示工业设备实时数据。

2. 后台支持 Modbus TCP 数据采集。

3. 后台支持 MQTT 多服务器发布。

4. Web 页面通过 SignalR 实时刷新。

5. 所有设备和点位来自 JSON 配置。

6. 支持历史数据存储和查询。

7. 支持报警配置和报警记录。

8. 支持后续扩展 Siemens S7、OPC UA。

 

请先不要直接写代码。

第一步请输出:

1. 项目整体架构

2. 解决方案目录结构

3. 每个项目职责

4. 核心数据流

5. 关键类设计

6. 分阶段开发计划

 

要求:

- 使用 C# / .NET 8

- 使用 Blazor Server

- 使用 SignalR

- 使用 BackgroundService

- 使用 MQTTnet

- 使用 JSON 配置点表

- 代码必须适合工业现场长期运行

 

AI回答以下内容 


# IndustrialWebScada 架构设计文档


## 1. 项目整体架构


```
┌─────────────────────────────────────────────────────────────────────┐
│ Blazor Server (Web UI) │
│ 仪表盘 · 设备状态 · 实时趋势 · 报警面板 · 历史查询 · 系统配置 │
└──────────────────────────┬──────────────────────────────────────────┘
│ SignalR Hub (实时推送)
┌──────────────────────────┴──────────────────────────────────────────┐
│ 应用服务层 (Application Layer) │
│ AlarmService · HistoryService · TagService · UserService │
│ 报警引擎 · 历史归档 · 点位管理 · 用户/权限 │
└────────┬───────────────┬───────────────┬────────────────────────────┘
│ │ │
┌────┴────┐ ┌──────┴──────┐ ┌─────┴──────┐
│ 数据总线 │ │ 报警引擎 │ │ 历史归档 │
│(Channel)│ │(AlarmEngine)│ │(History │
│ │ │ │ │ Archiver) │
└────┬────┘ └─────────────┘ └────────────┘

┌────────┴────────────────────────────────────────────────────────────┐
│ 采集抽象层 (Collection Abstraction) │
│ IProtocolDriver · IDriverFactory · TagDataSnapshot │
└──┬──────────────┬──────────────────────┬────────────────────────────┘
│ │ │
┌──┴───┐ ┌─────┴─────┐ ┌─────────────┴──────────────────────────────┐
│Modbus│ │ MQTT │ │ 预留: S7 / OPC UA / 其他协议驱动 │
│Driver│ │ Publisher │ │ (IProtocolDriver 实现) │
│ │ │(MQTTnet) │ └───────────────────────────────────────────┘
└──────┘ └───────────┘


┌─────────────────────────────────────────────────────────────────────┐
│ 基础设施层 (Infrastructure) │
│ SQLite/PostgreSQL(历史) · JSON配置(点表) · 日志(Serilog) · DI容器 │
└─────────────────────────────────────────────────────────────────────┘
```


**架构风格**:**模块化单体 (Modular Monolith)** — 单解决方案、多项目分层,未来需要时可拆分为微服务。


---


## 2. 解决方案目录结构


```
IndustrialWebScada/
├── IndustrialWebScada.sln

├── src/
│ ├── IndustrialWebScada.Web/ # Blazor Server 宿主
│ │ ├── Components/
│ │ │ ├── Layout/
│ │ │ │ ├── MainLayout.razor
│ │ │ │ └── NavMenu.razor
│ │ │ ├── Pages/
│ │ │ │ ├── Dashboard.razor # 实时总览仪表盘
│ │ │ │ ├── DeviceDetail.razor # 单设备详情
│ │ │ │ ├── AlarmPanel.razor # 实时报警面板
│ │ │ │ ├── HistoryQuery.razor # 历史数据查询
│ │ │ │ └── SystemConfig.razor # 系统配置
│ │ │ ├── Shared/
│ │ │ │ ├── TagValueCard.razor # 点位值卡片组件
│ │ │ │ ├── TrendChart.razor # 趋势图组件
│ │ │ │ └── AlarmBanner.razor # 报警横幅
│ │ │ └── _Imports.razor
│ │ ├── wwwroot/
│ │ ├── Program.cs
│ │ ├── appsettings.json
│ │ └── Hubs/
│ │ └── ScadaHub.cs # SignalR Hub
│ │
│ ├── IndustrialWebScada.Application/ # 应用逻辑层
│ │ ├── Services/
│ │ │ ├── TagService.cs # 点位查询/管理
│ │ │ ├── AlarmService.cs # 报警管理
│ │ │ ├── HistoryService.cs # 历史数据读写
│ │ │ └── DeviceService.cs # 设备管理
│ │ ├── Alarm/
│ │ │ ├── AlarmEngine.cs # 报警判断引擎
│ │ │ ├── AlarmRule.cs # 报警规则模型
│ │ │ └── AlarmRecord.cs # 报警记录模型
│ │ ├── History/
│ │ │ └── HistoryArchiver.cs # 定时归档 BackgroundService
│ │ └── Interfaces/ # 应用层接口
│ │
│ ├── IndustrialWebScada.Core/ # 领域模型 + 核心抽象
│ │ ├── Models/
│ │ │ ├── Device.cs # 设备模型
│ │ │ ├── TagPoint.cs # 点位模型
│ │ │ ├── TagValue.cs # 点位实时值
│ │ │ └── AlarmRecord.cs # 报警记录
│ │ ├── Configuration/
│ │ │ ├── ScadaConfig.cs # 顶层配置
│ │ │ ├── DeviceConfig.cs # 设备配置节
│ │ │ ├── TagConfig.cs # 点位配置节
│ │ │ ├── ModbusConfig.cs # Modbus 参数
│ │ │ ├── MqttConfig.cs # MQTT 参数
│ │ │ └── AlarmConfig.cs # 报警配置节
│ │ ├── Drivers/
│ │ │ ├── IProtocolDriver.cs # 协议驱动接口
│ │ │ ├── IDriverFactory.cs # 驱动工厂接口
│ │ │ └── DriverStatus.cs # 驱动状态枚举
│ │ └── Events/
│ │ ├── TagChangedEventArgs.cs # 点位变更事件
│ │ └── AlarmEventArgs.cs # 报警事件
│ │
│ ├── IndustrialWebScada.Drivers/ # 协议驱动实现
│ │ ├── Modbus/
│ │ │ ├── ModbusTcpDriver.cs # Modbus TCP 驱动
│ │ │ ├── ModbusDriverFactory.cs # Modbus 驱动工厂
│ │ │ └── ModbusDataConverter.cs # 数据类型转换
│ │ ├── Mqtt/
│ │ │ ├── MqttPublisher.cs # MQTT 发布服务
│ │ │ └── MqttPublisherHostedService.cs # MQTT 后台服务
│ │ └── S7/ # 预留
│ │ └── Placeholder
│ │
│ ├── IndustrialWebScada.Infrastructure/ # 基础设施
│ │ ├── Persistence/
│ │ │ ├── ScadaDbContext.cs # EF Core DbContext
│ │ │ ├── HistoryRepository.cs # 历史数据仓储
│ │ │ └── AlarmRepository.cs # 报警记录仓储
│ │ ├── Configuration/
│ │ │ └── JsonConfigLoader.cs # JSON 点表加载器
│ │ └── Logging/
│ │ └── SerilogConfigurator.cs # Serilog 配置
│ │
│ └── IndustrialWebScada.BackgroundServices/ # 后台任务
│ ├── DataCollectionService.cs # 数据采集主循环
│ ├── AlarmMonitorService.cs # 报警监控服务
│ ├── HistoryArchiveService.cs # 历史归档服务
│ └── MqttPublishService.cs # MQTT 发布服务

├── config/
│ ├── scada-config.json # 点表配置 (设备/点位/报警)
│ └── scada-config.schema.json # 配置 JSON Schema

├── tests/
│ ├── IndustrialWebScada.Drivers.Tests/
│ ├── IndustrialWebScada.Application.Tests/
│ └── IndustrialWebScada.IntegrationTests/

└── docs/
├── architecture.md
└── config-guide.md
```


---


## 3. 每个项目职责


| 项目 | 职责 | 依赖 |
|---|---|---|
| **IndustrialWebScada.Core** | 领域模型、配置 POCO、协议驱动接口(`IProtocolDriver`)、事件定义。**零外部依赖**,仅引用 `System.*` | 无 |
| **IndustrialWebScada.Drivers** | 协议驱动具体实现:Modbus TCP 读写、MQTT 发布。每种协议一个子目录,实现 Core 中的接口 | Core, MQTTnet, NModbus4 |
| **IndustrialWebScada.Application** | 应用服务编排:点位管理、报警引擎(阈值/状态判断)、历史归档调度。**不含 UI 和协议细节** | Core |
| **IndustrialWebScada.Infrastructure** | 持久化(EF Core + SQLite/PG)、JSON 配置加载、日志配置 | Core, EFCore, Serilog |
| **IndustrialWebScada.BackgroundServices** | 所有 `BackgroundService`:数据采集循环、报警监控、历史归档、MQTT 发布 | Core, Drivers, Application, Infrastructure |
| **IndustrialWebScada.Web** | Blazor Server 宿主:页面、SignalR Hub、DI 注册、启动配置 | 所有项目 |


---


## 4. 核心数据流


### 4.1 实时数据流(主循环)


```
JSON点表 → 加载配置 → 创建 IProtocolDriver[] → BackgroundService 定时轮询


ModbusTcpDriver.PollAsync() → TagValue[] (原始采集值)

├─→ TagValueStore (内存快照,ConcurrentDictionary)
│ │
│ ├─→ AlarmEngine.Evaluate() → 产生/解除报警 → AlarmRecord → 入库 + SignalR 推送
│ │
│ ├─→ ScadaHub.Clients.All.SendAsync("TagUpdate") → Blazor 页面实时刷新
│ │
│ └─→ MqttPublisher.PublishAsync() → 发布到所有配置的 MQTT Broker

└─→ HistoryArchiveService (每 N 秒批量写入历史表)
```


### 4.2 历史查询流


```
Blazor页面 (HistoryQuery.razor)
→ HistoryService.GetHistoryAsync(tagId, from, to)
→ HistoryRepository (EF Core LINQ)
→ SQLite/PostgreSQL
→ 返回 → 趋势图渲染 (Chart.js 或 Plotly)
```


### 4.3 报警流


```
AlarmEngine 检测到报警条件满足
→ 生成 AlarmRecord { TagId, Level, Message, Timestamp }
→ AlarmRepository.InsertAsync() (持久化)
→ ScadaHub 推送 "AlarmRaised" 到前端
→ 前端 AlarmPanel 实时显示 + 声音提示
→ 操作员确认 → AlarmRecord.Status = Acknowledged
```


---


## 5. 关键类设计


### 5.1 协议驱动接口


```csharp
// Core 层 - 协议驱动抽象
public interface IProtocolDriver
{
string DriverId { get; }
string ProtocolName { get; } // "ModbusTcp" / "S7" / "OpcUa"
DriverStatus Status { get; }


Task InitializeAsync(DriverConfig config, CancellationToken ct);
Task<IReadOnlyList<TagValue>> PollAsync(IReadOnlyList<TagPoint> points, CancellationToken ct);
Task WriteAsync(string tagId, object value, CancellationToken ct);
Task StopAsync(CancellationToken ct);


event EventHandler<TagChangedEventArgs> TagChanged;
event EventHandler<DriverStatusChangedEventArgs> StatusChanged;
}


public interface IDriverFactory
{
IProtocolDriver Create(string protocolName);
}
```


### 5.2 核心模型


```csharp
public class Device
{
public string DeviceId { get; set; } // "PLC001"
public string Name { get; set; } // "1号生产线PLC"
public string Protocol { get; set; } // "ModbusTcp"
public DriverConfig DriverConfig { get; set; }
public List<TagPoint> Tags { get; set; }
}


public class TagPoint
{
public string TagId { get; set; } // "PLC001.Temperature"
public string DeviceId { get; set; }
public string Name { get; set; } // "炉温"
public string DataType { get; set; } // "Float32" / "Int16" / "Bool"
public string Address { get; set; } // "40001" (Modbus 地址)
public string Unit { get; set; } // "℃"
public int ScanRateMs { get; set; } // 1000
public bool EnableHistory { get; set; }
public List<AlarmRule> AlarmRules { get; set; }
}


public class TagValue
{
public string TagId { get; set; }
public object Value { get; set; }
public QualityCode Quality { get; set; } // Good / Bad / Uncertain
public DateTime Timestamp { get; set; }
}


public enum QualityCode { Good, Bad, Uncertain, Timeout }
```


### 5.3 报警引擎


```csharp
public class AlarmRule
{
public string RuleId { get; set; }
public string TagId { get; set; }
public AlarmType Type { get; set; } // HighHigh / High / Low / LowLow / State
public double Threshold { get; set; }
public AlarmSeverity Severity { get; set; } // Critical / Warning / Info
public int DeadbandPercent { get; set; } // 死区,防止抖动
public int DelaySeconds { get; set; } // 延时确认
public string Message { get; set; }
}


public enum AlarmType { HighHigh, High, Low, LowLow, StateChange, Deviation }
public enum AlarmSeverity { Critical, Warning, Info }


public class AlarmEngine
{
// 内部维护每个规则的状态机: Normal → Pending → Active → Acked → Normal
public IEnumerable<AlarmRecord> Evaluate(IReadOnlyDictionary<string, TagValue> snapshot);
}
```


### 5.4 SignalR Hub


```csharp
public class ScadaHub : Hub
{
// 客户端订阅指定设备的点位
public async Task SubscribeDevice(string deviceId);
public async Task UnsubscribeDevice(string deviceId);


// 服务端推送(由 DataCollectionService 调用)
// TagUpdate: { tagId, value, quality, timestamp }
// AlarmRaised: { record }
// AlarmCleared: { ruleId, tagId }
// DriverStatusChanged: { driverId, status }
}
```


### 5.5 数据采集服务(核心 BackgroundService)


```csharp
public class DataCollectionService : BackgroundService
{
private readonly IProtocolDriver[] _drivers;
private readonly TagValueStore _store; // ConcurrentDictionary 封装
private readonly AlarmEngine _alarmEngine;
private readonly MqttPublisher _mqttPublisher;
private readonly IHubContext<ScadaHub> _hubContext;


protected override async Task ExecuteAsync(CancellationToken ct)
{
// 1. InitializeAsync 所有驱动
// 2. 按 ScanRate 分组,为每组创建独立轮询循环
// 3. 轮询循环:
// poll → update store → evaluate alarms → hub push → mqtt publish
// 4. 异常时不崩溃,记录日志,指数退避重试
}
}
```


### 5.6 JSON 配置结构


```jsonc
{
"Scada": {
"Devices": [
{
"DeviceId": "PLC001",
"Name": "1号线温控PLC",
"Protocol": "ModbusTcp",
"DriverConfig": {
"Host": "192.168.1.100",
"Port": 502,
"UnitId": 1,
"TimeoutMs": 3000,
"RetryCount": 3
},
"Tags": [
{
"TagId": "PLC001.FurnaceTemp",
"Name": "炉温",
"DataType": "Float32",
"Address": "40001",
"Unit": "℃",
"ScanRateMs": 1000,
"EnableHistory": true,
"AlarmRules": [
{
"RuleId": "PLC001.FurnaceTemp.HH",
"Type": "HighHigh",
"Threshold": 850,
"Severity": "Critical",
"DeadbandPercent": 2,
"DelaySeconds": 5,
"Message": "炉温超高高限!"
}
]
}
]
}
],
"MqttPublishers": [
{
"BrokerId": "CloudBroker",
"Host": "mqtt.example.com",
"Port": 1883,
"ClientId": "ScadaPublisher",
"TopicPrefix": "scada/plant01",
"PublishIntervalMs": 2000
}
],
"History": {
"StorageType": "SQLite", // 或 "PostgreSQL"
"ConnectionString": "Data Source=scada-history.db",
"ArchiveIntervalSeconds": 10,
"RetentionDays": 365
}
}
}
```


---


## 6. 分阶段开发计划


### Phase 1:基础框架 + Modbus 采集 + 内存刷新(约 3-4 天)


| 任务 | 产出 |
|---|---|
| 创建解决方案和 6 个项目骨架 | sln + csproj 引用链 |
| 实现 Core 层所有模型和接口 | Device, TagPoint, TagValue, IProtocolDriver |
| 实现 JSON 配置加载 | JsonConfigLoader + schema |
| 实现 ModbusTcpDriver | 能连真实设备或模拟器读寄存器 |
| 实现 DataCollectionService | BackgroundService 驱动轮询 |
| Blazor 首页 + SignalR 基础 | Dashboard 显示点位实时值 |


**验收标准**:启动后自动连接 Modbus 设备,Blazor 页面实时显示点位值。


### Phase 2:MQTT 发布 + 历史存储(约 2-3 天)


| 任务 | 产出 |
|---|---|
| 实现 MqttPublisher(MQTTnet) | 支持多 Broker 并行发布 |
| 实现 EF Core + SQLite 历史表 | HistoryRepository |
| 实现 HistoryArchiveService | 定时批量归档 |
| 历史查询页面 | HistoryQuery.razor + 趋势图 |


**验收标准**:数据持续写入 SQLite,页面可按时间范围查询历史趋势。


### Phase 3:报警系统(约 2 天)


| 任务 | 产出 |
|---|---|
| 实现 AlarmEngine(状态机 + 死区 + 延时) | 阈值判断 + 防抖 |
| 实现 AlarmRepository | 报警记录持久化 |
| 实现 AlarmMonitorService | 后台报警扫描 |
| 报警面板页面 | 实时报警列表 + 确认操作 + 声音 |


**验收标准**:温度超限时产生报警记录,页面实时弹出,操作员可确认。


### Phase 4:完善和加固(约 2-3 天)


| 任务 | 产出 |
|---|---|
| Serilog 结构化日志 | 文件 + 控制台,工业级日志轮转 |
| 异常容错:驱动断线重连 | 指数退避 + 状态上报 |
| 配置热重载 | 监听 JSON 变更,不停机生效 |
| 设备管理页面 | 设备列表、在线状态、手动写值 |
| 单元测试(核心逻辑) | AlarmEngine + ModbusDataConverter |


### Phase 5:扩展协议(后续)


| 任务 | 说明 |
|---|---|
| S7 驱动(S7netplus) | 实现 IProtocolDriver,配置层新增 S7Config |
| OPC UA 驱动(OPCFoundation.NetStandard.Opc.Ua) | 同上 |
| 用户权限管理 | 登录 + 角色 + 操作审计 |


---


## 7. 关键技术决策说明


| 决策 | 理由 |
|---|---|
| **模块化单体** 而非微服务 | 工业现场单机部署为主,降低运维复杂度;接口已按协议抽象,未来可拆 |
| **SQLite** 作为默认历史库 | 零配置部署,单机场景够用;接口层可切 PostgreSQL |
| **Channel<T>** 做进程内事件总线 | 高吞吐、零分配、无外部依赖,比 MediatR 更适合高频数据流 |
| **ConcurrentDictionary** 做实时值缓存 | 点位数量可控(通常 < 10万),读多写少,性能最优 |
| **每个驱动独立 BackgroundService** | Modbus 轮询和 MQTT 发布生命周期独立,互不影响 |
| **JSON 点表而非数据库** | 现场工程师可直接编辑文件,版本管理方便,符合工控习惯 |


---


如确认此架构方案,我将开始 Phase 1 的代码实现。

 

 

 然后让AI帮你创建整个完整项目

2.针对创建后完毕后项目进行测试

打开终端,

本次以windows为例

win+r 输入cmd 打开终端,cd D:\003Develop\006WebScada\IndustrialWebScada\src\IndustrialWebScada.Web  然后输入dotnet run(这个是我文件的目录,不知道的可以问一下ai如何测试)

本次生成的项目主要存在以下问题。

1:界面上无法显示实时数据(反复让ai解决这个问题)

如果你出现上下文太多context text使用快要超过100%的情况,建议专门新建一个agent解决后续问题

 

 最终生成效果如下

image

 

 

image

 

 本次生成的demo文件github链接https://github.com/suwencjp/VibeCodingIndustrialWebScada,建议cursor配置好github仓库,方便后期项目管理。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2026-05-06 08:48  SuwenLab  阅读(39)  评论(0)    收藏  举报