产品定价 立即试用
专业版
文档 > 仪表盘 > SCADA > SCADA符号开发指南
入门
指南 安装 架构 API 常见问题
目录

SCADA 符号开发指南

3.8.0及以上版本

ThingsBoard中的SCADA symbol使用 SVG(Scalable Vector Graphics)制作, 其矢量特性便于在不同屏幕尺寸下无缝缩放。 我们的工程师扩展了SVG格式以支持symbol的交互性。 本指南将带您使用示例SVG文件创建自己的交互式SCADA symbol。

前置条件

要顺利跟随本指南,请确保已:

具备SVG.js经验有助于应对高级场景。

关键概念

我们常用以下定义:

  • 开发者 - 负责定义SCADA symbol的人员;
  • 最终用户 - 将SCADA symbol集成到dashboard的人员。

在ThingsBoard中创建SCADA symbol涉及SVG文件及以下概念:

  • Tags:SVG文件中为形状分配的自定义标签。Tag用于指定SVG元素的渲染函数和 onClick 操作;

  • Behavior:描述SCADA symbol如何从平台接收数据,以及其在device或dashboard上触发的操作;

  • Properties:供最终用户使用的配置项。这些property用于自定义部件外观;

  • 状态渲染函数:负责渲染SVG元素的JavaScript函数。

  • 点击动作:定义onClick处理逻辑的JavaScript函数。

  • ScadaSymbolContext:包含tag、behavior项、property及辅助API函数引用的JavaScript对象。

示例SVG文件

假设我们要将下方SVG文件转换为交互式SCADA symbol:

FAN SVG

图:包含风扇、文本标签和两个按钮的静态SVG图像。

该SVG图像为静态,包含风扇、文本标签和两个按钮。 目标是将其实时反映风扇状态并更新的交互式部件。

任务定义:

  • 按钮
    • 向目标device发送命令,更新风扇状态;
    • 按钮文本和颜色需可由最终用户配置。
  • 风扇外观
    • 引擎为 “On” 时风扇旋转,”Off” 时停止;
    • “On” 与 “Off” 状态的颜色可分别配置。
  • 文本标签
    • 显示风扇转速。引擎为 “Off” 时隐藏该标签;
    • 标签可由最终用户自定义,包括显示/隐藏、字体、颜色和单位。

下面我们按步骤实现上述功能。

第1步:上传SVG文件

  • 右键点击下方SVG文件,选择“图片另存为(Save image as)”将其保存到电脑:

FAN SVG

  • 进入 “SCADA symbols” 的 “Resources” 页面,点击 “Upload SCADA symbol” 按钮;
  • fan.svg 文件拖入相应区域,或从电脑文件夹上传,重命名为 “Fan”,点击 “Upload”。

第2步:了解SCADA编辑器

上传SCADA symbol后,将进入SCADA symbol编辑器。编辑器分为两栏:

  • 左侧面板 显示已上传的SVG文件;
  • 右侧面板 包含 “General”、”Tags”、”Behavior”、”Properties” 等标签。

SCADA编辑器操作

  • Create Widget - 该按钮可根据SCADA symbol快速创建部件。SCADA symbol的重大变更会自动反映到部件库,但title、description、search tags等信息在创建部件时会被复制,后续不会自动更新。

  • ApplyDecline - 用于保存或放弃对symbol的更改。

  • Preview - 从最终用户视角检查部件行为。左侧渲染SVG,右侧显示部件配置页。使用 Back 按钮退出预览模式。

作为简单练习,填写描述和搜索标签,然后点击 “Apply”。

部件尺寸与宽高比

注意部件以列和行表示的尺寸,这会影响SCADA layout如何放置部件。 该设置影响部件的宽高比,理想情况下应与SVG的宽高比一致。 不建议使用17:43等复杂宽高比。推荐示例有1:1、1:2、2:1等。

第3步:标签

Tag是赋予SVG文件中形状的自定义标签。 用于为SVG元素指定render函数和 onClick 操作。 可将同一tag分配给多个SVG元素,以简化相似组件的交互与功能。

通过编辑器定义标签

要定义tag,在编辑器左侧选中对应SVG元素,点击 “+Add tag” 按钮,然后命名tag。建议使用 camelCase 命名,便于在render函数中引用。

本例中需为SVG内几乎所有元素添加tag以实现完整交互。需定义的tag如下:

  • onButton - 用于 “group” 元素的tag,用来定义 “On” 按钮的 onClick 操作;
  • onButtonBackground - 用于 “rect” 元素的tag,用来控制 “On” 按钮的背景色;
  • onButtonText - 用于 “text” 元素的tag,用来定义 “On” 按钮的文本显示;
  • offButton - 用于 “group” 元素的tag,用来定义 “Off” 按钮的 onClick 操作;
  • offButtonBackground - 用于 “rect” 元素的tag,用来控制 “Off” 按钮的背景色;
  • offButtonText - 用于 “text” 元素的tag,用来定义 “Off” 按钮的文本显示;
  • rotationSpeedText - 用于 “text” 元素的tag,用来显示转速值;
  • fan - 用于 “path” 元素的tag,用来实现风扇旋转动画。

“Tags” 标签中的表格可快速访问每个tag,并定义状态渲染函数和 onClick 操作。

通过XML定义标签

对简单SCADA symbol,UI编辑器即可;复杂SVG结构可能需要XML方式。 对于被渐变或复杂形状遮挡的元素,可切换到XML编辑器模式。 该选项位于编辑器左侧面板右上角。 可在XML结构中直接使用 tb:tag 语法定义tag。

为 “On” 按钮元素添加tag:

  • 进入 “XML” 编辑器模式,将以下XML替换为:
1
2
3
4
5
6
<g transform="matrix(1.61104 0 0 1.60957 -72.338 -20.652)">
  <rect x="54.702" y="60.372" width="14.263" height="7.426" rx="1.5" fill="#12ed19" stroke="#000"/>
  <text x="61.856" y="64.491" dominant-baseline="middle" fill="#000000" font-family="Roboto" font-size="4.446" stroke-width=".741" text-anchor="middle" xml:space="preserve">
    <tspan stroke-width=".741">On</tspan>
  </text>
</g>

替换为以下代码:

1
2
3
4
5
6
<g tb:tag="onButton" transform="matrix(1.61104 0 0 1.60957 -72.338 -20.652)">
  <rect tb:tag="onButtonBackground" x="54.702" y="60.372" width="14.263" height="7.426" rx="1.5" fill="#12ed19" stroke="#000"/>
  <text tb:tag="onButtonText" x="61.856" y="64.491" dominant-baseline="middle" fill="#000000" font-family="Roboto" font-size="4.446" stroke-width=".741" text-anchor="middle" xml:space="preserve">
    <tspan stroke-width=".741">On</tspan>
  </text>
</g>
  • 返回 “SVG” 编辑器模式。您将看到tag已添加到 “On” 按钮元素。


以下XML代码将为本示例添加所有必要的tag。

  • 复制该XML代码:
1
2
3
4
5
6
7
8
9
<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="100" height="100" version="1.1" viewBox="0 0 100 100">
<rect width="100" height="100" rx="0" fill="none" stroke="#ccc" stroke-width="2"></rect><path tb:tag="fan" d="M66.868 25.074a1.752 1.752 0 0 0-.645-1.072c-2.852-2.356-6.806-2.198-11.864.476-.33-.33-.688-.61-1.088-.85 3.486-3.127 6.663-4.44 9.533-3.939.846.148 1.431-.821.907-1.502a16.52 16.52 0 0 0-4.079-3.787 1.753 1.753 0 0 0-1.213-.302c-3.683.35-6.368 3.258-8.054 8.725-.467 0-.917.056-1.37.169.254-4.677 1.573-7.852 3.956-9.526.703-.494.431-1.593-.42-1.704a16.519 16.519 0 0 0-5.563.206 1.752 1.752 0 0 0-1.071.645c-2.357 2.852-2.199 6.806.475 11.864-.33.33-.61.688-.85 1.088-3.127-3.486-4.44-6.664-3.939-9.533.148-.846-.821-1.432-1.501-.907a16.517 16.517 0 0 0-3.788 4.079 1.753 1.753 0 0 0-.302 1.213c.35 3.683 3.259 6.368 8.726 8.054 0 .467.055.916.168 1.37-4.676-.254-7.851-1.573-9.526-3.956-.493-.703-1.593-.431-1.704.42a16.519 16.519 0 0 0 .207 5.563c.093.453.288.777.644 1.071 2.852 2.357 6.807 2.199 11.865-.475.33.33.687.61 1.087.85-3.486 3.127-6.663 4.44-9.532 3.939-.846-.148-1.432.821-.908 1.501a16.52 16.52 0 0 0 4.08 3.788c.386.255.752.346 1.213.302 3.683-.35 6.367-3.259 8.053-8.725a5.58 5.58 0 0 0 1.37-.17c-.254 4.677-1.572 7.853-3.956 9.527-.702.494-.431 1.593.42 1.704 1.89.245 3.696.178 5.563-.207a1.752 1.752 0 0 0 1.072-.644c2.356-2.852 2.198-6.806-.476-11.865.33-.33.61-.687.85-1.087 3.127 3.486 4.44 6.663 3.939 9.533-.148.845.821 1.431 1.501.907a16.518 16.518 0 0 0 3.788-4.08c.255-.386.346-.752.302-1.213-.35-3.683-3.259-6.367-8.725-8.053 0-.467-.056-.917-.169-1.37 4.676.254 7.852 1.572 9.526 3.956.494.702 1.593.431 1.704-.42.245-1.89.178-3.696-.206-5.563zm-16.503 8.103a4.706 4.706 0 1 1 0-9.412 4.706 4.706 0 0 1 0 9.412z" fill="#7d081e"></path><text tb:tag="rotationSpeedText" x="49.434" y="59.465" dominant-baseline="middle" fill="#000000" text-anchor="middle" xml:space="preserve"><tspan>30 RPM</tspan></text><g tb:tag="onButton" transform="matrix(1.61104 0 0 1.60957 -72.338 -20.652)">
    <rect tb:tag="onButtonBackground" x="54.702" y="60.372" width="14.263" height="7.426" rx="1.5" fill="#12ed19" stroke="#000"></rect>
    <text tb:tag="onButtonText" x="61.856" y="64.491" dominant-baseline="middle" fill="#000000" font-family="Roboto" font-size="4.446" stroke-width=".741" text-anchor="middle" xml:space="preserve"><tspan stroke-width=".741">On</tspan></text>
  </g><g tb:tag="offButton" transform="matrix(1.61253 0 0 1.61566 -58.441 -20.942)">
    <rect tb:tag="offButtonBackground" x="74.367" y="60.311" width="14.263" height="7.426" rx="1.5" fill="#ed121f" stroke="#000"></rect>
    <text tb:tag="offButtonText" x="81.366" y="64.518" dominant-baseline="middle" fill="#000000" font-family="Roboto" font-size="4.446" stroke-width=".741" text-anchor="middle" xml:space="preserve"><tspan stroke-width=".741">Off</tspan></text>
  </g>
</svg>
  • 进入 “XML” 编辑器模式;
  • 在对应窗口粘贴复制的代码;
  • 返回 “SVG” 编辑器模式。您可看到已定义的tag。随后应用更改。

标签操作

您可更新tag、添加状态渲染函数、分配点击动作,或使用相应tag图标删除tag。

更新tag

  • Hover over the tag and click the "Update tag" icon;
  • Change the tag name and click "Apply".

Tag设置

  • 将鼠标悬停在tag上,然后点击 “Tag settings” 图标;
  • 在弹出菜单中,可为每个tag分配两类函数:”状态渲染函数” 和 “点击动作”。我们会在 “Tag configurations” 章节中详细说明。

删除tag

  • Hover over the tag and click the "Remove tag" icon;
  • Confirm deleting the tag in the dialog box.

第4步:behavior项

behavior项使最终用户能够配置部件与平台之间的交互。 定义完成后,这些项会出现在部件的最终用户配置中,形成Behavior面板。 例如,您可以设置决定风扇状态(”On”/”Off”)的数据来源,并指定点击 “On” 和 “Off” 按钮时触发的动作。

下方图库包含两张图片:一张展示SCADA开发者配置的behavior项列表,另一张展示这些项在最终用户部件配置中的对应元素。

添加behavior

下面介绍如何配置behavior项。每个项都包含以下通用字段:

  • Id - 在 ScadaSymbolContext 中引用该项的标识符;
  • Name - 用于生成最终用户配置元素的标签;
  • Hint - 显示在最终用户配置元素中的提示信息,用于辅助使用;
  • Group title - 用于在 “Behavior” 配置面板中组织配置元素的分组标题;
  • Type - 字段类型可为 “Value”、”Action” 或 “Widget action”,下文将分别说明;
  • Default settings - 提供给最终用户的默认预设配置。

要为SCADA symbol添加新的behavior项,请执行以下操作:

  • Navigate to the "Behavior" tab and click the "Add behavior" button;
  • Fill in the required fields and click "Add".

“Name”、”Hint”、”Group title” 等字段支持通过 i18n 标签实现国际化,例如:{i18n:scada.fan.turn-on}。有关自定义翻译配置,请参见 Localization

behavior类型

behavior参数列表由所选SCADA symbol决定,并完全由symbol作者控制。behavior参数共有三种类型:”Value”、”Action”和”Widget action”。

  • Value” 参数通常控制symbol的可视表现,并会基于接收值随时间变化;
  • Action” 参数定义在特定事件发生时对目标实体执行的动作;
  • Widget action” 参数定义用户点击SCADA symbol组件时触发的动作。

Value类型

Value类型behavior项会将平台数据拉取到 ScadaSymbolContext 中,可视作变量。 这些变量通常会随目标device的属性或时序数据变化,并用于定义各tag的状态渲染函数。

用于获取值的动作共有六种:

  • Do nothing 动作类型使用用户定义的常量值。
  • Execute RPC 动作类型向目标device发送命令以获取值。该值会在部件创建时解析一次。
  • Get attribute 动作类型订阅目标实体的属性值,当属性变化时更新部件。
  • Get time series 动作类型订阅目标实体的时序字段,收到新数据时更新部件。
  • Get alarm status 动作类型订阅目标实体的告警状态字段,并根据告警类型更新部件状态。
  • Get dashboard state 动作类型使用当前dashboard状态名称,适用于与device状态无关的特定场景。

Action类型

Action类型behavior项用于定义特定事件发生时对目标device执行的动作,通常在为tag定义点击动作时通过 ScadaSymbolContext 触发。

平台支持三类与目标实体交互的动作:

  • Execute RPC 向目标device发送命令。您可指定命令的方法和参数。
  • Set attribute 动作类型下发设置目标device属性的命令,您可定义scope、key和value。
  • Add time series 动作类型向目标device新增一条时序值。您可定义新时序数据的key和value。

Widget action类型

Widget action类型behavior项与 Action 类型behavior项类似,但用于触发与当前dashboard部件相关的动作,而不是针对目标device。 可用的widget动作详见 Widget Actions文档

值类型

“Value” 和 “Action” 类型behavior项支持 “String”、”Integer”、”Double”、”Boolean”、”JSON” 等多种值类型,每种类型都有对应的配置参数。

为本SCADA symbol添加新的Value类型behavior项

下面为本SCADA symbol创建新的Value类型behavior项:

1.使用 “fanOn” 共享属性:

  • Id: fanOn
  • Name: 开/关状态
  • Type: Value
  • Value type: Boolean(true 表示风扇开启,false 表示风扇关闭)
  • True label: On
  • False label: Off
  • State label: On
  • Default settings:
    • Action: Get attribute
    • Attribute scope: Shared
    • Attribute key: fanOn

2.订阅目标device的时序key “fanSpeed“:

  • Id: fanSpeed
  • Name: Fan rotation Speed
  • Hint: 单位为RPM
  • Type: Value
  • Value type: Double(数值单位为RPM)
  • Default settings:
    • Action: Get time series
    • Time series key: fanSpeed


下面为用户与 “On”、”Off” 按钮的交互配置新的Action类型behavior项:

1.配置点击 “On” 按钮时的动作:将共享作用域属性 “fanOn” 设置为 “True“:

  • Id: onBtnClick
  • Name: 点击On按钮
  • Type: Action
  • Value type: Boolean
  • Default settings:
    • Action: Set attribute
    • Attribute scope: Shared
    • Attribute key: fanOn
    • Value: True

2.配置点击 “Off” 按钮时的动作:将共享作用域属性 “fanOn” 设置为 “False“:

  • Id: offBtnClick
  • Name: 点击Off按钮
  • Type: Action
  • Value type: Boolean
  • Default settings:
    • Action: Set attribute
    • Attribute scope: Shared
    • Attribute key: fanOn
    • Value: False


配置 “onFanClick” 点击动作为在单独浏览器标签页中打开ThingsBoard平台网页:

  • Id: onFanClick
  • Name: 点击风扇
  • Type: Widget action
  • Default settings:
    • Action: Open URL
    • URL: https://thingsboard.io/
    • Attribute key: fanOn
    • 启用在单独浏览器标签页打开网页

第5步:属性(Properties)

Properties是允许最终用户自定义部件外观的配置参数。 包括标签、字体、颜色、单位等设置。 定义完成后,这些property可在部件最终用户配置的 “Appearance” 标签页中使用。

下方图库包含两张图片:一张展示SCADA开发者配置的属性列表,另一张展示这些属性在最终用户部件配置中的对应元素。

下面介绍如何配置properties。每个property包含以下通用字段:

  • Id - 在 ScadaSymbolContext 中引用该property的标识符;
  • Name - 用于生成最终用户配置元素的标签。多个配置属性使用相同名称时会分组在同一行;
  • Type - property类型可为 TextNumberSwitchColorColor settingsFontUnits,下文将详细说明;
  • Default value - 提供给最终用户的默认预设值;
  • Value required - 要求用户必须输入该property值的开关;
  • Advanced UI settings - 包含多项配置,用于帮助开发者细化参数配置表单。

要为SCADA symbol添加新的property,请执行以下操作:

  • Navigate to the "Property" tab and click the "Add property" button;
  • Fill in the required fields and click "Add".

该结构清晰展示了property的定义与管理流程,便于最终用户和开发者理解与使用。

为本SCADA symbol添加新的property

下面配置 “On” 按钮的属性:

1.”On” 按钮标签:

  • Id: onBtnLabel
  • Name: On button(用于将与 “On” 按钮相关的属性分组到同一行
  • Type: Text
  • Default value: On
  • Advanced UI settings:
    • Property field classes: medium-width

2.”On” 按钮启用状态颜色:

  • Id: onBtnColor
  • Name: On button
  • Type: Color
  • Default value: #1C943E(绿色)

3.”On” 按钮禁用状态颜色:

  • Id: onBtnDisabledColor
  • Name: On button
  • Type: Color
  • Default value: #696969(灰色)
  • Advanced UI settings:
    • Sub label: Disabled


下面配置 “Off” 按钮的属性:

1.”Off” 按钮标签:

  • Id: offBtnLabel
  • Name: Off button
  • Type: Text
  • Default value: Off
  • Advanced UI settings:
    • Property field classes: medium-width

2.”Off” 按钮启用状态颜色:

  • Id: offBtnColor
  • Name: Off button
  • Type: Color
  • Default value: #D12730 (red)
  • Advanced UI settings:
    • Sub label: Enabled

3.”Off” 按钮禁用状态颜色:

  • Id: offBtnDisabledColor
  • Name: Off button
  • Type: Color
  • Default value: #696969(灰色)
  • Advanced UI settings:
    • Sub label: Disabled


下面配置风扇外观属性:

1.风扇 “On” 状态颜色:

  • Id: fanOnColor
  • Name: Fan colors(用于将与风扇相关的属性分组到同一行
  • Type: Color
  • Default value: #1C943E(绿色)
  • Advanced UI settings:
    • Sub label: On

2.风扇 “Off” 状态颜色:

  • Id: fanOffColor
  • Name: Fan colors(用于将与风扇相关的属性分组到同一行
  • Type: Color
  • Default value: #D12730 (red)
  • Advanced UI settings:
  • Sub label: Off
  • Property row classes: column


下面配置转速值显示属性:

1.显示/隐藏转速值开关:

  • Id: showRotationSpeed
  • Name: Rotation speed
  • Type: Switch
  • Default value: True

2.单位选择器:

  • Id: rotationSpeedUnit
  • Name: Rotation speed
  • Type: Units
  • Default value: RPM
  • Advanced UI settings:
    • Sub label: Unit
    • Disable on property: showRotationSpeed

3.字体选择器:

  • Id: rotationSpeedFont
  • Name: Rotation speed
  • Type: Font
  • Default value: Roboto Normal 12px
  • Advanced UI settings:
    • Disable on property: showRotationSpeed

4.标签颜色:

  • Id: rotationSpeedColor
  • Name: Rotation speed
  • Type: Color
  • Default value: #000000(黑色)
  • Advanced UI settings:
    • Disable on property: showRotationSpeed


配置完成后的属性列表应如下所示:

第6步:Tag函数

每个tag可分配两类函数:状态渲染函数点击动作。 下面先回顾函数签名,再为每个tag定义函数,并从简单示例逐步过渡到更复杂示例。

状态渲染函数

该JS函数负责通过 SVG.js API修改SVG元素,并接收两个参数:

您还会在 “General” 标签中看到全局状态渲染函数。 该函数为可选项,适用于希望在同一处统一定义所有tag渲染逻辑的场景。

点击动作

该JS函数用于定义点击处理逻辑,并接收三个参数:

  • ctxScadaSymbolContext 的实例;
  • elementSVG.js 元素;
  • event 是点击事件,后续版本可能扩展为其他事件;

Tag配置

onButtonText tag

我们先为 “On” 按钮文本定义一个简单的状态渲染函数。 只需将原始SVG中硬编码文本替换为最终用户通过 onBtnLabel property配置的文本:

  • 进入 “onButtonText” tag的 “Tag settings”,点击 “State rendering function” 的 “+ Add” 按钮;
  • 复制以下函数:
1
ctx.api.text(element, ctx.properties.onBtnLabel);
  • 将复制的函数粘贴到对应窗口,然后点击 “Apply”。

要点:

- ctx.api 用于访问 text 函数并更新元素文本;

- ctx.properties 用于获取 onBtnLabel property的值。

现在可点击 “Preview” 并修改对应property。点击 “Apply” 后,即可看到 “On” 按钮标签已变化。

offButtonText tag

onButtonText

  • 进入 “offButtonText” tag的 “Tag settings”,点击 “State rendering function” 的 “+ Add” 按钮;
  • 复制以下函数;
1
ctx.api.text(element, ctx.properties.offBtnLabel);
  • 将复制的函数粘贴到对应窗口,然后点击 “Apply”。

要点:

- ctx.api 用于访问 text 函数并更新元素文本;

- ctx.properties 用于获取 offBtnLabel property的值。

onButtonBackground tag

下面根据 “fanOn” behavior项的值来切换 “On” 按钮背景色:

  • 进入 “onButtonBackground” tag的 “Tag settings”,点击 “State rendering function” 的 “+ Add” 按钮;
  • 复制以下函数:
1
2
3
4
5
if(ctx.values.fanOn){
  element.attr({fill: ctx.properties.onBtnDisabledColor});
} else {
  element.attr({fill: ctx.properties.onBtnColor});
}
  • 将复制的函数粘贴到对应窗口,然后点击 “Apply”。

要点:

- ctx.values 用于获取 fanOn behavior项的值;

- element.attr({fill: color}) 用于更新元素的 fill 属性;

- ctx.properties 用于获取 onBtnColoronBtnDisabledColor 两个颜色property的值。

现在可点击 “Preview” 并修改对应颜色property。点击 “Apply” 后,可看到 “On” 按钮背景色已变化。

offButtonBackground tag

offButtonBackground 类似:

  • 进入 “offButtonBackground” tag的 “Tag settings”,点击 “State rendering function” 的 “+ Add” 按钮;
  • 复制以下函数:
1
2
3
4
5
if(ctx.values.fanOn){
  element.attr({fill: ctx.properties.offBtnColor});
} else {
  element.attr({fill: ctx.properties.offBtnDisabledColor});
}
  • 将复制的函数粘贴到对应窗口,然后点击 “Apply”。

要点:

- ctx.values 用于获取 fanOn behavior项的值;

- element.attr({fill: color}) 用于更新元素的 fill 属性;

- ctx.properties 用于获取 offBtnColoroffBtnDisabledColor 两个颜色property的值。

onButton tag

下面使用以下状态渲染函数,根据风扇状态启用或禁用 “On” 按钮:

  • 进入 “onButton” tag的 “Tag settings”,点击 “State rendering function” 的 “+ Add” 按钮;
  • 复制以下函数:
1
2
3
4
5
if(!ctx.values.fanOn){
    ctx.api.enable(element);
} else {
    ctx.api.disable(element);
}
  • 将复制的函数粘贴到对应窗口,然后点击 “Apply”。

要点:

- ctx.values 用于获取 fanOn behavior项的值;

- 若风扇已开启,ctx.api.disable 会禁用用户交互(包括onClick处理);

- 若风扇已关闭,ctx.api.enable 会启用用户交互(包括onClick处理)。


下面定义该按钮的点击动作:

  • 进入 “onButton” tag的 “Tag settings”,点击 “点击动作” 的 “+ Add” 按钮;
  • 复制以下函数:
1
2
3
4
5
6
7
8
9
ctx.api.disable(element);
ctx.api.callAction(event, 'onBtnClick', undefined, {
  next: () => {
     ctx.api.setValue('fanOn', true);
  },
  error: () => {
     ctx.api.enable(element);
  }  
});
  • 将复制的函数粘贴到对应窗口,然后点击 “Apply”。

要点:

- ctx.api.disable 会在收到onClick事件后立即禁用按钮,防止重复触发;

- ctx.api.callAction 会触发 onBtnClick behavior项中定义的动作;

- callAction 接收event、actionId、可选参数以及用于处理结果的Observer实例;

- 动作执行成功后,next 回调会将 fanOn 设置为 true

- 若动作执行失败,ctx.api.enable 会重新启用按钮。

offButton tag

offButton 类似,状态渲染函数如下:

  • 进入 “offButton” tag的 “Tag settings”,点击 “State rendering function” 的 “+ Add” 按钮;
  • 复制以下函数:
1
2
3
4
5
if(ctx.values.fanOn){
  ctx.api.enable(element);
} else {
  ctx.api.disable(element);
}
  • 将复制的函数粘贴到对应窗口,然后点击 “Apply”。

要点:

- ctx.values 用于获取 fanOn behavior项的值;

- 若风扇已关闭,ctx.api.disable 会禁用用户交互(包括onClick处理);

- 若风扇已开启,ctx.api.enable 会启用用户交互(包括onClick处理)。


下面定义该按钮的点击动作:

  • 进入 “offButton” tag的 “Tag settings”,点击 “点击动作” 的 “+ Add” 按钮;
  • 复制以下函数:
1
2
3
4
5
6
7
8
9
ctx.api.disable(element);
ctx.api.callAction(event, 'offBtnClick', undefined, {
  next: () => {
     ctx.api.setValue('fanOn', false);
  },
  error: () => {
     ctx.api.enable(element);
  }  
});
  • 将复制的函数粘贴到对应窗口,然后点击 “Apply”。

要点:

- ctx.api.disable 会在收到onClick事件后立即禁用按钮,防止重复触发;

- ctx.api.callAction 会触发 offBtnClick behavior项中定义的动作;

- callAction 接收event、actionId、可选参数以及用于处理结果的Observer实例;

- 动作执行成功后,next 回调会将 fanOn 设置为 false

- 若动作执行失败,ctx.api.enable 会重新启用按钮。

rotationSpeedText tag

下面使用 showRotationSpeedrotationSpeedFontrotationSpeedColorrotationSpeedUnit 这些property来优化文本标签显示:

  • 进入 “rotationSpeedText” tag的 “Tag settings”,点击 “State rendering function” 的 “+ Add” 按钮;
  • 复制以下函数:
1
2
3
4
5
6
7
8
9
10
11
12
var show = ctx.properties.showRotationSpeed && ctx.values.fanOn;
if (show) {
  var speed = ctx.values.fanSpeed ? ctx.values.fanSpeed : 60;
  var font = ctx.properties.rotationSpeedFont;
  var color = ctx.properties.rotationSpeedColor;
  var text = ctx.api.formatValue(speed, 0, ctx.properties.rotationSpeedUnit);
  ctx.api.text(element, text);
  ctx.api.font(element, font, color);
  element.show();
} else {
  element.hide();
}
  • 将复制的函数粘贴到对应窗口,然后点击 “Apply”。

要点:

- 第1行:show 变量同时由 showRotationSpeed property和 fanOn behavior项决定;

- 第3行:speed 变量优先使用 fanSpeed behavior项,若无值则默认 60(主要用于预览模式);

- 第6行:文本值由 speed 与指定的 rotationSpeedUnit property共同格式化;

- 第7、8行:设置文本内容及其样式(字体与颜色);

- 第9、11行:依据 show 变量控制文本元素显示或隐藏。

fan tag

下面使用一个稍复杂的函数来旋转 “fan” tag:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var on = ctx.values.fanOn;
var speed = ctx.values.fanSpeed ? ctx.values.fanSpeed /60 : 1;
var hasAnimation = element.remember('hasAnimation');

if (on) {
    element.attr({fill: ctx.properties.fanOnColor});
    if (!hasAnimation) {
        element.remember('hasAnimation', true);
        element.animate(1000).ease('-').rotate(360).loop();
    } else {
        element.timeline().play();
    }
    element.timeline().speed(speed);
} else {
    element.attr({fill: ctx.properties.fanOffColor});
    if (hasAnimation) {
        element.timeline().pause();
    }
}

该函数本身不复杂,但需要具备 SVG.js 的基础知识。要点如下:

- 第3行:使用 SVG.jselement.remember getter获取动画状态;

- 第9行:使用 SVG.jselement.remember setter设置动画状态。这样可避免每次调用渲染函数都重复初始化动画;

- 第11行:使用 SVG.jselement.timeline.speed 设置动画速度(由RPM换算为RPS);

- 第14行:使用 SVG.jselement.timeline.pause 在风扇关闭时暂停动画;


SVG.js 动画功能丰富,但会对浏览器主线程带来一定性能开销。这里给出一个基于CSS动画的替代方案:

  • 进入 “fan” tag的 “Tag settings”,点击 “State rendering function” 的 “+ Add” 按钮;
  • 复制以下函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var on = ctx.values.fanOn;
var speed = ctx.values.fanSpeed ? ctx.values.fanSpeed / 60 : 1;
var animation = ctx.api.cssAnimation(element);

if (on) {
    element.attr({fill: ctx.properties.fanOnColor});
    if (!animation) {
        animation = ctx.api.cssAnimate(element, 2000)
                                      .rotate(360).loop().speed(speed);
    } else {
        animation.speed(speed).play();
    }
} else {
    element.attr({fill: ctx.properties.fanOffColor});
    if (animation) {
        animation.pause();
    }
}
  • 将复制的函数粘贴到对应窗口,然后点击 “Apply”。

要点:

  • 在多数场景下,CSS动画更流畅且资源占用更低;
  • 第3行:使用 ctx.api.cssAnimation 获取当前 ScadaSymbolAnimation 对象实例;
  • 第8行:使用 ctx.api.cssAnimate 创建新的 ScadaSymbolAnimation 对象实例,提供与SVG.js Runner 类似的控制能力;
  • 第11行:使用 animation.speed(speed).play() 设置动画速度并开始播放;
  • 第16行:使用 animation.pause() 暂停动画;


下面定义该按钮的点击动作:

  • 进入 “fan” tag的 “Tag settings”,点击 “点击动作” 的 “+ Add” 按钮;
  • 复制以下函数:
1
2
3
4
5
6
7
8
9
ctx.api.disable(element);
ctx.api.callAction(event, 'onFanClick', undefined, {
  next: () => {
     ctx.api.enable(element);
  },
  error: () => {
     ctx.api.enable(element);
  }  
});
  • 将复制的函数粘贴到对应窗口,然后点击 “Apply”。

最佳实践

避免手动设置behavior值(如 ctx.api.setValue('fanOn', true) 示例)。该写法用于简化预览模式调试,但由于命令下发或处理可能失败,未必能反映device的真实状态。

设备交互推荐模式:

  1. RPC to Device:当预期命令需立即生效且确认device在线时,使用如 setFanState 这类RPC短时命令。
  2. Shared Attribute:设置共享属性(如 targetFanState)来表达期望状态,适用于可能离线的device。这样device上线后仍能最终接收并应用更新。
  3. Client Attributes or Time-Series Data:将device上报数据(如 fanState)作为behavior项取值来源,确保SCADA symbol反映的是设备真实响应,而非仅仅反映命令是否已发送。

全局状态渲染函数

除了分别配置每个tag的渲染函数外,也可以集中在一个地方统一配置。 但在全局函数中,您操作的是 svg,而不是单个tag的 element。 可使用 ctx.tags.[tagId](如 ctx.tags.rotationSpeedText)获取某个tag对应的SVG元素数组。 通常该数组仅包含一个元素,但在一般场景下,SVG文件也可能存在多个共享同一tag id的元素。

第7步:预览模式

在预览模式下,您可以检查未来部件的行为和配置正确性。

进入预览模式时,点击窗口右侧的 “Preview” 按钮。 左侧面板会显示SVG,右侧面板会显示部件配置。

下面测试部件行为:

  • 点击绿色 “On” 按钮。按钮将不可点击,颜色应变为灰色;风扇会由红色变为绿色并开始旋转,且下方显示RPM数值。与此同时,”Off” 按钮会变为可点击并由灰色变为红色。点击它;
  • 风扇应停止,”Off” 按钮再次变为不可点击,颜色恢复为灰色。

第8步:创建部件

现在我们已完成部件配置,接下来需要创建部件。操作如下:

  • 点击右上角 “Create widget” 按钮;
  • 在新窗口中输入部件名称,并选择已有widget bundle或新建一个。这里选择新建,输入名称后点击 “Create new widget bundle”;
  • 可选:为widget bundle添加预览图,然后点击 “Add”;
  • 点击 “Create” 确认创建部件。

下载SCADA symbol

您可以下载包含全部配置的SCADA symbol。点击SCADA symbol编辑器左侧面板的 “Download SCADA symbol” 按钮后,SVG文件将保存到本地电脑。


以下是已完成配置的SCADA symbol示例:

FAN SVG

部件测试

下面在dashboard中测试该部件:

  • 新建一个dashboard或打开已有dashboard。进入 “Layouts” 设置,将布局从 “Default” 改为 “SCADA”,然后点击 “Save”;
  • 点击页面顶部 “Add widget” 按钮,或点击页面中央大号 “Add new widget” 图标;
  • 找到并点击 “My SCADA widgets” widget bundle;
  • 点击 “Fan” 部件,将其添加到dashboard;
  • 指定目标device(可使用任意device),然后点击 “Add”;
  • 部件添加后,点击 “Save” 保存dashboard变更;
  • 点击绿色 “On” 按钮。按钮将变为不可点击、颜色变灰;风扇会由红变绿并开始旋转,下方显示RPM值;
  • 此时 “Off” 按钮会变为可点击并由灰变红。点击它后,风扇应停止,”Off” 按钮再次变为不可点击且颜色恢复为灰色。

参考

ScadaSymbolContext

ScadaSymbolContext(在函数代码中以 ctx 表示)是ThingsBoard中用于与SCADA symbol交互的核心JavaScript对象,包含以下字段:

  1. ctx.svg:用于访问SVG根节点,是进入SVG DOM结构的主要入口。

  2. ctx.tags:按tag ID(对象键)归类所有已打标的SVG元素,例如 ctx.tags.myTagId。每个tag ID对应一个数组,数组中包含一个或多个SVG元素。

  3. ctx.values:保存所有来自 Value 类型behavior项的值。该字段对基于device或其他来源数据动态更新symbol至关重要。

  4. ctx.properties:包含为SCADA symbol定义的全部properties,可根据最终用户需求进行外观自定义与配置调整。

  5. ctx.api:提供 SCADA symbol API 引用,包含与SVG元素及其关联动作进行交互、修改和管理的方法。

该对象对于开发者高效创建和管理SCADA symbol交互元素至关重要。接口定义如下:

1
2
3
4
5
6
7
export interface ScadaSymbolContext {
    api: ScadaSymbolApi;
    tags: {[id: string]: Element[]};
    values: {[id: string]: any};
    properties: {[id: string]: any};
    svg: Svg;
}

ScadaSymbolApi

ScadaSymbolApi(通过 ScadaSymbolContext 访问时记作 api)是用于操作ThingsBoard中SCADA symbol元素的综合JavaScript接口。它封装了创建、修改和管理SVG元素交互所需的多种方法。该API的主要功能如下:

  • generateElementId:为元素生成唯一标识符。创建新元素时非常有用。
    1
    
     generateElementId: () => string
    

    Returns:新生成的字符串类型元素ID。

  • formatValue:按指定精度与单位转换规则格式化数值。
    1
    
     formatValue: (value: any, dec?: number, units?: string | TbUnit, showZeroDecimals?: boolean) => string | undefined
    

    Parameters

    • value:待格式化的数值。
    • dec(optional):小数位数,通常来自 ctx.properties
    • units(optional):追加到格式化结果中的单位,通常来自 ctx.properties
    • showZeroDecimals(optional):是否保留为零的小数位,通常来自 ctx.properties

    Returns:格式化后的字符串;若格式化失败则返回undefined。

  • formatValue:按指定精度与单位转换规则格式化数值。
    1
    
     formatValue: (value: any, settings: ValueFormatSettings) => string | undefined
    

    Parameters

    • value:待格式化的数值。
    • settings:定义格式化选项(decimals、units、ignoreUnitSymbol、showZeroDecimals)的 ValueFormatSettings 对象。

    Returns:格式化后的字符串;若格式化失败则返回undefined。

  • text:设置或更新一个或多个SVG元素的文本内容。仅适用于 SVG.TextSVG.Tspan 类型元素。
    1
    
     text: (element: Element | Element[], text: string) => void
    

    Parameters

    • element:SVG元素或SVG元素数组。
    • text:要设置的文本。

  • font:为文本元素应用字体样式和颜色。仅适用于 SVG.TextSVG.Tspan 类型元素。
    1
    
     font: (element: Element | Element[], font: Font, color: string) => void
    

    Parameters

    • element:SVG元素或SVG元素数组。
    • font:用于设置文本字体的Font配置对象,通常来自 ctx.properties
    • color:用于设置文本颜色的字符串,通常来自 ctx.properties

  • icon:在SVG元素中嵌入图标,并可选设置尺寸、颜色及居中方式。仅适用于 SVG.G 类型元素。
    1
    
     icon: (element: Element | Element[], icon: string, size?: number, color?: string, center?: boolean) => void
    

    Parameters

    • element:SVG元素或SVG元素数组。
    • icon:要绘制的图标,支持 MDI 图标,通常来自 ctx.properties
    • size(optional):图标像素尺寸,通常来自 ctx.properties
    • color(optional):图标颜色,通常来自 ctx.properties
    • center(optional):是否在group元素内居中显示图标。

  • cssAnimate:启动基于CSS的动画,并提供与SVG.js Runner 类似的控制能力。会结束此前的CSS动画。
    1
    
     cssAnimate: (element: Element, duration: number) => ScadaSymbolAnimation
    

    Parameters

    • element:SVG元素。
    • duration:动画时长(毫秒)。

    ReturnsScadaSymbolAnimation 实例,用于控制动画。

  • cssAnimation:获取元素当前应用的CSS动画。
    1
    
      cssAnimation: (element: Element) => ScadaSymbolAnimation | undefined
    

    Parameters

    • element:SVG元素。

    Returns:当前CSS动画实例;若未应用动画则返回undefined。

  • resetCssAnimation:停止并清除元素上的所有CSS动画,将其重置为初始状态,同时移除CSS动画实例。
    1
    
      resetCssAnimation: (element: Element) => void
    

    Parameters

    • element:SVG元素。

  • finishCssAnimation:立即结束所有CSS动画,并将元素应用到最终动画状态,同时移除CSS动画实例。
    1
    
      finishCssAnimation: (element: Element) => void
    

    Parameters

    • element:SVG元素。

  • disable:禁用一个或多个元素的交互。例如用户点击时不会触发点击动作。
    1
    
      disable: (element: Element | Element[]) => void
    

    Parameters

    • element:SVG元素或SVG元素数组。

  • enable:重新启用先前被禁用元素的交互。例如用户点击时会触发点击动作。
    1
    
      enable: (element: Element | Element[]) => void
    

    Parameters

    • element:SVG元素或SVG元素数组。

  • callAction:按ID触发指定behavior动作,并可选传入值与observer回调。
    1
    
      callAction: (event: Event, behaviorId: string, value?: any, observer?: Partial<Observer<void>>) => void
    

    Parameters

    • event:事件对象。
    • behaviorId:类型为 Action 的behavior项ID。
    • value(optional):传给该动作的参数。
    • observer(optional):结果回调。

  • setValue:更新 ctx.values 对象中的某个值,并触发所有渲染函数。
    1
    
      setValue: (valueId: string, value: any) => void
    

    Parameters

    • valueId:类型为 Value 的behavior项ID。
    • value:要设置的新值。

  • unitSymbol:根据当前单位制或传入单位,获取目标单位符号。
    1
    
     unitSymbol: (unit: TbUnit) => string
    

    Parameters

    • unit:单位定义,可为字符串,或为不同单位制(如METRIC、IMPERIAL、HYBRID)定义映射关系的TbUnitMapping对象。

    Returns:目标单位符号字符串,由当前单位制或传入单位计算得到。

  • convertUnitValue:根据提供的单位定义,将数值从一个单位转换到另一个单位。
    1
    
     convertUnitValue: (value: number, unit: TbUnit) => number
    

    Parameters

    • value:待转换的数值。
    • unit:单位定义,可为表示源单位的字符串,或用于按单位制转换的TbUnitMapping对象。

    Returns:转换后的数值;若转换失败或无需转换,则返回原值。

ScadaSymbolAnimation

ThingsBoard中的 ScadaSymbolAnimation 接口用于在SCADA symbol内实现复杂CSS动画。 该接口允许开发者动态控制动画细节,并提供多种方法来操作动画行为与属性。 以下是 ScadaSymbolAnimation 接口的关键方法:

  • running:检查动画当前是否正在运行。
    1
    
     running: () => boolean
    

    Returns:若动画正在运行返回 true,否则返回 false

  • play:启动或继续动画。
    1
    
     play: () => void
    
  • pause:暂停动画。
    1
    
     pause: () => void
    
  • stop:停止动画并重置进度。
    1
    
     stop: () => void
    
  • finish:完成动画并跳转到结束状态。
    1
    
     finish: () => void
    
  • speed:设置动画速度。
    1
    
     speed: (speed: number) => ScadaSymbolAnimation
    

    Parameters

    • speed:速度系数(例如 2 表示速度为2倍)。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • ease:设置动画缓动函数。
    1
    
     ease: (easing: string) => ScadaSymbolAnimation
    

    Parameters

    • easing:缓动类型(如 linearease-inease-out)。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • loop:使动画按指定次数重复播放。
    1
    
     loop: (times?: number, swing?: boolean) => ScadaSymbolAnimation
    

    Parameters

    • times(optional):动画重复次数。
    • swing(optional):若为 true,动画方向将交替。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • transform:对动画元素应用矩阵变换。
    1
    
     transform: (transform: MatrixTransformParam, relative?: boolean) => ScadaSymbolAnimation
    

    Parameters

    • transform:与 SVG.js 类似的变换对象,但仅支持以下属性:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      rotate?: number
      scaleX?: number
      scaleY?: number
      ox?: number
      originX?: number
      oy?: number
      originY?: number
      translateX?: number
      translateY?: number
      
    • relative(optional):若为 true,则相对于当前状态进行变换。

Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • rotate:围绕某个点旋转元素。
    1
    
      rotate: (r: number, cx?: number, cy?: number) => ScadaSymbolAnimation
    

    Parameters

    • r:旋转角度(度)。
    • cxcy(optional):旋转中心。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • x:沿x轴移动元素。
    1
    
      x: (x: number) => ScadaSymbolAnimation
    

    Parameters

    • x:新的x坐标。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • y:沿y轴移动元素。
    1
    
      y: (y: number) => ScadaSymbolAnimation
    

    Parameters

    • y:新的y坐标。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • size:设置元素尺寸。
    1
    
      size: (width: number, height: number) => ScadaSymbolAnimation
    

    Parameters

    • width:新的宽度。
    • height:新的高度。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • width:设置元素宽度。
    1
    
      width: (width: number) => ScadaSymbolAnimation
    

    Parameters

    • width:新的宽度。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • height:设置元素高度。
    1
    
      height: (height: number) => ScadaSymbolAnimation
    

    Parameters

    • height:新的高度。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • move:将元素移动到新位置。
    1
    
      move: (x: number, y: number) => ScadaSymbolAnimation
    

    Parameters

    • x:新的x坐标。
    • y:新的y坐标。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • dmove:按指定增量移动元素。
    1
    
      dmove: (dx: number, dy: number) => ScadaSymbolAnimation
    

    Parameters

    • dx:x坐标增量。
    • dy:y坐标增量。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • relative:相对于当前位置移动元素。
    1
    
      relative: (x: number, y: number) => ScadaSymbolAnimation
    

    Parameters

    • x:x增量。
    • y:y增量。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • scale:以中心点为基准缩放元素。
    1
    
      scale: (x: number, y?: number, cx?: number, cy?: number) => ScadaSymbolAnimation
    

    Parameters

    • x:x轴缩放因子。
    • y(optional):y轴缩放因子。
    • cxcy(optional):缩放中心点。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

  • attr:设置元素属性。
    1
    
      attr: (attr: string | object, value?: any) => ScadaSymbolAnimation
    

    Parameters

    • attr:属性名,或属性名-属性值对象。
    • value(optional):当 attr 为单个属性名时对应的属性值。

    Returns:自身(更新后的 ScadaSymbolAnimation 实例),可用于链式调用。

ConnectorScadaSymbolAnimation

ThingsBoard中的 ConnectorScadaSymbolAnimation 接口用于管理SVG连接线元素动画,尤其是沿指定路径的流动动画。 该接口提供对动画播放、外观、速度和方向的控制方法,可动态操控连接线动画。 以下是 ConnectorScadaSymbolAnimation 接口的关键方法:

  • play:启动或继续连接线动画。
    1
    
     play: () => void
    

若SVG元素中尚不存在动画路径,则先添加该路径,并以同步偏移方式启动动画。

  • stop:停止连接线动画。
    1
    
     stop: () => void
    

通过停止 animate 元素结束动画,并暂停流动效果。

  • finish:完成连接线动画并将其移除。
    1
    
     finish: () => void
    

从SVG元素中移除动画路径,从而结束动画。

  • flowAppearance:配置连接线动画的视觉外观。
    1
    
     flowAppearance: (width: number, color: string, linecap: StrokeLineCap, dashWidth: number, dashGap: number) => ConnectorScadaSymbolAnimation
    

    Parameters

    • width:动画路径的描边宽度。
    • color:动画路径的描边颜色(例如 #C8DFF7)。
    • linecap:描边端点样式(buttroundsquare)。
    • dashWidth:描边 dasharray 中短划线宽度。
    • dashGap:描边 dasharray 中短划线间距。

    Returns:自身(更新后的 ConnectorScadaSymbolAnimation 实例),可用于链式调用。

  • duration:设置连接线动画速度。
    1
    
     duration: (speed: number) => ConnectorScadaSymbolAnimation
    

    Parameters

    • speed:动画持续时间(秒)。

    Returns:自身(更新后的 ConnectorScadaSymbolAnimation 实例),可用于链式调用。

  • direction:设置连接线动画沿路径的流动方向。
    1
    
     direction: (direction: boolean) => ConnectorScadaSymbolAnimation
    

    Parameters

    • direction:若为 true 使用正向路径;若为 false 使用反向路径。

    Returns:自身(更新后的 ConnectorScadaSymbolAnimation 实例),可用于链式调用。