4. ThingTemplate与ThingShape的复用机制

在ThingWorx中,ThingTemplate(事物模板)与ThingShape(事物形状)是两种最核心的模型复用单元。它们解决的是同一个问题的两个侧面:ThingTemplate定义“一类设备是什么”,ThingShape定义“一类能力做什么”。理解二者的分工与组合方式,是避免重复建模、实现资产类型标准化的关键。

一、ThingTemplate:资产类型的“出厂规格”

ThingTemplate描述某一类资产的完整规格。以工业场景中常见的“离心泵”为例,一个名为PumpTemplate的模板通常包含以下内容:

  • 属性(Properties):如ratedFlow(额定流量,单位m³/h)、ratedHead(额定扬程,单位m)、ratedPower(额定功率,单位kW)、manufacturer(制造商)。这些属性在模板层定义名称、数据类型和默认值,实例化时只需覆盖差异值。
  • 服务(Services):如Start()、Stop()、GetRuntimeHours(),定义该类设备对外暴露的行为契约。
  • 事件(Events):如OverheatAlarm、VibrationHigh,定义该类设备可能产生的告警事件。
  • 订阅(Subscriptions):如属性temperature超过阈值时触发OverheatAlarm,将属性变化与事件绑定。

当现场有20台同型号离心泵时,只需创建20个Thing实例并分别绑定到PumpTemplate,每台泵只需填写serialNumber、installDate、location等实例级差异属性。模板层的任何修改——例如新增一个energyConsumption属性或调整OverheatAlarm的触发阈值——会自动传播到所有实例,无需逐台修改。

ThingTemplate支持继承。可以定义RotatingEquipmentTemplate作为基模板,包含vibration、bearingTemperature等旋转设备通用属性,再让PumpTemplate和FanTemplate继承它。子模板自动获得基模板的全部属性、服务和事件,并可追加或覆盖。

二、ThingShape:可组合的能力单元

ThingShape与ThingTemplate的本质区别在于:ThingTemplate是“是什么”,ThingShape是“能做什么”。一个ThingShape封装一组相关的属性、服务、事件和订阅,但它不限定具体设备类型。例如:

  • MaintainableShape:包含lastMaintenanceDate、maintenanceIntervalDays属性,以及ScheduleMaintenance()服务。
  • EnergyMonitorShape:包含powerConsumption、energyCost属性,以及ResetEnergyCounter()服务。
  • RemoteControlShape:包含Start()、Stop()、SetSpeed()服务,以及controlMode属性。

一个Thing可以同时实现多个ThingShape。例如一台离心泵可以同时实现MaintainableShape、EnergyMonitorShape和RemoteControlShape,从而获得可维护、可能耗监测、可远程控制三种能力。这种组合方式比继承更灵活:继承是“纵向”的类型层次,组合是“横向”的能力拼装。

ThingTemplate 继承 + ThingShape 组合 → Thing 实例 ThingTemplate 继承链 RotatingEquipmentTemplate vibration · bearingTemp healthIndex · GetHealth() extends PumpTemplate ratedFlow · ratedHead Start() · Stop() · OverheatAlarm extends CentrifugalPumpTemplate npshRequired · sealType Priming() · CavitationAlarm ThingShape 能力组合 MaintainableShape lastMaintenanceDate · ScheduleMaintenance() EnergyMonitorShape powerConsumption · ResetEnergyCounter() RemoteControlShape controlMode · SetSpeed() · Start() · Stop() implements Thing: Pump_Line3_A serialNumber = "CP-2024-0317" · location = "Line3" 继承自 CentrifugalPumpTemplate(含全部父模板属性/服务/事件) 同时实现 MaintainableShape + EnergyMonitorShape + RemoteControlShape instanceOf ThingTemplate(继承) ThingShape(组合) Thing 实例

三、继承与组合的协作规则

在实际建模中,ThingTemplate和ThingShape并非二选一,而是协同工作。一个Thing实例的最终能力由三部分叠加而成:

  1. 模板继承链:从最顶层的基模板到最底层的具体模板,逐层累积属性、服务、事件和订阅。子模板可以覆盖父模板的默认值,但不能删除父模板已定义的内容。
  2. ThingShape组合:Thing实例可以额外实现多个ThingShape,每个Shape贡献一组独立的能力。Shape之间不应有属性名冲突;若冲突,ThingWorx会以最后添加的Shape为准,因此命名时建议加前缀(如maint_、energy_)。
  3. 实例级覆盖:在Thing实例上可以直接修改属性值、添加订阅或覆盖服务实现。这是优先级最高的层,但应尽量少用,否则会削弱模板的标准化价值。
常见误区:把本应放在ThingShape中的通用能力(如“可维护性”)直接写进某个ThingTemplate。这样会导致其他设备类型无法复用该能力,只能重复定义。判断标准很简单——如果一组属性/服务与设备类型无关,只是“某种能力”,就应该做成ThingShape。

四、标准化建模的实操建议

以下是一套可直接参考的建模决策流程,用于判断一个新需求应该放在哪一层:

判断条件 归属层 示例
所有旋转设备共有的属性/服务 基模板(ThingTemplate) vibration、bearingTemperature
某类设备特有的属性/服务 具体模板(ThingTemplate) 泵的ratedFlow、阀的cvValue
跨设备类型的通用能力 ThingShape 可维护、可能耗监测、可远程控制
仅单台设备特有的配置 Thing实例 serialNumber、installDate、location

以一个具体配置为例。假设需要为某化工厂的32台离心泵建立模型,其中8台位于A线、12台位于B线、12台位于C线。建模过程如下:

1. 创建基模板 RotatingEquipmentTemplate
   - 属性:vibration (NUMBER, 默认0)、bearingTemperature (NUMBER, 默认25)
   - 服务:GetHealthIndex() → 返回 100 - vibration*2 - (bearingTemperature-25)*0.5
   - 事件:HealthDegraded(当 GetHealthIndex() < 60 时触发)

2. 创建子模板 CentrifugalPumpTemplate extends RotatingEquipmentTemplate
   - 新增属性:ratedFlow (NUMBER)、ratedHead (NUMBER)、npshRequired (NUMBER)
   - 新增服务:Priming()、Start()、Stop()
   - 新增事件:CavitationAlarm

3. 创建ThingShape MaintainableShape
   - 属性:lastMaintenanceDate (DATETIME)、maintenanceIntervalDays (INTEGER, 默认90)
   - 服务:ScheduleMaintenance(date)、GetNextMaintenanceDate()

4. 创建ThingShape EnergyMonitorShape
   - 属性:powerConsumption (NUMBER)、energyCost (NUMBER)
   - 服务:ResetEnergyCounter()

5. 为每台泵创建Thing实例,绑定 CentrifugalPumpTemplate
   并实现 MaintainableShape + EnergyMonitorShape
   实例级填写:serialNumber、location、ratedFlow、ratedHead

6. 验证:修改基模板中 vibration 的默认值,
   检查32台泵实例是否全部同步更新。

完成上述配置后,可以通过以下方式验证复用机制是否生效:在ThingWorx Composer中打开任意一台泵实例,查看其“Properties”面板是否同时包含模板继承的属性(vibration、ratedFlow)和Shape贡献的属性(lastMaintenanceDate、powerConsumption);在“Services”面板中确认GetHealthIndex()、ScheduleMaintenance()、ResetEnergyCounter()均可调用。若修改基模板的某个默认值后,所有实例的对应属性值自动变化,则说明继承链工作正常。

最后需要强调的是,ThingTemplate和ThingShape的复用机制之所以能避免重复建模,根本原因在于它们把“变化”和“不变”分离到了不同层级。设备类型之间的共性沉淀到模板继承链,跨类型的能力沉淀到ThingShape,只有真正因设备而异的参数才留在实例层。这种分层策略使得新增一台设备时,大部分建模工作已经在模板和Shape中完成,现场只需填写少量实例级参数即可投入使用。