虚拟标签
概览
虚拟标签并非从传感器或 PLC 读取的标签,而是通过计算多个其他标签的值而创建的新标签。在现场,经常存在许多«虽然不直接测量但需要查看的值»,例如两路压力的差值(差压)、线路总功率之和或多个传感器的平均值。将其创建为虚拟标签后,该值将像普通标签一样被存储、绘制在图表上,并且可以设置报警。
一个虚拟标签由以下两部分组成:
| 项目 | 位置 | 功能 |
|---|---|---|
| 标签本身 | 连接修改界面 → 已连接标签列表 → [虚拟标签] | 注册标签 ID · 名称 · 数据类型 |
| 计算公式 | 标签设置表单 → 计算 选项卡 | 用于读取源标签并生成值的 EQL 语句 |
如果没有计算公式,虚拟标签将不会产生值(手动输入值的 虚拟点 除外)。
应用场景
| 用途 | 示例 | 计算公式核心 |
|---|---|---|
| 两个标签之差 | 差压 = 入口压力 $-$ 出口压力, 偏差 = 设定值 $-$ 实测值 | to_double(a.value) - to_double(b.value) |
| 总和 | 线路总功率 = 设备电力的总和 | to_double(a.value) + to_double(b.value) + to_double(c.value) |
| 平均值 | 多个传感器的平均温度 | (to_double(a.value) + to_double(b.value)) / 2 |
| 最大 · 最小 | 多个传感器中的最高温度 | CASE WHEN to_double(a.value) >= to_double(b.value) THEN a.value ELSE b.value END |
| 比例 | 原料投入量 대비 生产量 | to_double(a.value) / to_double(b.value) |
| 单个标签的时间平均 | 最近 10 秒平均值 | AVG(TO_DOUBLE(value)) 与时间窗口 —— 计算选项卡帮助中的示例 |
EQL 函数列表中没有专门用于从多个标签中选择最大值的函数(如 greatest)。最大 · 最小值的计算如上所述使用 CASE。
工作原理
在计算选项卡中输入的 EQL 在保存瞬间将作为语句发布至 CEP。当源标签进入新值时,该语句会生成一行结果,该行成为虚拟标签的值(数据点),进入与采集值相同的管线。因此,虚拟标签的值与普通标签完全一样被存储,可通过流 · 趋势界面和 API 读取,并能被报警或其他计算公式再次引用。
| 项目 | 虚拟标签中的处理方式 |
|---|---|
| 存储 | 通过与普通标签相同的路径存储。在趋势 · 流 · API 中使用相同的方法查看 |
| 数据类型 | 遵循注册时选择的数据类型 |
| 单位 | 注册对话框中没有该输入框,因此为空。在标签设置表单的标签属性选项卡中填写 |
| 更新时间点 | 源标签进入新值时更新。并非按固定周期运行的计算 |
| 更新频率 | 由语句决定。添加 OUTPUT LAST EVERY 1 SEC 后,每秒最多输出一次 |
| 质量 (quality) | 源标签的质量不会自动传递。语句中 quality 栏填写的数值将直接写入(示例中 192 = GOOD) |
| 源标签中断时 | 不会产生新值。不会用 «0» 填充 —— 在最后一个值之后为空 |
| 结果值为空时 | 该结果将被丢弃,不创建数据点 |
| 报警 | 与普通标签一样,可作为报警带 · EQL 报警的目标 |
a.quality · b.quality 是整数栏,可以在语句中直接读取。若要根据源质量不同而使用不同的 quality,必须将该表达式直接写入语句 —— Platform 不会代为计算。
创建步骤
1. 注册虚拟标签
虚拟标签隶属于一个连接。因此,注册按钮位于连接界面中。
- 在连接管理中打开要放置虚拟标签的连接,进入修改界面。 建议将其放置在源标签进入的连接中。
- 点击表单下方已连接标签列表面板标题的 [虚拟标签] 按钮(工具提示为 «添加虚拟标签»)。

| 数字 | 位置 | 功能 |
|---|---|---|
| ① | 面板顶部 | 已连接标签列表 — «当前连接中注册的标签». 仅在已保存连接的修改界面中填充 |
| ② | 面板顶部右侧 | [虚拟标签] — 打开下方的添加虚拟标签对话框 |
| ③ | 正文 | 该连接所属的标签列表 — 标签 ID · 标签名 · 数据类型 · 单位 · 说明 |
- 在添加虚拟标签对话框中输入以下内容并保存。

| 数字 | 输入栏 | 规则 |
|---|---|---|
| ① | 指南 | «注册虚拟标签。标签 ID 必须以 TAG_ 开头。选择数据类型后,输入虚拟点时将按该格式进行校验.» |
| ② | 标签 ID | 必填。以 TAG_ 开头,仅允许大写字母 · 数字 · _,长度 5~30 个字符。虚拟标签惯例以 TAG_V_ 命名 — ID 规则 |
| ③ | 标签名 | 必填。占位符为 «可解释的名称» |
| ④ | 数据类型 | String · Short · Integer · Long · Float · Double · Boolean · Date. 默认值为 String |
| ⑤ | 说明 | 必填。占位符为 «请填写此标签的用途» — 留空则无法保存 |
| ⑥ | 右下角 | [保存] |
String对话框打开时默认选中 String。如果是计算数值的虚拟标签,请将其改为 Double。由于报警带只能设置在数值型和布尔型标签上,若保持 String,之后将无法设置带报警。
已连接标签列表仅在已保存连接的修改界面中填充 (连接管理)。虚拟标签会同时保存该连接的 ID,因此在尚未保存的连接中注册将被拒绝。
删除连接后,隶属于该连接的标签(包括虚拟标签)将被一并删除,与其关联的报警设置和计算公式也将被解除。如果您将虚拟标签放置在与源标签不同的连接中,请务必记住这一点。
2. 输入计算公式

| 数字 | 位置 | 功能 |
|---|---|---|
| ① | EQL 计算 帮助 | «通过 EQL 自动为标签生成计算数据点.» 及示例语句 |
| ② | EQL | 计算公式编辑器。保存被拒绝时,原因将显示在该栏正下方的方框中 — 见下方 |
| ③ | 部署 → 应用状态 | 必须为激活状态才能部署 |
| ④ | 右下角 | [保存] — 仅保存此选项卡 |
计算公式语句必须遵守以下规则:
| 规则 | 原因 |
|---|---|
结果必须输出 timestamp · value · quality · error_code 四栏 | 四者中任何一栏缺失或 value 为空,该结果将被丢弃 |
源值需转换为 to_double(…) 进行计算 | 标签值 (value) 以字符串形式流动。不能直接进行加减运算 |
每个源标签在 Point(tag_id = '…').win:length(1) 中指定别名 (a, b …) 并列出 | 将每个标签的最新值一一配对计算 |
必须编写 SELECT 完整语句,而非单行表达式 | 保存时 CEP 会尝试编译该语句 |
若保存被拒绝
保存时系统会对语句进行编译尝试,若错误则不予保存 (HTTP 422)。原因将直接显示在界面上。
② EQL 栏正下方会出现红色指南方框 «无法读取 EQL»。此拒绝状态不会通过 Toast 弹出。
| 方框内容 | 说明 |
|---|---|
| 位置标签 | «第 N 行 第 M 列». 光标将移动至该位置,点击标签可快速跳转。编辑器内该位置也会出现标记 |
| 正文 | 编译器的语句(原因)及修复建议 |
| 查看引擎原文 | 折叠的引擎原始语句 |
若编译器无法指明位置,则仅显示语句而无位置标签。修改语句后标记将消失。
当 CEP 未启动而无法检查时,同样不予保存 —— 未经检查的语句禁止保存。此时非语句错误,编辑器内无显示,Toast 将提示 «无法连接至 CEP 引擎,未能验证 EQL.» (HTTP 503)。请在 CEP 启动后重新保存。 Statement · 报警设置 · 查询执行等其他 EQL 保存或检查环节,均采用相同形式(原因语句及行 · 列)进行拒绝(虚拟标签运行)。
整体语法请参考 EQL 与 CEP — EQL 语言。
3. 确认值是否输出
在 流界面 中选择虚拟标签,确认值是否流动。仅当源标签有值进入时,虚拟标签才会产生值。
若要无计算公式输入值 — 虚拟点
流界面的 [虚拟点] 按钮可打开一个对话框,用于手动向单个标签输入时间与值。时间采用 ISO 8601 格式 (2024-01-15T17:10:15.123Z)。在尚未编写计算公式时,可用作测试界面或报警的用途。
示例 — 过滤器差压
这是一个通过过滤器前后的两个压力标签创建差压的示例。以下标签 ID 仅为说明用途的示例。
| 标签 | ID (示例) | 备注 |
|---|---|---|
| 过滤器入口压力 | TAG_PT_FILTER_IN | 源 |
| 过滤器出口压力 | TAG_PT_FILTER_OUT | 源 |
| 过滤器差压 | TAG_V_FILTER_DP | 虚拟标签 · 数据类型 Double · 单位 bar |
计算选项卡的 EQL:
SELECT current_timestamp() AS timestamp,
to_double(a.value) - to_double(b.value) AS value,
192 AS quality,
0 AS error_code
FROM Point(tag_id = 'TAG_PT_FILTER_IN').win:length(1) a,
Point(tag_id = 'TAG_PT_FILTER_OUT').win:length(1) b
OUTPUT LAST EVERY 1 SEC
| 部分 | 含义 |
|---|---|
win:length(1) a, win:length(1) b | 将入口 · 出口各自的最新一个值进行配对 |
to_double(a.value) - to_double(b.value) | 差压 = 入口 $-$ 出口 |
192 AS quality | 将结果质量声明为 GOOD(源质量不会传递) |
OUTPUT LAST EVERY 1 SEC | 无论哪一方有值进入均重新计算,但每秒仅发送一次 |
采用相同模式,将 - 改为 + 则变为总和,改为 / 则变为比例。若源标签有三个或更多,则按相同方式续接 c, d …。
报警原则 «一设定 = 一标签»
报警设置无论是带报警还是 EQL 报警,均挂载在单个标签上。
| 报警类型 | 如何挂载在单个标签上 |
|---|---|
| 带报警 | 标签设置表单的报警带选项卡 — 为该标签自身的值设置阈值。每个标签限设一个 |
| EQL 报警 | 报警设置表单中的目标标签为必填项 — 报警将记录为该标签的报警 |
若要根据多个标签组合的条件设置报警,应先将该组合创建为虚拟标签,然后将报警挂载在虚拟标签上。 不要尝试在 EQL 报警内部读取两个标签并计算 «入口 $-$ 出口 $> 0.5$»,而应创建差压虚拟标签,并为其设置 «$> 0.5$»。这样组合后的值本身会被存储并可通过趋势图查看,且报警触发的具体数值将保留在该标签中。
若 EQL 报警语句读取了非目标标签的标签、混合了多个标签或缺少标签条件,保存将被拒绝(错误代码 alarm.eql.one_tag, HTTP 422)。
表单中的 [运行 EQL] 同样遵循与保存相同的规则进行检查,因此会直接拒绝。
由于此为无位置的规则违规,EQL 编辑器下方橙色方框将显示如下内容:
EQL 报警仅读取单个标签 —— 即报警的目标标签。拒绝读取多个标签、无标签条件或与其他标签进行 Join。请为每个标签单独设置报警,或将标签对比(差压 · 偏差)通过虚拟标签计算后再为其设置报警。
即使是已保存的报警在运行时产生了其他标签的行,判定时也会忽略非目标标签的行,并留下诊断 diagnostic.tag.alarm_foreign_tag_rows。此类报警请迁移至虚拟标签。
示例 — 差压超过 0.5 bar 持续 5 分钟
在上述 TAG_V_FILTER_DP 上设置 EQL 报警。
在 高级报警 界面中:
添加报警设置 → 目标标签 为 TAG_V_FILTER_DP, 条件 (EQL) 的 EQL 如下:
SELECT timestamp, tag_id, tag_name, value, quality, error_code,
CASE WHEN to_double(value) > 0.5 THEN 'HIGH' ELSE 'NORMAL' END AS band
FROM Point(tag_id = 'TAG_V_FILTER_DP').win:length(1)
| 部分 | 含义 |
|---|---|
CASE … END AS band | 每个值输出一个 band 栏。输出 'HIGH' 时报警开启,输出 'NORMAL' 时关闭 — 若缺少 band 栏或 'NORMAL' 则保存被拒绝 |
Point(tag_id = 'TAG_V_FILTER_DP') | 仅读取一个目标标签。组合两个压力值的工作已由虚拟标签完成 |
持续 5 分钟并非在语句中实现,而是在表单的 检测设置 (ISA-18.2) → 开启延迟 中输入 300000(ms) 来实现 —— 界面帮助显示 «条件必须持续此时间(ms)才触发报警。0 为关闭,最大 3,600,000 ms(1小时).»
- 减少重复推送通知,可通过报警设置表单的 重复报警抑制 → 抑制时间 (分) 进行调整。
- 保存前,请使用表单的 [运行 EQL] 进行检查。其检查规则与保存一致(单标签 ·
band栏 · 编译) — 报警设置表单。 - 若无需持续条件,只需在超过阈值时立即通知,则无需 EQL 报警 —— 直接在差压标签的报警带选项卡中输入阈值即可。
局限与注意
| 项目 | 内容 |
|---|---|
| 源标签数量 | 产品无固定上限。但由于每个源标签都会附加一个窗口,请像 win:length(1) 那样减小窗口范围 — 若时间窗口过大,配对组合将呈爆炸式增长 |
| 虚拟标签的虚拟标签 | 支持。计算结果像普通标签值一样再次输入,因此可被其他计算公式作为源读取 |
| 读取自身的计算 | 保存时不进行检查。 请勿创建自身读取或循环读取(A 读 B, B 读 A)的情况 |
| 计算公式长度 | 通过 V5 API 输入时上限为 4,000 字符 |
| CEP 后端 | 以上示例基于默认后端 (Aster CEP)。若使用其他后端安装,请参考 CEP — 后端 的表格 |
| 源质量 | 不会自动传播 — 工作原理 |
API 与 MCP
| 路径 | 虚拟标签中的处理方式 |
|---|---|
| V5 API — 注册 | POST /api/v5/tag — 与普通标签注册相同。opc_id 为必填,tag_id 命名为 TAG_V_… |
| V5 API — 计算公式 | PATCH /api/v5/tag/{tag_id}/calculation — calculation_eql 与 use_calculation(true/false). 保存后重新发布计算公式 |
| V5 API — 读取 | GET /api/v5/tag/{tag_id}/config 返回 calculation_eql · use_calculation |
| MCP | 无虚拟标签专用工具。MCP 工具通过标签 ID 读取值,因此虚拟标签也可像普通标签一样通过 list_latest_tag_values · get_tag_history 读取。无创建或更改计算公式的 MCP 工具 |
SDK 方法请参阅 标签服务。