
一、项目定位与技术选型说明
1.1 核心定位
一套跨平台工业组态 SCADA 系统,包含组态设计器(拖拽画布、元件编辑) + 运行监控客户端(实时数据、告警、联动逻辑) + 后台数据服务(采集、存储、协议解析),支持 Windows/Linux/ 国产信创(银河麒麟、统信),替代传统 WinForm/WPF 组态,轻量化无依赖。
1.2 技术栈清单
表格
| 分层 | 技术组件 | 作用 |
|---|---|---|
| 主框架 | .NET 8 + Avalonia UI 11 | 跨平台桌面渲染、MVVM 界面 |
| MVVM 架构 | ReactiveUI 19 | 响应式数据绑定、生命周期管理、异步采集解耦 |
| 依赖注入 | Microsoft.Extensions.DependencyInjection | 模块化服务注册、分层解耦 |
| 工业协议 | NModbus4、S7.NET、OPC UA .NET Standard | Modbus RTU/TCP、西门子 S7、OPC UA 设备采集 |
| 实时内存库 | Microsoft.Data.Sqlite + LiteDB | 本地测点缓存、历史轻量化存储;可选 InfluxDB 时序库 |
| 画布渲染 | Avalonia Canvas + 自定义 Shape 控件 | 组态图元拖拽、缩放、图层、对齐吸附 |
| 序列化 | System.Text.Json(自定义 SnakeCase 映射) | 工程文件、测点配置、图元模板持久化 |
| 后台调度 | Microsoft.Extensions.Hosting + BackgroundService | 独立采集后台、告警扫描、定时任务 |
| 权限日志 | ASP.NET Core Identity 轻量化封装 | 操作员分级、操作日志、告警记录 |
| 打包发布 | Avalonia.Desktop + PublishSingleFile | 单文件部署、Linux/Windows 独立包 |
1.3 架构设计核心原则
- 前后端分离:UI 层(Avalonia)与采集业务层完全隔离,采集逻辑可单独编译为后台服务;
- 模块插拔式:协议驱动、图元库、报表、告警、权限均为独立模块,按需加载;
- 响应式数据流:所有测点数据采用 ReactiveUI Observable 推送,无轮询 UI 阻塞;
- 跨平台兼容:不依赖 Windows GDI,统一渲染管线适配信创系统;
- 工程化隔离:每个组态工程独立文件存储,支持多工程切换、导入导出。
二、整体四层模块化架构总览
plaintext
┌─────────────────────────────────────────────────────────────┐
│ 第一层:Avalonia 桌面UI表现层(组态设计器 + 运行监控视图) │
│ ├─ 组态画布模块、图元控件库、属性编辑器、菜单工具栏 │
│ ├─ 实时监控面板、告警弹窗、趋势曲线、报表视图 │
│ └─ 用户登录、权限视图、系统配置页面 │
├─────────────────────────────────────────────────────────────┤
│ 第二层:ViewModel业务中间层(ReactiveUI) │
│ ├─ 工程管理VM、画布编辑VM、测点管理VM │
│ ├─ 采集调度VM、告警处理VM、历史曲线VM │
│ └─ 全局状态管理器(当前工程、在线设备、用户身份) │
├─────────────────────────────────────────────────────────────┤
│ 第三层:核心业务服务层(DI全局注入) │
│ ├─ 工程文件服务、图元模板服务、测点配置服务 │
│ ├─ 工业协议驱动管理器、实时数据缓存服务 │
│ ├─ 告警服务、联动脚本服务、历史存储服务 │
│ └─ 权限服务、日志服务、系统配置服务 │
├─────────────────────────────────────────────────────────────┤
│ 第四层:底层硬件/数据基础设施层 │
│ ├─ 通信驱动抽象层(Modbus/S7/OPC UA统一接口) │
│ ├─ 本地文件持久化(Json工程、LiteDB测点缓存) │
│ ├─ 数据库抽象层(SQLite/InfluxDB/Mysql 适配) │
│ └─ 后台定时任务、异步消息总线、异常重试机制 │
└─────────────────────────────────────────────────────────────┘
三、各模块详细拆分与职责落地
模块组 1:基础设施底层模块(基础依赖,所有模块共用)
3.1.1 模块:Core.Shared 公共基础库
输出类库,无 UI,全局引用
- 通用模型:测点 PointModel、设备 DeviceModel、告警 AlarmModel、图元 BaseShapeModel;
- 全局枚举:数据类型、采集周期、告警等级、图元类型、协议类型;
- 扩展工具:Json 序列化(蛇形命名映射)、字节转换、工业数值换算;
- 统一异常定义:采集异常、协议解析异常、工程文件损坏异常;
- 消息总线接口
IMessageBus:跨模块事件分发(设备上线、测点值变更、告警触发)。
3.1.2 模块:Core.Communication 通信抽象层
驱动解耦核心,采用策略模式
- 抽象接口
IDeviceDriver
csharp
运行
public interface IDeviceDriver : IDisposable
{
Task ConnectAsync();
Task DisconnectAsync();
Task<Dictionary<string, double>> ReadPointsAsync(List<string> pointTags);
Task WritePointAsync(string tag, object value);
IObservable<PointValue> PointValueChanged { get; }
bool IsConnected { get; }
}
- 独立驱动实现(可单独删减)
- Driver.Modbus:ModbusTcp/Rtu
- Driver.S7:西门子 S7 协议
- Driver.OpcUa:OPC UA 客户端
DriverManagerService:驱动工厂,根据设备配置自动实例化对应驱动,统一管理连接池、断线重连。
3.1.3 模块:Core.Storage 数据持久化抽象
统一存储接口,切换数据库无需改上层业务
IProjectStorage:组态工程读写(JSON 序列化画布、测点、图元)IRuntimeCache:内存实时测点缓存(ConcurrentDictionary + Reactive 推送)IHistoryStorage:历史数据存储实现(LiteDB 本地轻量、InfluxDB 时序)IAlarmStorage:告警记录、操作日志持久化
模块组 2:核心业务服务模块(DI 注入,UI 无直接依赖)
全部注册为 Scoped/Singleton 后台服务,可脱离 Avalonia 单独运行
- ProjectService 工程管理服务
- 创建 / 打开 / 保存 / 另存组态工程;
- 工程加密、模板导入导出、画布图层管理;
- 加载工程时自动加载测点、设备、图元配置。
- PointCollectService 采集调度服务(BackgroundService)
- 轮询分组调度:按采集周期分组批量读取设备测点;
- 限流、断线重试、心跳检测;
- 读取值推送至消息总线,供画布、趋势、告警订阅。
- AlarmService 告警逻辑服务
- 阈值告警、变化率告警、断线告警、开关量变位告警;
- 告警确认、屏蔽、分级弹窗、声光通知;
- 实时告警队列维护,历史告警入库。
- LinkageScriptService 联动逻辑服务
- 轻量表达式解析(测点四则运算、条件判断);
- 测点联动下发写值、多设备联锁逻辑;
- UserAuthService 权限服务
- 用户、角色、功能权限(编辑组态 / 仅监控 / 管理员);
- 操作日志记录(修改画布、下发控制指令)。
模块组 3:Avalonia UI 控件基础模块(UI 层底层)
3.3.1 UI.Controls 通用工业控件库
自定义可复用 Avalonia 控件,支持设计器预览
- 基础图元:矩形、圆形、折线、管道、阀门、电机、指示灯;
- 数据展示:数字显示、棒图、仪表盘、趋势曲线 Chart;
- 交互控件:手动输入按钮、切换开关、弹窗面板;
- 图层容器:LayerCanvas(支持图层锁定、隐藏、吸附对齐、缩放平移)。 所有图元统一继承
BaseShapeControl,绑定对应BaseShapeModel实现 MVVM 双向绑定。
3.3.2 UI.Designer 组态设计器专用模块
拖拽编辑核心模块,仅组态编辑模式加载
- 工具箱模块:图元分类侧边栏、自定义模板拖拽;
- 画布编辑模块:多选、复制粘贴、层级调整、对齐、网格吸附;
- 属性面板模块:选中图元后动态渲染属性编辑器(颜色、坐标、绑定测点、闪烁告警样式);
- 模板管理:保存自定义图元模板至本地库。
3.3.3 UI.Runtime 运行监控视图模块
工程运行模式,禁用编辑功能,仅展示实时数据
- 运行画布渲染(隐藏编辑控制点、锁定图层);
- 实时趋势曲线视图(历史数据分页查询、缩放);
- 告警中心弹窗、告警列表分页;
- 设备状态总览面板、远程手动控制弹窗。
模块组 4:ReactiveUI ViewModel 层(中间桥接 UI 与服务)
完全分离界面与业务逻辑,所有 VM 通过构造函数注入服务接口
- 全局根 VM
AppRootViewModel:管理全局状态、当前打开工程、登录用户、消息总线订阅; - 设计器 VM
DesignerViewModel:画布操作、选中图元、工具箱交互、工程保存; - 运行 VM
RuntimeViewModel:订阅测点数据流、刷新图元动态效果、告警监听; - 独立子 VM:PointManageViewModel、AlarmViewModel、UserConfigViewModel; 生命周期规范 :所有控件 VM 实现
WhenActivated,订阅数据流并绑定DisposeWith防止内存泄漏。
模块组 5:启动入口模块(双启动模式)
3.5.1 App.Desktop Avalonia 桌面主程序
- Avalonia Application 入口,配置 DI 容器、注册所有服务、控件;
- 双模式启动:
- 设计模式:加载 DesignerWindow
- 运行模式:直接打开 RuntimeWindow,隐藏编辑功能
- 全局样式、工业主题、字体适配国产系统;
- 单文件打包发布配置,支持 Windows/Linux x64/ARM64。
3.5.2 App.Service 独立采集后台(可选)
无 Avalonia 依赖,纯.NET 控制台 / Windows 服务
- 仅加载 Core 底层服务,负责 7×24 小时采集、存储、告警;
- 桌面客户端可通过本地 IPC 与后台服务通信,分离采集与界面渲染,界面关闭不中断采集。
四、落地实施全流程(从 0 到 1 开发步骤)
阶段 1:解决方案与项目分层搭建(1-3 天)
- 创建.NET 解决方案,按上述模块拆分类库,严格分层引用约束:
- Core 底层库不引用任何 Avalonia/UI 层;
- ViewModel 层仅依赖 Core 服务接口,不依赖具体驱动实现;
- UI 层仅依赖 ViewModel 与 UI 控件库;
- 配置 DI 容器封装:创建
ServiceCollectionExtensions扩展方法,批量注册所有业务服务、驱动、存储实现; - 定义全局消息总线,统一测点变更、告警、设备状态事件模型。
阶段 2:底层通信与存储模块开发(3-7 天)
- 实现设备驱动抽象接口,完成 Modbus/S7 基础驱动开发,编写单元测试模拟寄存器读写;
- 实现工程 JSON 序列化模型,完成画布图元、测点、设备配置持久化;
- 开发本地缓存 LiteDB 封装,实现实时测点读写、历史数据分页查询;
- 实现断线重连、采集异常重试、通信日志打印机制。
阶段 3:Avalonia 工业图元控件库开发(7-12 天)
- 封装基础 LayerCanvas 图层画布,实现平移、缩放、网格吸附;
- 开发基础工业图元控件(电机、阀门、指示灯、管道),绑定测点动态颜色 / 闪烁;
- 封装趋势曲线、仪表盘、数值显示控件,支持 ReactiveUI 数据流绑定;
- 编写控件预览,兼容 Avalonia 设计器。
阶段 4:组态设计器拖拽编辑逻辑(10-15 天)
- 实现工具箱拖拽逻辑(PointerPressed/PointerMoved 拖拽预览);
- 画布多选、复制、删除、层级上下移、对齐工具;
- 动态属性面板:根据选中图元类型自动渲染属性输入框、测点绑定下拉框;
- 工程保存 / 加载逻辑,序列化画布所有图元、测点关联关系。
阶段 5:采集调度、告警、联动业务开发(7-10 天)
- BackgroundService 采集后台,按周期分组批量读取设备测点;
- 消息总线订阅:测点值变更自动推送画布所有绑定图元,实时刷新;
- 告警阈值判断逻辑,弹窗、告警列表、历史入库;
- 简单表达式联动脚本,实现测点联锁控制下发。
阶段 6:ViewModel 层与 UI 绑定整合(5-8 天)
- 按页面拆分所有 ViewModel,构造注入对应服务;
- 使用 WhenActivated 订阅数据流,统一释放 Disposable 防止内存泄漏;
- 绑定画布、属性面板、告警列表、趋势曲线响应式数据;
- 区分设计 / 运行两套视图逻辑,运行模式屏蔽编辑操作。
阶段 7:权限、日志、系统配置、跨平台适配(3-5 天)
- 用户登录、角色权限校验,隐藏无权限菜单按钮;
- 全链路操作日志、采集异常日志持久化;
- 适配 Linux / 国产系统字体、窗口缩放、单文件发布配置;
- 全局工业深色主题、界面缩放兼容高分屏。
阶段 8:联调、压力测试、打包交付(5 天 +)
- 联调全链路:新建工程→添加设备测点→拖拽图元绑定→启动采集→实时刷新→告警触发;
- 压力测试:500 + 测点并发采集、100 + 图元同时刷新,检测内存泄漏、UI 卡顿;
- 打包:Windows 单文件 exe、Linux 独立运行包;
- 编写组态工程模板、部署文档、二次开发接口说明。
五、关键技术难点落地解决方案
5.1 画布大量图元渲染卡顿问题
方案:
- 使用 Avalonia
VisualLayer离屏缓存静态图元,仅动态测点图元实时重绘; - 测点数据流节流(Throttle),高频变化测点限制刷新频率;
- 图层分块渲染,隐藏图层跳过绘制逻辑;
- 所有数值更新走 ReactiveUI 绑定,禁止后台线程直接操作 UI 控件。
5.2 多设备采集并发、连接池管理
- 每个设备驱动独立连接实例,单设备串行读写避免端口冲突;
- 采集任务按周期分组调度,统一线程池限流,防止 TCP 连接耗尽;
- 断线自动标记测点为 "故障",画布图元变灰提示,后台定时重试连接。
5.3 工程文件序列化复杂画布结构
- 分层序列化:工程→设备列表→测点列表→画布图层→图层内所有图元;
- BaseShapeModel 多态序列化:使用 Json 派生类型转换器,识别不同图元子类;
- 工程版本号兼容,新版本自动兼容旧组态文件。
5.4 Avalonia 跨平台(国产信创)兼容
- 禁用 Windows 专属 API,全部使用 Avalonia 跨平台封装;
- 内置思源黑体等开源字体,避免 Linux 缺失字体乱码;
- 发布时指定 RuntimeIdentifier:win-x64、linux-x64、linux-arm64;
- Linux 打包附带 libSkiaSharp 原生依赖。
5.5 内存泄漏风险(长期运行 7×24 小时)
强制规范:
- 所有 IObservable 订阅必须
.DisposeWith(this); - 切换工程时清空画布 VM、释放所有驱动连接、清空消息总线订阅;
- IDeviceDriver 统一实现 IDisposable,窗口关闭强制释放 TCP / 串口资源;
- 定时内存快照检测,清理过期历史缓存。
六、扩展迭代规划(模块化扩展能力)
- 新增协议驱动:只需新增 Driver.XXX 类库,实现 IDeviceDriver,DI 自动注册,上层 UI 无需修改;
- 新增工业图元:新增控件库图元 + 对应 Model,工具箱自动扫描加载;
- 新增存储数据库:实现 IHistoryStorage 新适配类,DI 切换注入即可;
- Web 端可视化扩展:Core 业务层完全复用,单独开发 Blazor Web 后端共享采集服务;
- 报表 / 打印模块:独立 UI.Report 模块,按需引入,不影响基础组态核心;
- 脚本高级逻辑:集成 Lua/Jint 脚本引擎,复杂联锁逻辑扩展。