WinCC 8.2 中 JavaScript 使用全解析:从入门到调试
一、WinCC 8.2 引入 JavaScript
WinCC 在 V8.2 版本中,除了传统的 ANSI-C 和 VBScript 之外,正式引入了 JavaScript 作为第三种脚本编程接口 。这一变化顺应了 Web 化的技术趋势——JavaScript 语法现代、生态庞大、学习资源多,对新一代工程师更友好。
在 WinCC 8.2 中,JavaScript 主要可以干两件事:
- 读写变量(Tags):例如读取 PLC 的设定值、写入控制器的设定值;
- 与画面无关的动作(Actions):通过周期性触发或变量变化触发,执行画面之外的逻辑,比如每天定时把数据写入 Excel 报表。
需要注意的是:JavaScript 只能在 Global Script 编辑器中编写,不能在图形设计器(Graphics Designer)中直接使用。
路径分隔符上,JavaScript 使用双反斜杠 \\(与 ANSI-C 相同,区别于 VBScript 的单反斜杠 \)。
二、核心概念:函数、模块与动作
理解 WinCC 的 JavaScript,必须先理清三个核心概念的关系:
| 概念 | 说明 |
|---|---|
| 函数(Function) | 一段可复用的代码,没有自己的触发器,只能被动作或其他函数调用。可带返回值,也可不带。 |
| 模块(Module) | 存放函数的文件,扩展名为 .jmo,位于 <项目目录>\JScriptLib\ 下。相关函数应组织在同一模块中。 |
| 动作(Action) | 必须有触发器(Trigger),由事件(时间到达或变量变化)触发执行。扩展名为 .jac,位于 <项目目录>\JScriptAct\ 下。 |
三者的关系可以概括为:动作是入口,函数是工具,模块是工具箱 。
模块化与 import 语法
WinCC 的 JavaScript 支持 ES 模块风格的导入导出:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import * as module_calculateOEE from 'calculateOEE'; export function Quality() { let Line1totalUnitsProduced = HMIRuntime.Tags("Line1.totalUnitsProduced"); let Line1goodUnitsProduced = HMIRuntime.Tags("Line1.goodUnitsProduced"); Line1totalUnitsProduced.Read(); Line1goodUnitsProduced.Read(); const QualityLine1 = module_calculateOEE.calculateQuality( Line1totalUnitsProduced.value, Line1goodUnitsProduced.value ); } |
⚠️ 性能提示:调用脚本时加载的模块越多、模块越大,Runtime 性能越差。建议按工艺单元或功能主题划分模块,避免一个巨型模块塞入所有函数。
全局变量的注意事项
WinCC 中的全局 JavaScript 变量行为与 Web 应用不同。若要实现类似 Web 中全局变量的效果,官方推荐使用 HMIRuntime.DataSet 对象。
三、动作与触发器
动作的生命完全由触发器驱动——没有触发器的动作不会执行 。
WinCC 8.2 支持两类触发器:
1. 定时器触发器(Timer)
- 周期性触发:标准周期(从 Runtime 启动时开始计时)、每小时、每天、每周、每月、每年;
- 注意:周期性触发保证高刷新率但带来高系统负载,只应在更新要求确实很高的动作上使用。
2. 变量触发器(Tag)
- 值变化时(Upon Change):每次变量变化都触发,系统负载最高,应谨慎使用;
- 按标准周期查询(Cyclic Query):每隔设定周期(如每 2 秒)查询一次,检测到变化才触发。周期越大,可能漏掉两次查询之间的变化。
性能最佳实践:优先使用变量触发器而非周期触发器——变量没变时动作不执行,可显著降低系统负载。查询周期尽量设大。
一个动作可以关联多个触发器,任一触发事件发生时动作都会执行;两个事件同时发生则动作顺序执行两次。
在 Runtime 中激活全局动作
要让画面无关的全局动作真正跑起来,必须在启动列表中激活:
- 打开 WinCC Configuration Studio 的"计算机"编辑器;
- 选择计算机名,切换到"启动 WinCC Runtime 时的进程"选项卡;
- 勾选 "Global Script Runtime" 组件。
四、读写变量:核心代码示例
写变量
|
1 2 3 4 5 6 7 8 9 10 11 12 |
// 最简单的方式——直接写 HMIRuntime.Tags("Tag1").Write(6); // 带对象引用的写法——可以先读再算再写 let objTag; objTag = HMIRuntime.Tags("Tag1"); objTag.Read(); objTag.Value = objTag.Value + 1; objTag.Write(); // 同步写入(确保值真正写入后才继续执行) objTag.Write(8, 1); |
同步写入对应 ANSI-C 中的 SetTagXXXWait(),调用耗时更长,与通道和 PLC 有关,请酌情使用。
带状态检查的读写
生产环境中建议始终检查 LastError 和 QualityCode (0x80 表示良好):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
let objTag; let qualityCodeInt; objTag = HMIRuntime.Tags("Tag1"); qualityCodeInt = 80; objTag.Read(); if (objTag.QualityCode != qualityCodeInt.toString(16)) { HMIRuntime.Trace("Error: " + objTag.LastError + " " + "ErrorDescription: " + objTag.ErrorDescription + " " + "QualityCode: 0x" + objTag.QualityCode.toString(16) + " "); } else { HMIRuntime.Trace("Value: " + objTag.Value + " "); } |
读变量
|
1 2 3 4 5 6 |
// 简单读 HMIRuntime.Trace("Value: " + HMIRuntime.Tags("Tag1").Read()); // 直接从 AS 读取(绕过映像区,用于快速过程同步) let objTag = HMIRuntime.Tags("Tag1"); HMIRuntime.Trace("Value: " + objTag.Read(1)); |
用 Read() 读过的过程变量会被注册进映像区,之后周期性向 PLC 请求;画面关闭时自动注销。但在全局脚本动作中读取的变量,会在整个 Runtime 运行期间保持注册。
数组变量
WinCC 的 JavaScript 不支持多维数组。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
let tagObj = HMIRuntime.Tags("ArrTag"); tagObj.Read(); let tagValue = tagObj.Value; // 读取单个元素 let arrEleValue = tagValue[0]; // 修改单个元素后整体写回 tagValue[0] = 42; tagObj.Write(tagValue); // 遍历数组 for (let i = 0; i < tagValue.length; i++) { HMIRuntime.Trace(tagValue[i]); } |
其他实用 HMIRuntime 方法
|
1 2 3 4 5 6 7 8 9 10 11 |
// 切换全局设计主题 HMIRuntime.Design = "WinCC Dark"; // 切换 Runtime 语言(LCID:1031 德语,1033 英语) HMIRuntime.Language = 1031; // 停止 Runtime HMIRuntime.Stop(); // 输出诊断信息到 GSC 诊断窗口 HMIRuntime.Trace("Customized error message"); |
GSC 诊断窗口会按调用时间顺序显示 ANSI-C、VBScript 和 JavaScript 三者的 Trace 输出,是排查脚本问题的重要工具。
五、调试 JavaScript
WinCC 8.2 提供两种调试器:
方式一:Chrome DevTools(推荐入门)
启用调试 (默认关闭):
- 打开 WinCC Configuration Studio → "计算机"编辑器;
- 本地设置 → JavaScript → 勾选 "Debug Global Scripts";
- 设置端口号(默认 9224);
- 启动 Runtime。
调试器仅本地可用,不能远程访问。生产环境务必关闭调试,长时间停留在断点会导致动作堆积、画面不刷新。
连接调试 :
- Chrome 打开
chrome://inspect; - 选择 Devices → 勾选 "Discover network targets" → Configure;
- 添加
localhost:9224; - 在 Remote Target 中为每个上下文点击 inspect(建议为全部 5 个 GlobalActionsContext 各开一个窗口)。
为什么要开多个窗口? 因为每个 Context 对应一个线程,而 JS 脚本每次触发时可能随机使用不同线程执行 ——只监视一个 Context 很可能看不到脚本的执行过程。调试基本操作与 Web 前端一致:
- F8:执行到下一个断点;
- F10:单步跳过(不进入函数内部);
- F11:单步进入(只能进入自己定义的函数);
- Shift+F11:跳出当前函数;
- 右键行号 → "Continue to here":执行到指定行;
- 支持条件断点(右键行号 → "Add conditional breakpoint");
- Watch、Scope、Call Stack、Console 查看变量值。
项目更新后需刷新调试器 :重新启动项目或修改全局脚本后,连接会断开。关闭所有 DevTools 窗口后,重新在起始页对各 Context 点击 inspect 即可。
方式二:VS Code + 官方扩展
安装西门子官方扩展 "WinCC Unified Runtime Debugger" (可在 Siemens Industry Online Support 下载),即可在 VS Code 环境中直接调试 Runtime 脚本,适合习惯 IDE 的开发者。
六、编辑器使用要点
Global Script 编辑器基于微软 Monaco 编辑器(VS Code 同款内核),提供:
- 语法高亮:关键字/函数蓝色、注释绿色、字符串红色、常量灰色;
- 自动补全:输入时上下文敏感地提示可用对象、属性和方法;
- 代码模板:导航窗口的"代码模板"选项卡提供 if/else、for 等常用结构,拖入代码后把
_XYZ_占位符替换为实际内容; - 选择对话框快捷键:
Ctrl+U选变量、Ctrl+W选变量带引用、Ctrl+B选画面; - 语法检查:
F7。注意语法检查只能发现语法错误,引用不存在之类的逻辑错误只能在 Runtime 暴露; - 书签:
Ctrl+F9设置,F9/Shift+F9前后跳转; - 模块和动作均可通过 "Info/Trigger" 对话框设置密码保护、版本信息和作者信息。
几个重要的保存/运行行为:
- 若模块中有任一函数语法错误,整个模块将无法加载,其中的所有函数都不可调用;
- Runtime 中保存全局动作会重置整个项目所有计算机上的全局和本地动作,触发器和静态变量会被重新初始化;
- 动作可在多个项目间复用:直接复制
.jac/.jmo文件到目标项目对应目录,或编辑器中"另存为"。但要保证目标计算机上存在脚本引用的变量和函数,否则动作不执行或报运行时错误。
七、常见坑位总结
| 坑 | 说明 |
|---|---|
| 函数名必须项目内唯一 | 重名会导致模块被标记为语法错误 |
| JS/VBS/C 脚本不能互相调用 | 三种脚本可并存于项目,但不可混调 |
| 关键词区分大小写 | 拼写错误编辑时不一定报错,Runtime 才暴露 |
| 语法正确 ≠ 逻辑正确 | 务必在 Runtime 中实测,必要时上调试器 |
| 避免在周期 C 动作中直接读 AS | Read(1) 这类直接读对应 GetTagXXXWait(),是造成性能问题的头号原因 |
| 全局动作需激活组件 | 别忘了启动列表中的 "Global Script Runtime" |
| 密码遗忘无法找回 | 模块/动作加密后丢失密码将无法再编辑 |
结语
WinCC 8.2 的 JavaScript 脚本体系(函数 → 模块 → 动作 → 触发器)结构清晰,配合 Monaco 编辑器的现代编辑体验、Chrome DevTools 原生的调试能力,相比 VBS 和 ANSI-C 有更低的上手门槛和更好的可维护性。对于新项目,尤其是有 Web 开发背景的工程师,JavaScript 无疑是首选的 WinCC 脚本方案。