HMIx 实用指南
如何为 WinCC Unified & V8 创建 Custom Web Control(CWC):手动或借助 AI 的分步指南
Custom Web Control(CWC)是为 WinCC Unified 或 WinCC V8 量身定制的画面对象。在本指南中,你将制作一个真实的控件——一个显示三个数值的饼图——把它导入 TIA Portal,并在 Runtime 中看到它随数值变化,无需 PLC,也无需从零编写代码。最后,你还会看到如何借助 HMIx AI 生成器在几分钟内完成同样的工作。
- Siemens
- Custom Web Control
- CWC
- WinCC Unified
- WinCC V8
- TIA Portal
- HTML 与 JavaScript
- AI
- AI 生成器

完整流程一览
- 下载示例并在编辑器中打开
- 修改一段文字,做出你自己的版本
- 将内容压缩为
{GUID}.zip - 复制到
UserFiles\CustomControls,再拖到画面上 - 将
ValueA、ValueB、ValueC连接到变量,并在 Runtime 中测试
你需要准备
- 带有 WinCC Unified 的 TIA Portal(本文为 V21.1),以及其仿真或 Unified PC Runtime
- 一个文本编辑器,例如 Visual Studio Code 或 Notepad++
- Windows 文件资源管理器。无需 PLC,也无需编程知识
WinCC Unified 与 WinCC V8 的文件准备方式相同。导入和测试步骤以 TIA Portal / WinCC Unified V21.1 为例。在 WinCC V8 中使用 Graphics Designer 操作:请确认你的安装环境中可用的功能。
什么是 Custom Web Control(CWC),它有什么用
Custom Web Control,简称 CWC,是一种用 Web 技术(HTML、CSS 和 JavaScript)制作的定制画面对象。你可以像放置按钮或输入框一样把它放到 WinCC Unified 画面上,但它的外观和行为由你决定:可以是一张产量图、一种专用表格,也可以是包含多个指标的面板……
我们的示例是一个中间留空的饼图:中间显示合计,周围的三段分别表示 A、B、C 三个数量。某个数量变化时,对应的那一段就会变大或变小。
控件通过属性接收每个数值。属性就是一个有名字的输入口,例如 ValueA。在 TIA Portal 中,你会把这个属性连接到一个 HMI 变量,也就是项目中保存该数值的地方。控件并不关心数值来自哪里:在本次测试中由你在画面上输入;在真实设备上,数值则来自 PLC。
- 当 WinCC Unified 的标准对象无法提供你需要的显示或交互方式时,就可以使用 CWC。
- 如果只是想让符号变色,或让储罐显示液位,可以先从动态 SVG 开始:它涉及的部分更少。
在 HMIx 上,你可以下载数百种免费的 HMI 资源。可以从目录中的现成控件开始,也可以向 HMIx AI 生成器描述你的想法,创建一个可以根据项目调整的资源。

继续之前
路线始终相同:控件文件 → {GUID}.zip 包 → TIA Portal 中的画面 → 在 Runtime 中看到数值变化。
Siemens · Custom Web Control 编程Siemens · WinCC V8 中的 Custom Web Control
准备好工作环境(5 分钟)
你会在两个地方操作:在文本编辑器中准备控件,在 TIA Portal 中把它放到画面上。基础文件已经包含一个完整可用的图表,所以你不需要编写代码:只需了解每个部分的作用,并做第一次修改。
开始之前,请在 Windows 中打开文件扩展名显示(文件资源管理器 → 查看 → 显示 → 文件扩展名)。这样你就能看清文件是否真的以 .zip 或 .json 结尾,避免最常见的错误:类似 file.zip.zip 这样的文件名。
- 你需要带有 WinCC Unified 的 TIA Portal(步骤以 V21.1 为例),以及其仿真或 Unified PC Runtime。Runtime 就是运行 HMI 画面的程序。
- 使用 Visual Studio Code 等文本编辑器,以及本身就能创建 ZIP 文件的 Windows 文件资源管理器。不需要 PLC。
本指南要用的文件
下载这份基础示例,即可使用与指南相同的名称和数值跟着操作。
下载饼图文件包含三个属性和 Siemens 原版 WebCC 库的 ZIP。解压后可跟着本指南操作,也可以原样复制到 UserFiles\CustomControls 中直接试用。代码和结构已经过检查;在 WinCC Unified V21.1 中的导入和运行情况请在你的环境中确认。
操作位置 · TIA Portal → 项目树 → HMI 设备 → 画面(Screens)
准备一张空白画面
打开或新建一个包含 WinCC Unified 设备(例如 Unified PC)的测试项目。在设备的“画面”下新建一张名为
TestCWC的画面,然后保存项目。记下项目文件夹的位置:默认情况下,TIA Portal 会将其创建在文档\Automation\<项目名称>中。检查结果: 你有了一张空白画面,并且知道项目保存在电脑的哪个文件夹中。
操作位置 · Windows 文件资源管理器
下载并解压基础文件
使用本节的按钮下载饼图:它是一个名为
{8D821B43-4EF5-4BF1-A31D-931D283C7C04}.zip的 ZIP 文件。保留一份未改动的副本。右键 → 全部解压缩,并在对话框中把目标文件夹名称改为HmixPieChart(Windows 默认会建议使用较长的 GUID 名称)。检查结果: 在
HmixPieChart中可以看到manifest.json,以及assets和control两个文件夹。操作位置 · Visual Studio Code 或你的文本编辑器
在编辑器中打开文件夹
在 Visual Studio Code 中选择“文件 → 打开文件夹”,然后选择
HmixPieChart。如果看不到文件树,请打开资源管理器面板(Ctrl+Shift+E)。下一节会从这里依次打开各个文件。检查结果: 编辑器侧边栏中显示了控件的文件树。
继续之前
继续之前,让编辑器保持打开 HmixPieChart,让 TIA Portal 保持打开 TestCWC。请使用本指南的下载文件:目录中的 Pie Chart 产品具有不同的属性。
逐个文件搭建控件
CWC 由几个文本文件组成。你不需要记住它们,只要知道每个文件的作用即可。manifest.json 向 TIA Portal 介绍控件,index.html 包含你看到的内容,code.js 决定数值到达时图表如何变化。
操作位置 · 编辑器 →
HmixPieChart的资源管理器面板核对每个文件的位置
最外层是
manifest.json以及assets和control两个文件夹。control中包含index.html、code.js和webcc.min.js。最后这个文件是 Siemens 官方库,用于把控件与 WinCC Unified 连接起来:它已包含在内,不能修改。assets保存它的许可证;在你自己的控件中,还可以存放图标。一个文件夹,三部分协同工作
HmixPieChart/manifest.json控件的身份证:包括名称、标识符(GUID),以及它能从 WinCC Unified 接收的数值。
assets/SIEMENS-LICENSE.mdSiemens 通信库附带的许可证。
control/index.html绘制图表的页面。外观也在这里:颜色、尺寸和布局。
code.js数值变化时负责更新图表的指令。
webcc.min.js与 WinCC Unified 通信的桥梁。这是 Siemens 的官方文件:不要编辑。
这就是可下载示例的真实结构。请保留文件名和文件夹:清单会告诉 WinCC Unified 控件页面在哪里。 检查结果: 你的文件夹结构与示意图一致,没有放错位置的文件。
操作位置 · 编辑器 →
manifest.json认识图表的三个输入
打开
manifest.json,查找properties。你会看到ValueA、ValueB和ValueC。每一项都写有"type": "number"(接收一个数字),并在default中给出初始值:45、35 和 20。它们就是将在 TIA Portal 中出现的三个属性。再往上,在identity下还能找到displayname(TIA Portal 显示的名称,即 HMIx Pie Chart)和type,后者包含控件的唯一标识符。第一次测试时,请不要修改这个文件中的任何内容。检查结果: 你知道控件接收哪三个数量、它们叫什么,以及标识符在哪里。
操作位置 · 编辑器 →
control/index.html做第一次看得见的修改
这个文件用 HTML 组织内容,并在
<style>标签中用 CSS 规则定义颜色和尺寸。搜索(Ctrl+F)文字PIE CHART,把它替换为PRODUCTION。只修改这几个字母,不要改动外面的<span>标签,然后保存文件(Ctrl+S)。检查结果: 图表标题显示 PRODUCTION:你用一个容易检查的修改定制了自己的控件。
操作位置 · 编辑器 →
control/code.js找到负责更新数值的部分
code.js使用 JavaScript 编写,这是描述控件动作的语言。查找drawChart:这个函数负责计算合计并绘制各段。再往下,WebCC.start负责连接 WinCC Unified,onPropertyChanged会在每次属性变化时发出通知。注意ValueA、ValueB和ValueC的拼写与清单完全一致。这里不需要改动任何内容。检查结果: 你能区分外观(index.html)和接收并绘制数据的逻辑(code.js)。
操作位置 · Windows 文件资源管理器 →
HmixPieChart→control打包之前检查外观
双击
index.html,在浏览器中打开。你应该看到标题 PRODUCTION,以及数值为 45、35 和 20 的图表。它不响应任何操作是正常的:在 WinCC 之外,控件没有变量,只显示初始值。如果仍然看到 PIE CHART,请在编辑器中保存修改,再刷新页面(F5)。检查结果: 图表正常绘制,并显示你刚刚修改的文字。
操作位置 · Windows 文件资源管理器 →
HmixPieChart文件夹内制作 TIA Portal 要导入的 ZIP
进入
HmixPieChart,同时选中manifest.json、assets和control(Ctrl+单击)。右键 → 压缩为 ZIP 文件(Windows 10 中为:发送到 → 压缩(zipped)文件夹)。要选中的是这三项,而不是HmixPieChart文件夹本身。把生成的 ZIP 准确地重命名为{8D821B43-4EF5-4BF1-A31D-931D283C7C04}.zip,包括大括号:这就是清单中identity→type里的 GUID。如果名称不一致,TIA Portal 不会显示该控件。从工作文件夹到 TIA Portal 项目
选中文件夹里的内容
manifest.jsonassets/control/进入 HmixPieChart,选中这三项。HmixPieChart 文件夹本身不放进 ZIP。
压缩,并用 GUID 命名 ZIP
{8D821B43-4EF5-4BF1-A31D-931D283C7C04}.zipZIP 名称与 manifest.json 中的 GUID 一致。大括号也是名称的一部分。
将整个 ZIP 复制到这里
你的项目/UserFiles/CustomControls/{8D821B43-4EF5-4BF1-A31D-931D283C7C04}.zip
ZIP 放在这里,保持压缩状态。如果 UserFiles 和 CustomControls 不存在,请先创建。
打开 ZIP 时,应直接看到 manifest.json、assets 和 control。如果看到的是一个包含其他所有内容的 HmixPieChart 文件夹,说明多压缩了一层。 检查结果: 打开 ZIP 时,直接看到
manifest.json、assets和control,并且文件名与 GUID 一致。
跟着本指南操作时,请保留示例的标识。创建另一个独立控件时,请生成一个新的 GUID(例如在 PowerShell 中使用 [guid]::NewGuid()),以大写形式写入 identity → type(guid://…),并把同一个 GUID 加上大括号作为 ZIP 文件名。只重命名 ZIP 不会改变控件标识。
查看示例代码
可选:下载文件已包含完整示例。按照本指南测试时,无需自己编写这些代码。
manifest.json
{
"mver": "1.2.0",
"control": {
"identity": {
"name": "HmixPieChart",
"version": "1.0",
"displayname": "HMIx Pie Chart",
"type": "guid://8D821B43-4EF5-4BF1-A31D-931D283C7C04",
"start": "./control/index.html"
},
"metadata": {
"author": "HMIx",
"description": "Educational read-only three-value pie chart"
},
"contracts": {
"api": {
"methods": {},
"events": {},
"properties": {
"ValueA": { "type": "number", "default": 45 },
"ValueB": { "type": "number", "default": 35 },
"ValueC": { "type": "number", "default": 20 }
}
}
},
"types": {}
}
}
control/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>HMIx Pie Chart</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 20px;
background: #171e26;
color: #f3f5f6;
font:
14px system-ui,
sans-serif;
}
header {
display: flex;
justify-content: space-between;
color: #bac5ce;
font-size: 11px;
letter-spacing: 0.14em;
}
main {
display: flex;
align-items: center;
justify-content: center;
gap: 24px;
min-height: 240px;
}
svg {
width: 55%;
max-width: 300px;
flex-shrink: 0;
}
ul {
list-style: none;
padding: 0;
min-width: 110px;
}
li {
display: grid;
grid-template-columns: 10px 1fr auto;
align-items: center;
gap: 10px;
padding: 14px 0;
border-bottom: 1px solid #35404a;
}
.dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
small {
display: block;
margin-top: 4px;
color: #bac5ce;
font-variant-numeric: tabular-nums;
}
strong {
font-variant-numeric: tabular-nums;
}
@media (max-width: 360px) {
body {
padding: 12px;
}
main {
gap: 12px;
}
}
</style>
</head>
<body>
<header><span>HMIx</span><span>PIE CHART</span></header>
<main>
<svg viewBox="0 0 220 220" role="img" aria-labelledby="chart-title">
<title id="chart-title">Distribution of A, B and C</title>
<circle
cx="110"
cy="110"
r="76"
fill="none"
stroke="#35404a"
stroke-width="28"
/>
<g transform="rotate(-90 110 110)" fill="none" stroke-width="28">
<circle id="ValueA" cx="110" cy="110" r="76" stroke="#47d2c8" />
<circle id="ValueB" cx="110" cy="110" r="76" stroke="#79a9ed" />
<circle id="ValueC" cx="110" cy="110" r="76" stroke="#f5c16c" />
</g>
<text
id="total"
x="110"
y="115"
text-anchor="middle"
fill="#f3f5f6"
font-size="30"
font-weight="600"
>
100
</text>
<text
x="110"
y="139"
text-anchor="middle"
fill="#bac5ce"
font-size="10"
letter-spacing="2"
>
A + B + C
</text>
</svg>
<ul aria-label="Values and shares">
<li>
<i class="dot" style="background: #47d2c8"></i
><span>A<small id="ValueA-amount">45</small></span
><strong id="ValueA-percent">45%</strong>
</li>
<li>
<i class="dot" style="background: #79a9ed"></i
><span>B<small id="ValueB-amount">35</small></span
><strong id="ValueB-percent">35%</strong>
</li>
<li>
<i class="dot" style="background: #f5c16c"></i
><span>C<small id="ValueC-amount">20</small></span
><strong id="ValueC-percent">20%</strong>
</li>
</ul>
</main>
<script src="webcc.min.js"></script>
<script src="code.js"></script>
</body>
</html>
control/code.js
/* HMIx educational pie chart. Values are amounts, not required percentages. */
var values = { ValueA: 45, ValueB: 35, ValueC: 20 };
var keys = ['ValueA', 'ValueB', 'ValueC'];
var circumference = 2 * Math.PI * 76;
function drawChart() {
// Normalize before adding to avoid overflow for very large finite values.
var maximum = Math.max(values.ValueA, values.ValueB, values.ValueC, 1);
var sum = keys.reduce(function (n, key) {
return n + values[key] / maximum;
}, 0);
var offset = 0;
keys.forEach(function (key) {
var fraction = sum ? values[key] / maximum / sum : 0;
var arc = document.getElementById(key);
var length = fraction * circumference;
arc.setAttribute('stroke-dasharray', length + ' ' + circumference);
arc.setAttribute('stroke-dashoffset', String(-offset));
arc.setAttribute('visibility', fraction ? 'visible' : 'hidden');
document.getElementById(key + '-amount').textContent = String(values[key]);
document.getElementById(key + '-percent').textContent =
Math.round(fraction * 100) + '%';
offset += length;
});
var total = values.ValueA + values.ValueB + values.ValueC;
document.getElementById('total').textContent = isFinite(total)
? String(total)
: '—';
}
function setValue(key, value) {
if (keys.indexOf(key) === -1 || typeof value !== 'number' || !isFinite(value))
return;
values[key] = Math.max(0, value);
}
drawChart();
if (typeof WebCC !== 'undefined') {
WebCC.start(
function (connected) {
if (!connected) return;
keys.forEach(function (key) {
setValue(key, WebCC.Properties[key]);
});
drawChart();
WebCC.onPropertyChanged.subscribe(function (change) {
setValue(change.key, change.value);
drawChart();
});
},
{
methods: {},
events: [],
properties: { ValueA: 45, ValueB: 35, ValueC: 20 },
},
['HMI'],
10000,
);
}
继续之前
现在你有一个可编辑的控件(文件夹),以及包含文字修改的导入包(ZIP)。两者都要保留:文件夹用于编辑,ZIP 把结果带到 TIA Portal。
Siemens · 清单文件结构Siemens · WebCC 与 Runtime 接口Siemens · 示例文件与 WebCC 库Siemens · 创建 ZIP 文件
将 CWC 导入 TIA Portal 并放到画面上
导入包已经准备好。现在从文本编辑器转到 TIA Portal。ZIP 要放在项目文件夹中的特定子文件夹里,TIA Portal 才能找到它。
操作位置 · Windows 文件资源管理器 → 你的 TIA 项目文件夹
把 ZIP 复制到目标文件夹
打开开始时记下的项目文件夹,进入
UserFiles(如果不存在,就新建)。在其中新建名为CustomControls的文件夹(如果不存在),并把 ZIP 复制进去。保持压缩状态:不要解压,也不要只复制index.html。检查结果: 路径末尾为
UserFiles\CustomControls\{8D821B43-4EF5-4BF1-A31D-931D283C7C04}.zip。操作位置 · TIA Portal →
TestCWC画面 → 工具(Tools)任务卡让 TIA Portal 找到控件
打开
TestCWC画面。在右侧的工具(Tools)任务卡中,展开“我的控件”(My controls)窗格,然后点击其中的更新按钮。检查结果: HMIx Pie Chart 出现在“我的控件”窗格中。
操作位置 · TIA Portal → 我的控件(My controls)→
TestCWC画面把控件放到画面上
把 HMIx Pie Chart 从窗格拖到画面上。将其尺寸调整为约 480 × 300 像素,并在一侧留出空间,稍后要添加三个数值输入域。
检查结果: 画面上有一个带 PRODUCTION 标题的图表实例。
操作位置 · 选中的控件 → 巡视窗口(Inspector window)→ 属性 → 属性 → 接口(Interface)
找到你准备好的输入
选中控件,在巡视窗口中打开“属性 → 属性 → 接口”。在这里可以找到
ValueA、ValueB和ValueC,其初始值为 45、35 和 20。下一节会把这些固定值替换为变量。
Siemens 提供的可视参考,帮助你找到“我的控件”(My controls)和“接口”(Interface)。截图中显示的是 GaugeMeter 控件;在本指南中,请选择 HMIx Pie Chart,并找到 ValueA、ValueB 和 ValueC。 参考来源 · © Siemens AG · 许可与来源说明 检查结果: 你看到了
manifest.json中定义的同样三个属性。
继续之前
如果缺少 HMIx Pie Chart 或它的三个属性,请不要继续。按照“遇到问题时”一节中的检查清单,核对 ZIP 的名称、内容和位置。
连接变量并在 Runtime 中测试,无需 PLC
控件有三个输入,现在要为它们提供数据。你将创建三个内部变量(它们存在于 HMI 内部,不需要 PLC)和三个 I/O 域。I/O(输入/输出)域是画面上的一个框,可以在其中读取和写入数字。每个框和它对应的图表段使用同一个变量。
先看看预期效果
这个演示概括了测试过程:修改 A、B 或 C,观察对应的段和合计。这些数值是数量,不需要加起来等于 100。
操作位置 · TIA Portal → HMI 设备 → HMI 变量 → 变量表
创建三个测试变量
打开默认变量表,添加
ProductionA、ProductionB和ProductionC。在“连接”列中选择“内部变量”,并选择数值数据类型,例如Real。检查结果: 变量表中有三个使用这些名称的内部数值变量。
操作位置 ·
TestCWC画面 → 选中的 CWC → 属性 → 属性 → 接口(Interface)把每个变量连接到对应输入
在
ValueA一行中,打开“动态化”列,选择“变量”(Tag),然后选择ProductionA。“动态化”指属性从变量取值,而不再使用固定数字。同样设置ValueB→ProductionB和ValueC→ProductionC。保留“只读”(Read only)勾选:图表只负责显示数据,你会从输入框写入数据。三个数值如何传到图表
在每个 I/O 域中输入一个数字
- A
- 45
- B
- 35
- C
- 20
I/O 表示输入/输出:该域显示一个数值,并允许你在测试中修改它。
HMI 变量保存这个数字
- ProductionA
- 45
- ProductionB
- 35
- ProductionC
- 20
它们是项目内部变量。本次测试不需要 PLC。
控件属性接收该数值
- ValueA
- 45
- ValueB
- 35
- ValueC
- 20
在接口的“动态化”列中,将每个属性绑定到对应变量。
图表重新绘制
A: 45% · B: 35% · C: 20%
45、35 和 20 之和为 100。修改其中一个数字后,三个比例都会重新计算。
每个输入域和对应的图表属性都连接到同一个 HMI 变量:A 对 A、B 对 B、C 对 C。百分比根据三个数值之和计算。 
这是 Siemens 示例中连接属性的方式。在你的测试中,将 ValueA 连接到 ProductionA,并对 B 和 C 重复同样操作,保持勾选“只读”(Read only)。 参考来源 · © Siemens AG · 许可与来源说明 检查结果: 图表的每个输入都接收一个不同的变量,如示意图所示。
操作位置 ·
TestCWC画面 → 工具 → 元素 → I/O 域(I/O field)添加用于输入数字的框
把三个 I/O 域拖到图表旁边。为每个 I/O 域选择“输入/输出”模式,并将其过程值分别连接到
ProductionA、ProductionB和ProductionC。在旁边添加文字 A、B 和 C,便于区分。检查结果: 画面上有图表和三个域:分别对应 A、B 和 C。
操作位置 · TIA Portal → 项目树 → HMI 设备
编译并在 Runtime 中打开画面
右键点击
TestCWC,选择“设置为起始画面”(Define as start screen)(也可以在“运行系统设置 → 常规”中设置)。选中 HMI 设备,进行编译(右键 → 编译 → 软件),并修正出现的错误。然后点击“启动仿真”,或将项目下载到你的 Unified PC Runtime。Web 客户端随即打开:使用项目用户登录。如果还没有用户,请在“安全设置 → 用户和角色”中创建一个,为其分配 HMI 角色(例如 HMI Administrator),然后重新编译。检查结果: 你看到画面正在运行,并且可以在 I/O 域中输入数字。
操作位置 · Runtime 中的画面 → A、B、C 输入域
检查初始比例,再修改 A
在 A 中输入 45,在 B 中输入 35,在 C 中输入 20,每个数字都按 Enter 确认。合计应为 100。现在只把 A 改为 90 并确认:A 段变大,合计变为 145。这些数字是数量,而不是百分比:控件会自动算出每个数量占总量的比例。
检查结果: 确认数字后图表立即变化,无需重新加载画面。
操作位置 · Runtime 中的画面 → A、B、C 输入域
再检查空状态
在三个域中都输入 0:彩色段消失,只剩下一个合计为 0 的空环。重新输入 45、35 和 20,然后刷新浏览器页面(F5),检查控件打开时会读取当前数值。
检查结果: 控件既能显示正常数据,也能显示没有产量的情况。
继续之前
当输入框中的变化能更新对应段和合计时,测试即完成。之前在浏览器中看到图形并不能测试这种连接:只有 Runtime 可以。
遇到问题时:症状与解决方法
- “我的控件”中没有出现 HMIx Pie Chart: 打开 ZIP,其最外层必须直接包含
manifest.json、assets和control,中间不能多一层文件夹。检查文件名是否准确为{8D821B43-4EF5-4BF1-A31D-931D283C7C04}.zip(显示扩展名,确保不是.zip.zip),是否位于当前打开项目的UserFiles\CustomControls中,然后点击更新。 - 缺少
ValueA、ValueB或ValueC: 使用本指南的 ZIP,不要重命名manifest.json中的任何内容;名称区分大小写。目录中的 Pie Chart 产品具有不同的属性。 - 图表在 Runtime 中不变化: 按 Enter 确认数字。然后检查 I/O 域是否为“输入/输出”模式,以及该域和控件属性是否使用同一个变量。
- 无法登录 Runtime: 客户端要求使用项目用户。在“安全设置 → 用户和角色”中创建一个带 HMI 角色的用户,然后重新编译并下载。
- 仍然显示 PIE CHART: 保存
index.html,重新制作 ZIP,并替换项目中的 ZIP。在“我的控件”中点击更新:巡视窗口会提示对象已更新。再次编译并下载 HMI。只修改工作文件夹,不会改变 TIA Portal 中已有的内容。 - 在 PC 上正常,但在 Unified Comfort Panel 上失败: 确认所有依赖都包含在 ZIP 内,并查看 Siemens 针对该设备的限制,尤其是外部资源和数据请求方面的限制。
测试成功后,每次只修改一项:先改文字或颜色,再尝试其他数据呈现方式。如果重命名属性或更改其类型,TIA Portal 可能会丢失现有实例上的配置。始终在实际使用的设备上验证控件。
捷径:用 AI 创建你自己的 CWC
现在你已经了解 CWC 的内部结构。如果想在不编写 HTML 或 JavaScript 的情况下创建新控件,可以使用 HMIx AI 生成器(ai.hmix.tech):用自然语言描述控件,AI 就会准备好设计、属性、manifest.json 以及可直接导入 TIA Portal 的 {GUID}.zip 包。你可以通过 Community 套餐免费开始。
你在这里学到的内容依然适用:导入、连接变量和在 Runtime 中测试的方式完全相同。
操作位置 · ai.hmix.tech → Custom Web Control
描述你需要的控件
写下它要显示什么、接收哪些数据,例如:“饼图,显示 A、B、C 三个产量,中间显示合计,并带有百分比图例”。你也可以附上一张参考图片。
检查结果: AI 生成第一个可视化版本,你可以在聊天或可视化编辑器中继续完善。
操作位置 · 生成器 → 定义与仿真步骤
检查属性和仿真
检查 AI 提出的属性(相当于
ValueA、ValueB和ValueC),并用仿真控件调整它们,在下载前观察控件的反应。检查结果: 控件在仿真中的反应符合你的预期。
操作位置 · 生成器 → 生成与安装步骤
下载控件包
下载结果。下载的 ZIP 中包含说明文档,以及控件的
{GUID}.zip包:要复制到UserFiles\CustomControls的是这个内部文件,并且保持压缩状态。检查结果: 你得到一个与本指南格式相同的
{GUID}.zip。操作位置 · TIA Portal → 我的控件(My controls)
按本指南的方法导入并测试
使用新控件的名称,按照“将 CWC 导入 TIA Portal”和“连接变量并在 Runtime 中测试”两节操作。
检查结果: AI 生成的控件在你的 WinCC Unified 画面上正常工作。
在免费套餐中,生成的控件会发布到 HMIx 目录,供其他用户使用;付费套餐可以将其设为私有。
继续之前
AI 能加快创建速度,但不能代替测试。务必在 Runtime 和目标设备上验证控件。
常见问题
创建 Custom Web Control 需要会编程吗?
跟着本指南操作不需要:你使用的是完整文件,了解每个文件的作用并修改一段文字即可。如果要手动实现新的行为,需要掌握一些 HTML、CSS 和 JavaScript;使用 HMIx AI 生成器,则可以用自然语言描述控件,并得到可直接导入的控件包。
ValueA 和 ProductionA 有什么区别?
ValueA 是控件的属性,定义在 manifest.json 中。ProductionA 是你在 HMI 项目中创建的变量。在 TIA Portal 中把它们连接起来,控件就能接收 ProductionA 中保存的数字。两者不需要同名。
为什么 ZIP 必须用带大括号的 GUID 命名?
TIA Portal 通过 manifest.json 中 identity → type 的 GUID 识别每个 CWC,并要求控件包使用相同的名称(包括大括号):{GUID}.zip。如果名称不一致,控件就不会出现在“我的控件”中。
可以用 AI 创建 CWC 吗?
可以。HMIx AI 生成器(ai.hmix.tech)可根据描述为 WinCC Unified 和 V8 创建 Custom Web Control:包括设计、属性、manifest.json 和 {GUID}.zip 包。之后按照本指南的方法导入并测试即可。
可以在另一个项目中使用这个控件吗?
可以。把同一个 ZIP 复制到另一个项目的 UserFiles\CustomControls 中,在“我的控件”中点击更新,然后重新把属性连接到变量。如果是另一个不同的控件,请在清单和控件包名称中使用它自己的 GUID。