3. ThingWorx Composer建模环境实操

进入 ThingWorx Composer 后,最先要建立的空间感不是“菜单在哪”,而是“我当前在哪个层级操作”。Composer 的建模工作区可以理解为三层:最外层是项目(Project),用于把一组相关实体打包、导出和迁移;中间层是实体(Entity),如 Thing、ThingTemplate、ThingShape、DataShape、Mashup;最内层是实体自身的配置页签,如 General Information、Properties、Services、Subscriptions、Permissions。很多初学者把属性直接建在 Thing 上,结果后续同类设备无法复用,问题就出在没有先分清 ThingTemplate 与 Thing 的职责边界。

本节以一个具体对象贯穿:一台名为 CNC-01 的数控机床。我们希望在 Composer 中创建它的数字孪生体,采集三个属性:SpindleSpeed(主轴转速,NUMBER,单位 rpm)、RunState(运行状态,STRING,取值 Idle/Running/Fault)、Temperature(主轴温度,NUMBER,单位 ℃)。这三个属性既有数值型也有字符串型,能覆盖属性定义中最常见的类型选择与绑定场景。

项目组织:先建容器,再放实体

推荐的操作顺序是先在 Browse > Projects 中新建项目 PRJ_CNC_Demo,再在项目上下文里创建实体。项目本身不改变实体运行逻辑,但它决定了导出、导入和权限继承的范围。一个实用约定是:项目名与设备族对应,实体名与具体设备对应。例如项目 PRJ_CNC_Demo 下放 CNC-01、CNC-02,而它们的模板 CNC_Template 也归入同一项目,这样打包迁移时不会漏掉依赖。

权限与版本:建模时就要考虑的两件事

权限在 Composer 中按“实体 + 用户/用户组 + 权限类型”三元组设置。常见权限类型包括 Design(设计)、Read(读取)、Write(写入)、Execute(执行服务)、Visibility(可见性)。对 CNC-01 的合理初始设置是:管理员组拥有全部权限;运维组拥有 Read 与 Execute;现场操作组只拥有 Read。注意 Write 权限要谨慎开放,因为它允许外部系统直接改写属性值,可能绕过业务校验。

版本管理方面,Composer 提供实体的 Save 与 Check In / Check Out 机制。当实体被 Check Out 后,其他用户无法同时编辑,避免覆盖冲突;修改完成后 Check In 并填写版本说明,例如“v1.1 增加 Temperature 属性”。对于本节练习,建议在创建完属性后执行一次 Check In,形成可回溯的基线版本。

Composer 建模工作区:项目 → 实体 → 属性绑定 项目层 Project PRJ_CNC_Demo 作用:打包实体、导出迁移、权限继承范围 约定:项目名 ↔ 设备族,实体名 ↔ 具体设备 实体层 Entity CNC_Template ThingTemplate(可复用) CNC-01 Thing(实例) CNC-02 Thing(实例) CNC_DataShape DataShape(数据结构) 继承属性/服务 实例化 属性定义与值绑定(CNC-01) Properties 定义 SpindleSpeed : NUMBER (rpm) RunState : STRING (Idle/Running/Fault) Temperature : NUMBER (℃) 值绑定来源 Remote Thing / Edge Agent REST API 写入 Service 内部赋值 权限与版本 Design / Read / Write / Execute Check Out → 编辑 → Check In 版本说明:v1.1 增加 Temperature

创建第一个 Thing:从模板继承还是从零开始

在 Composer 中点击 + > Thing,会弹出新建对话框。这里有两个关键选择:Base Thing Template 和 Project。如果选择 GenericThing,得到的是一个空壳;如果选择我们自建的 CNC_Template,则自动继承模板中已定义的属性、服务和订阅。对于本节练习,建议先创建 CNC_Template,再基于它创建 CNC-01,这样能直观看到继承关系。

创建 CNC-01 时,Name 填 CNC-01,Description 填“一号数控机床数字孪生体”,Thing Template 选 CNC_Template,Project 选 PRJ_CNC_Demo。保存后进入 General Information 页签,确认 Enabled 为 true,Thing Template 显示正确。此时 CNC-01 已经继承了模板中的属性定义,但属性值仍为空。

属性定义:类型、默认值与持久化

在 CNC_Template 的 Properties 页签中逐个添加属性。以 SpindleSpeed 为例:Base Type 选 NUMBER,Default Value 填 0,Data Change Type 选 VALUE,Persistent 勾选 true,Logged 可勾选 true 以便后续做趋势分析。这里有几个容易出错的点:

  • Base Type 与 DataShape 的区别:单个属性用 Base Type 即可;如果一组属性经常一起传输(如一次上报包含转速、状态、温度),应定义 DataShape 并让属性引用它。
  • Persistent 的含义:勾选后属性值会写入数据库,Thing 重启后仍保留;不勾选则只存在于内存,适合临时计算值。
  • Default Value 的作用:Thing 首次启动且尚未收到外部写入时,属性值取默认值。把 RunState 默认值设为 Idle,比留空更利于上层 Mashup 显示。

三个属性定义完成后,在 CNC-01 的 Properties 页签中应能看到它们,且值列显示默认值。此时可以手动在 Composer 中修改 SpindleSpeed 为 1200,保存后刷新页面,确认值被持久化。

值绑定:让属性真正“活”起来

属性定义只是声明了“有这个数据”,值绑定才决定“数据从哪来”。在 Composer 中常见的绑定方式有三种:

  1. Remote Thing 绑定:在 CNC-01 的 Properties 中,将某个属性的 Remote 勾选,并指定远程 Thing 名称与远程属性名。适用于边缘设备通过 AlwaysOn 协议上报的场景。
  2. Service 赋值:在 Thing 的 Service 中通过 me.SpindleSpeed = 1500; 直接赋值。适用于内部计算或业务逻辑驱动的属性更新。
  3. REST API 写入:外部系统调用 PUT /Thingworx/Things/CNC-01/Properties/SpindleSpeed,请求体为 {"SpindleSpeed":1500}。适用于 MES、SCADA 等系统集成。

本节练习采用第二种方式做一次闭环验证:在 CNC-01 中新建一个 Service,命名为 SimulateSpindle,脚本如下:

// 模拟一次主轴转速更新
me.SpindleSpeed = 1500;
me.RunState = "Running";
me.Temperature = 42.5;
// 返回当前值,便于在 Composer 中直接观察
var result = {
    SpindleSpeed: me.SpindleSpeed,
    RunState: me.RunState,
    Temperature: me.Temperature
};

保存并执行该 Service,观察 Properties 页签中的值是否变为 1500、Running、42.5。如果值未变化,优先检查 Service 是否已保存、Thing 是否处于 Enabled 状态、以及当前用户是否拥有该属性的 Write 权限。这一步是很多初学者卡住的地方:Service 能执行,但属性没变,往往是权限或持久化设置的问题。

权限与版本的实操检查点

完成属性绑定后,回到 CNC-01 的 Permissions 页签,按前文建议设置三组权限。然后执行 Check Out,修改 Description 为“一号数控机床数字孪生体(含温度采集)”,Check In 并填写版本说明。此时在 Version History 中应能看到两条记录:初始创建和本次修改。这个动作看似简单,却是团队协作中避免“谁改了、改了什么”说不清的关键习惯。

建议在完成本节后,把 PRJ_CNC_Demo 导出为 .twx 文件并保存。导出时勾选“Include dependencies”,这样 CNC_Template、CNC_DataShape 等依赖会一并打包,后续导入到测试环境时不会出现“实体缺失”的错误。