4. AVEVA脚本语言基础
在AVEVA System Platform与InTouch的二次开发中,脚本是把静态画面变成动态逻辑的关键。平台里常见的脚本体系主要有两类:一类是InTouch时代的QuickScript(含QuickScript .NET),另一类是System Platform中基于对象模板的AVEVA Script(在IDE中通常以脚本编辑器形式出现,与Automation对象、图形符号绑定)。两者语法风格接近,但运行宿主、作用域和事件模型差异明显,理解这些差异是写出稳定脚本的前提。
一、两种脚本的定位与语法风格
QuickScript .NET运行在InTouch WindowMaker/WindowViewer中,宿主是窗口、控件或应用程序本身。它支持条件判断、循环、函数调用,并可通过.NET扩展访问System.Windows.Forms、System.Data等命名空间。AVEVA Script则运行在Galaxy对象(如Automation对象、图形模板)内部,脚本随对象实例化,天然具备“模板—实例”的继承关系。语法上两者都使用类似C的表达式,但AVEVA Script更强调通过Me、MyArea等关键字访问对象自身属性。
' QuickScript .NET 示例:按钮点击时写入标签
IF $System.TagExists("Reactor1_SP") THEN
$Reactor1_SP = 75.0;
LogMessage("SP set to " + Text($Reactor1_SP, "#0.0"));
ELSE
LogMessage("Tag not found");
ENDIF;
' AVEVA Script 示例:Automation对象脚本
Me.Setpoint = 75.0;
Me.AlarmLimitHigh = 80.0;
IF Me.PV > Me.AlarmLimitHigh THEN
Me.AlarmState = 1;
ENDIF;
可以看到,QuickScript .NET用$前缀引用InTouch标签,AVEVA Script用Me引用当前对象属性。混用两者是常见错误,例如在Automation对象脚本里写$TagName不会解析到InTouch标签,而应通过对象属性或引用路径访问。
二、变量作用域:局部、窗口、对象与全局
变量作用域决定了脚本能“看见”哪些数据,也决定了并发调用时是否互相干扰。QuickScript .NET中,Dim声明的变量默认是脚本局部变量,每次触发重新初始化;窗口级变量(Window Script中声明)在窗口打开期间保持;应用程序级变量(Application Script)在整个InTouch会话中有效。AVEVA Script中,变量通常绑定到对象属性,作用域随对象实例走,模板中定义的属性在实例中独立存储。
下面这张图展示了从事件触发到变量读写、再到结果输出的作用域与数据流关系,帮助区分局部变量、对象属性和全局标签在脚本执行中的位置。
三、事件驱动机制:什么时候执行脚本
脚本不是主动轮询,而是由事件触发。QuickScript .NET常见事件包括:按钮的OnClick、窗口的OnShow/OnHide、数据变化脚本(Data Change Script)、条件脚本(Condition Script)以及定时脚本(While/Scheduled)。AVEVA Script则绑定在对象属性变化、对象状态迁移、图形元素动画事件上。理解事件触发时机,才能避免“脚本没执行”或“执行了多次”的问题。
以InTouch数据变化脚本为例,当$Reactor1_PV变化超过死区(Deadband)时触发。若死区设为0,则每次微小波动都会触发,可能造成日志刷屏;若死区设为0.5,则只有变化量超过0.5时才执行。这是工程中必须显式设置的参数。
' 数据变化脚本:PV变化时判断高报警
' 触发条件:$Reactor1_PV 变化量 > 0.5
IF $Reactor1_PV > 80.0 THEN
$Reactor1_HiAlarm = 1;
LogMessage("High alarm ON, PV=" + Text($Reactor1_PV, "#0.0"));
ELSE
$Reactor1_HiAlarm = 0;
ENDIF;
AVEVA Script中,事件通常与对象状态机绑定。例如Automation对象从“Idle”进入“Running”时触发OnStart脚本,从“Running”进入“Stopped”时触发OnStop脚本。这类脚本适合做初始化、清理和状态同步。
四、常用内置函数与工程用法
两类脚本都提供了一批内置函数,覆盖字符串、数学、时间、标签访问和日志。下面列出最常用的一组,并说明典型用途。
| 函数 | 所属 | 用途 | 示例 |
|---|---|---|---|
| Text(值, 格式) | 两者通用 | 数值转字符串 | Text(75.3, "#0.0") → "75.3" |
| StringToValue(字符串) | QuickScript .NET | 字符串转数值 | StringToValue("75.3") → 75.3 |
| LogMessage(消息) | 两者通用 | 写诊断日志 | LogMessage("SP changed") |
| TagExists(标签名) | QuickScript .NET | 判断标签是否存在 | IF TagExists("Reactor1_SP") THEN |
| Me.SetAttribute(名, 值) | AVEVA Script | 设置对象属性 | Me.SetAttribute("SP", 75.0) |
| Now() / TimeCurrent() | 两者通用 | 获取当前时间 | LogMessage(Text(Now(), "yyyy-mm-dd hh:mm:ss")) |
| Abs(x)、Sqrt(x) | 两者通用 | 数学计算 | Abs(-3.2) → 3.2 |
五、一个可复用的脚本片段:设定值写入与越限检查
下面给出一个同时体现变量作用域、事件触发和内置函数使用的示例。场景:操作员在画面输入反应器设定值,点击“应用”按钮后,脚本检查输入是否在0~100之间,合法则写入标签并记录日志,非法则弹窗提示。
' 按钮 OnClick 脚本(QuickScript .NET)
DIM sInput AS STRING;
DIM nSP AS FLOAT;
sInput = $InputBox_Text; ' 读取输入框文本
nSP = StringToValue(sInput); ' 字符串转数值
IF nSP >= 0 AND nSP <= 100 THEN
$Reactor1_SP = nSP; ' 写入全局标签
LogMessage("SP applied: " + Text(nSP, "#0.0"));
ELSE
MessageBox("设定值必须在0~100之间,当前输入:" + sInput);
ENDIF;
这段脚本中,sInput和nSP是局部变量,只在本次点击事件中存在;$Reactor1_SP是全局标签,写入后其他画面和脚本都能读到;StringToValue和Text是内置函数,分别完成类型转换和格式化。若把这段逻辑放到AVEVA Script中,则改为通过Me.InputText读取输入、Me.Setpoint写入属性,并用Me.LogMessage记录。