简介:这是一份面向工业软件实施与开发人员的AVEVA系统平台界面定制与开发教程,涵盖平台架构、核心组件及界面定制完整流程,旨在帮助读者掌握从仪表板配置到自定义应用开发的实用技能。资源以docx文档形式整理,全文共1个文件,压缩包大小约40KB,内容结构清晰,适合作为AVEVA System Platform入门与进阶的参考手册;目前已有86人学习。文档重点包括AVEVA Insight、Connect、Operations等核心组件的功能定位,定制界面与数据模型之间的关系,以及定制前的环境配置、权限设置、备份等准备工作;同时具体介绍了使用AVEVA Design System拖放控件、配置图表与报警列表的方法,并给出创建仪表板的实操步骤、用Python连接PI服务器读取数据点的代码示例,以及通过API或OPC-UA集成ERP、SCADA、MES等外部系统的思路。整体内容由浅入深,兼顾界面设计与代码开发,能够帮助读者快速理解界面定制原理并上手实操,提升工业数字化项目的交付效率。
1. AVEVA 系统平台界面定制:先从一次现场改造说起
你们可能接过这样的活:一套流程工业的 SCADA 画面看了一年多,现场操作员还是每天抱怨按钮太小、报警看不清、翻好几页才能找到关键参数。换新系统投入太大,在 AVEVA System Platform 上做界面定制就成了最现实的解法。这份教程讲的就是这条路——从开发环境搭建、画面布局、控件开发,到把实时数据绑定到界面,基本覆盖了定制一个工业上位机界面的全部环节。它适合两类人:一类是要给现场做 HMI 改造的工程师,另一类是想摸清 AVEVA 这套平台上怎么挂自定义控件的开发人员。说白了,这是把平台从“黑匣子”变成“能改的界面”的那类资料。
2. 开发环境搭建:从组件勾选到编译出第一个自定义面板
2.1 开发机选型与组件勾选:别把整套平台都装上去
很多人第一次装 AVEVA System Platform,习惯性选了“典型安装”,结果装完一看,一堆用不上的服务占着内存,界面定制要用的 Designer 反而不一定齐。教程里建议开发环境选“自定义”而不是“典型”,这个点很实在。勾选组件时,关键是确认这几项:AVEVA System Platform Designer 或等效的 IDE 工具、OPC UA 网关组件(后面连实时数据要用)、历史库客户端组件,以及开发宿主如果需要 OMI 的话那一整套 Web 宿主环境。
组件选型对照表可以这么参考:
| 用途 | 必装组件 | 可后续再补 |
|---|---|---|
| 界面拖放设计 | Designer / InTouch 开发环境 | 云端可视化件 |
| 实时数据接入 | OPC UA 客户端组件、PI Server 客户端 | 历史数据分析组件 |
| Web 端定制 | OMI Runtime、App Server | —— |
| 自定义控件编译 | .NET SDK、IDE | 各类第三方图表库 |
教程正文里没有细说装完后要做什么,我一般会补一步:装完立刻检查 Windows 服务列表里 AVEVA 相关的服务是否都起来了,再打开 Designer 新建一个空工程试一次保存。这一步能提前暴露掉权限和数据库连接问题,免得后来写了一天代码才发现根本存不进工程里。还有个小习惯:给这台开发机固定一个专用域名解析,数据库连接字符串里用域名而不是localhost,后面接 OPC 和外部系统时能省很多事。
2.2 环境变量与 IDE 集成:先让编译器能找到 AVEVA 的库
安装只是第一步,让 Visual Studio 这类 IDE 能找到 AVEVA 的引用才是开发的起点。教程里写“在系统环境变量中添加 AVEVA System Platform 的路径”,实际开发中我通常是这么处理的:
- 在系统环境变量的
Path中加入C:\Program Files\AVEVA\下的主程序目录和 SDK 目录; - 在 IDE 的项目引用里,通过“浏览”直接定位 AVEVA 提供的 DLL,而不是把整个 SDK 目录一次性引进来,避免引用冲突;
- 确认目标框架是 .NET Framework 4.8 或者平台支持的对应版本,AVEVA 的控件库对 .NET Core 的支持要看具体版本,不要想当然。
这里的坑在于:AVEVA 安装后 DLL 版本很多,同一个功能可能出现在多个程序集里。更稳的做法是把引用列表里每一项的“复制本地”属性设成false,让编译产物运行时到 AVEVA 的安装目录去找 DLL,这样部署时不用带一整个依赖库过去。
2.3 第一个自定义面板:继承 Panel 并加载自定义元素
教程第 3 章给了一段 C# 自定义面板的代码,结构很清楚。它的核心思路是:你的类继承 AVEVA UI 框架里的Panel,在构造函数里做两件事——先调InitializeComponent()初始化框架组件,再调LoadCustomElements()加载自定义控件。下面是照着它能直接编译的工程代码:
// C# 示例:创建一个简单的 AVEVA 界面定制工程 using AVEVA.SystemPlatform.UI; namespace MyCustomInterface { public class CustomPanel : Panel { public CustomPanel() { InitializeComponent(); // 初始化组件,加载自定义界面元素 LoadCustomElements(); } private void LoadCustomElements() { // 示例:加载自定义的界面元素 Label label = new Label(); label.Text = "欢迎使用 AVEVA System Platform!"; label.Location = new Point(10, 10); this.Controls.Add(label); } } }这段代码的逻辑要说清楚:CustomPanel继承Panel后,就获得了 AVEVA UI 框架里面板容器的全部能力,包括控件集合、布局、事件分发。InitializeComponent()在真实工程里是设计器生成的,负责把你拖进界面的控件初始化为实例;这里手写调用是为了保证对象创建顺序。LoadCustomElements()里创建Label并设置Location,注意这是像素坐标,很多新人在动态布局时会踩这个坑——后面讲布局的时候会专门展开。
编译运行这一句,教程原文只说“检查自定义界面是否正确加载”。我补一个验证方法:在 IDE 里以调试模式启动工程后,不要只看画面有没有弹出来,要顺手打开 AVEVA 的运行时日志窗口,确认面板在宿主进程里被成功实例化。很多时候界面没显示出来,不是代码问题,是控件挂在了一个没有触发加载的宿主页面上。
3. 界面设计与布局:把默认模板改成操作员愿意用的画面
3.1 设计原则:工业界面不是网页设计
教程第 4 章开头列的设计原则——一致性、简洁性、可访问性、响应性、用户反馈、可定制性——初看像通用的 UI 设计清单,但在工业场景里有它特定的含义。以简洁性为例,网页设计追求的信息层级丰富在 DCS 操作站上反而不适用。现场操作员需要的是:正常时扫一眼就知道没事,异常时画面在几秒内把关键信息推到他眼前。我见过不少把画面做得像数据大屏的项目,最后都被现场要求改回去,因为信息密度太高反而拖慢了故障判断。
教程里讲可访问性时提到高对比度和键盘导航,这个在工业场景里比大多数 Web 项目更苛刻。操作站往往在强光环境或者夜间环境两套模式下切换,颜色对比度不能用默认值要单独调。键盘导航也不是可选项——现场很多操作员不用鼠标的,快捷键切画面是刚需。
3.2 布局管理器:拖放优先,代码兜底
教程给出了一套AVEVA_LayoutManager的 Python 示例,说可以用代码创建布局并添加控件:
# 创建布局并添加控件 layout = ALM.Layout() title_label = ALM.Label("欢迎使用 AVEVA System Platform") layout.addWidget(title_label, 0, 0, 1, 2) # 行,列,行跨度,列跨度 data_input = ALM.TextInput() layout.addWidget(data_input, 1, 0) data_display = ALM.DataDisplay() layout.addWidget(data_display, 1, 1) layout.setResponsive(True) layout.show()这里要说明一下:真正在 AVEVA Designer 里做画面,最常见的做法还是鼠标拖放,这套 Python 示例更像是把底层布局模型抽象出来演示网格定位逻辑。参数的含义是addWidget(控件, 行, 列, 行跨度, 列跨度)——(0,0,1,2)表示标题占第 0 行、从左列开始、横向跨两列;数据输入框和数据展示区放在第 1 行的左右两列。setResponsive(True)是启用响应式适配。这行代码对后续工作影响很大,需要单独说清楚:启用响应式后,画面里的控件会按网格比例缩放,而不是按像素硬撑。
我自己做批量画面时,会用代码生成而不是拖放。比如一个罐区有 30 台泵,每台泵的画面结构完全一样,只是数据点名字不同。拖放 30 遍既慢又容易漏 — 用布局参数生成 30 个画面,改布局参数就全部同步了。
3.3 动态布局调整:数据量大了,画面自动变大
教程第 4.3 节的动态调整示例,解决的是“同一画面在不同工况下显示密度不一样”的问题。它定义了一个layout.setDynamic(True),然后监听数据变化,当图表区域数据超过 100 个点、表格区域超过 50 行时,分别调整控件跨行跨列。核心思路是数据量驱动布局,而不是固定界面等数据。
做这个功能前,我的建议是先想清楚一个边界问题:动态调整大小只该发生在页面打开前或者用户空闲时,如果操作员正盯着一台泵的参数准备操作,画面突然重排了,那比数据挤在一起还危险。所以通常我会在dataChanged信号处理函数里加一个_isAdjusting互斥锁,调整期间不再触发新的 resize 事件,避免反复重排造成的画面抖动。
3.4 Web 端的响应式适配:OMI 页面定制会用到前端手段
如果你做的是 OMI 这类 Web 形态的 AVEVA 界面,那教程里的 JavaScript 和 CSS 示例就对上号了。比如用媒体查询做适配:
/* 屏幕宽度小于等于 600px 时切换浅色背景 */ @media screen and (max-width: 600px) { body { background-color: lightblue; } }这条规则的意思很直白:屏幕宽度小于等于 600px 时应用background-color: lightblue,否则忽略。操作站分辨率一般固定,但管理者用的平板和手机可能要看同一套画面,媒体查询就是为这种多终端场景准备的。再配合流式布局,宽度设成百分比、高度设成vh单位,就能做到不管屏幕多大,画面结构不散。真正做 OM I页面定制时,还要考虑浏览器内核版本和兼容性,工业现场经常有老设备,grid布局在一些老内核上不支持,项目规划早期就要确认终端范围。
4. 控件与交互开发:按钮、进度条和数据刷新
4.1 标准控件挂事件:刷新按钮的完整套路
教程第 5 章用一个刷新按钮把标准控件的用法串起来了。它的框架代码是这样的:
// C# 按钮点击事件处理 public class RefreshDataForm : Form { private Button refreshButton; public RefreshDataForm() { refreshButton = new Button(); refreshButton.Text = "刷新数据"; refreshButton.Click += new EventHandler(RefreshDataButton_Click); this.Controls.Add(refreshButton); } private void RefreshDataButton_Click(object sender, EventArgs e) { // 在这里实现数据刷新的逻辑 DataService.RefreshData(); } }这里的逻辑是:构造函数里创建Button实例,设置Text属性后,把事件处理器挂到Click事件上。+= new EventHandler(...)是标准的 C# 事件订阅写法,等价于把RefreshDataButton_Click方法注册为按钮点击的回调。用户点按钮时,框架触发Click,进而调用DataService.RefreshData()。注意DataService是外部服务,界面层不直接写数据访问逻辑——这一点等到第 6 章讲数据绑定时会进一步展开。
我会强调一个做法:把RefreshData()做成接口而不是直接绑一个具体的服务类。因为现场常有“开发机连测试库、生产机连实时库”的情况,按钮点击事件里如果直接用new DataService(),换环境就要改代码重编译;如果通过工厂或者依赖注入拿到服务实例,环境切换只需要改配置。
4.2 自定义控件:进度条开发的继承与扩展
教程里自定义进度条部分的代码,继承自ProgressBar并加了一个UpdateProgress方法:
public class CustomProgressBar : ProgressBar { public void UpdateProgress(int value) { this.Value = value; this.Refresh(); // 强制刷新界面 } }这里有个值得展开的点:为什么继承ProgressBar而不是重新写一个控件?因为ProgressBar已经封装了值和显示的映射关系、进度条绘画逻辑、以及 Windows 控件的消息循环,你只需要扩展它的更新接口。Refresh()在这里是关键——Value改变后 Windows Forms 不一定立刻重绘,尤其在循环里连续赋值时界面可能卡在旧值,显式调用Refresh()强制重绘是处理界面卡顿的常规手段。
教程的完整示例里在for循环里每 1 秒更新一次进度,模拟数据处理。实际工程里不会用Thread.Sleep(1000),因为这会把 UI 线程堵死。更合理的做法是用System.Windows.Forms.Timer定时器驱动进度更新,或者用Task.Run做后台计算、用Invoke把进度回传 UI 线程。这点不算教程的错,但照着示例写进生产代码,画面会在处理期间完全卡住。
4.3 功能模块集成测试:把数据服务从界面里拆出去
教程最后给了 NUnit 单元的示例:
[TestFixture] public class DataServiceTests { [Test] public void GetData_ShouldReturnValidData() { // 安排 string expectedData = "Sample Data"; // 行动 string actualData = DataServiceModule.GetData(); // 断言 Assert.AreEqual(expectedData, actualData); } }字面意思是:GetData_ShouldReturnValidData三个步骤——先设置期望值,再调GetData,最后断言相等。示例很浅,但背后的工程价值值得说:界面改到一半,功能模块的回归会不会顺手被破坏掉,单测能兜底。我给 AVEVA 项目做功能模块时,会把数据服务层的单测覆盖率当硬指标,弹窗和画面可以不测,但数据换算逻辑必须挂单测。
在真实的 AVEVA 开发里,数据服务层一般是自己写的,从 PI Server 或者 OPC UA 拿原始数据,转成界面能显示的工程单位、量程范围、报警限值,这中间的逻辑最容易在版本迭代里被改坏。配合测试驱动开发的套路,先写断言再写实现,后面做界面大改时会相当安心。
5. 界面开发避坑指南:环境、绑定与部署的常见问题
5.1 控件拖进去了,运行时却看不见
现象:在设计器里按钮、图表都摆好了,运行后画面空白,连报错都没有。
原因:第一优先级排查控件所在容器是否被添加到可视化树里。设计器里的控件有时被放在一个隐藏层或者未激活的画布上,设计器保存时没有把容器实例化。另一种常见原因是自定义控件缺少无参构造函数——宿主进程加载控件时必须调用默认构造,如果你的控件只写了带参数的构造函数,实例化失败会被静默吞掉。
解决:先在自定义控件里显式添加一个空构造函数,并在构造函数里写一行日志输出,运行时看日志确认控件是否被创建;然后检查设计器里控件父容器的Visible属性和所在页面是否处于激活状态。最有效的验证是新建一个干净面板,只放一个按钮,如果按钮能显示,问题就出在布局容器层级上,逐个排查就能定位。
5.2 编译通过,但运行时报无法连接到运行时服务
现象:IDE 里编译无错误,启动调试时弹连接失败,甚至直接提示找不到服务端点。
原因:AVEVA 运行时服务和开发工具跑在不同的权限上下文里。开发机一般用管理员账号,运行时进程却可能跑在低权限服务账号下,两边访问的 Galaxy 数据库配置不一致,IDE 里看得见工程,运行时服务却读不到同一个数据源。
解决:按教程第 2.2 节检查环境变量之外,还要确认两件事:开发账号要加入 AVEVA 的授权用户组;运行时服务的配置工具里重新指定 Galaxy 数据库连接。曾经有个项目因为开发机和服务器不在一个域,一直连不上,最后发现是运行时服务配置里还保留着旧的服务器名,改成 IP 就是一瞬间的事。建议动手前把服务器名、用户名、数据库连接串逐项核对一遍。
5.3 数据绑定写了,画面里的值却不动
现象:明明把数据源功能模块绑定到了文本框,运行后也有初始值,但实时数据不更新。
原因:教程第 7.2 节讲绑定提到一个容易忽略的细节——绑定路径和更新频率。先查绑定路径有没有写对,Temperature是数据点ID 还是字段名,大小写是否完全一致;再查数据源有没有打开自动更新通道,AVEVA 历史库的数据读取需要显式订阅点集,不是绑上就自动推。多数“不更新”其实是忘记配置订阅。
解决:按这条链路检查——数据源连接是绿灯?订阅的数据点有没有实时值?绑定表达式的Path是数据源暴露的属性名?更新模式是不是单向推送到界面?A 面查完再查 B 面,通常问题会出现在数据源侧而不是界面侧。还有个技巧:在界面上放一个原始值的调试文本框,先绑原始数据再绑转换后数据,能快速区分是取值问题还是单位换算问题。
5.4 自定义控件部署到生产机后,画面出现乱码或字体错位
现象:开发机上显示正常,部署到另一台操作站后,中文字体变成方块,控件位置整体偏移。
原因:开发机的 AVEVA 运行环境里装了对应的中文字体包和控件依赖库,生产机没有;同时生产机屏幕分辨率和缩放比例与开发机不同,像素坐标定位的控件就会整体跑偏。
解决:部署时把自定义控件依赖的字体一并放进安装包,或者部署后用脚本检查目标机字体是否缺失。涉及分辨率的部分回到第 3 章的内容,布局用网格和跨度而不是绝对像素,响应式模式下做一套通用缩放规则。这类问题在开发机上是玄学,在部署机上每台都不一样,项目收尾前做一台标准操作站镜像,以后新装机全部基于镜像来,是少走回头路的办法。
5.5 改配置之前要不要备份,我给你一个明确答案
要。教程第 2.1 节里写了“备份现有配置”,当时你可能觉得这是正确的废话,直到有次手滑把一组画面符号库替换错,又没存导出版本,恢复原样花了一个多星期。我的习惯是每次动界面工程之前,完整导出当前 Galaxy 配置和画面包,命名带日期,放在专门服务器上留存。界面定制的改动不像写代码有版本控制,AVEVA 的原生工程文件在团队协作时容易覆盖,备份就是唯一的后悔药。养成这个习惯后,再没出现过“改不回去只能重做”的局面。
6. 数据绑定与动态显示:把实时数据连到界面上
6.1 数据源连接:数据库和 OPC UA 各有各的接法
教程第 7.1 节列了两类数据源:关系数据库和 OPC 服务器。这两类接法思路完全不一样。
接数据库的常规流程是:在系统配置里新建连接字符串,服务器地址、库名、账号密码配齐;然后在数据模型层定义一个表结构映射,目的是把数据库字段翻译成界面能直接引用的字段名;最后把模型和库表做字段映射。这个过程中最容易出问题的环节是数据库权限——界面运行服务用的账号往往和开发账号不同,给的数据库权限不足,开发时测得好好的,一运行就掉线。
OPC UA 的接入逻辑则不一样。先配置 OPC UA 服务器地址和匿名或证书认证;然后订阅需要的节点;系统按订阅频率自动读取,界面绑定这些订阅数据点后会收到更新事件。这里面有两个参数直接影响体验:订阅周期和死区。订阅周期决定多少毫秒拿一次数据,死区决定变化多少才触发一次界面更新。对于温度这类慢变量,周期可以放到 1000 毫秒以上,死区设成量程的 0.5%;对于压力或者流量这类变化快的点位,周期要缩短到 200 毫秒以内,死区要设得小一些。很多界面刷新过频导致 CPU 占用高的案例,深挖下去都是把快慢变送器设成了同一组刷新参数。
| 数据源 | 接入方式 | 典型用途 | 关键参数 |
|---|---|---|---|
| 关系数据库 | JDBC/ODBC 连接 | 产量报表、批次数据 | 连接池大小、查询超时 |
| OPC UA | 客户端订阅节点 | 实时过程数据 | 订阅周期、死区、会话超时 |
6.2 Binding 到文本框和图表:XML 路径与数据刷新频率
教程第 7.2 节给了一段 XAML 风格的绑定语句:
<TextBox x:Name="txtTemperature" Text="{Binding Path=Temperature}" />它的意思是将TextBox的Text属性绑定到数据源的Temperature属性上,只要Temperature的值发生变化,框架就会自动更新文本框显示,不需要手写赋值代码。图表绑定同理:
<Chart x:Name="chartPressure" Series="{Binding Path=PressureSeries}" />这里背后的机制是属性通知——数据源必须实现INotifyPropertyChanged接口,在Temperature的set访问器里触发事件,界面才会收到更新。你的数据源类是普通 POCO 而不是实现了通知接口的类,绑定了也没用,画面永远停在初始值。头一回做绑定的人写代码发现没反应,十有八九是这个原因。
顺手提一下数据刷新频率的考虑。绑定本身不负责抓数据,它只负责把数据变化转发到界面。实际数据还是由前面配置的数据源订阅周期控制的,增加界面上显示的更新频率,先要把 OPC UA 的订阅周期调小,只改界面没有用。
6.3 从本机连到生产数据源:验证数据链路的三个操作
教程里的示例代码都用localhost连接本机,但实际项目几乎没有本机连本机的场景。最常见的是开发机连测试库、操作站连生产库。我从这份教程里总结出的“改完界面三步验证”可以分享给你们:
第一步,在开发机上用数据源工具的客户端单独连一次生产数据源,确认网络策略和证书是通的,把数据源本身的问题先排除掉。
第二步,在界面上加一个调试用文本框,绑一个最简单的已知数据点,看值能不能出现。能出现,说明绑定链路没问题;不能,回到第 5.3 节排查绑定更新链路。
第三步,把画面上所有绑定了数据源的控件集结起来,逐个盯几分钟——不只是看有没有值,还要看刷新是否平滑、有没有时序交叉、报警状态的变色是否及时。这一步是磨耐心的活,但比部署上线后让操作员替我们发现异常要体面得多。
说实话,AVEVA 这套平台界面定制的资料很多写得很浅,这份教程的价值在于把从环境到控件的完整链路都串起来了,而且每一步都能落到代码上。从那以后,我每次改 AVEVA 画面都强制走一遍备份、绑定链路验证、操作站镜像部署这条流程。新手照着教程搭完环境再把控件跑通一遍,会比只看不做扎实得多。希望帮到你。
本文还有配套的精品资源,点击获取