Skip to content

3.7 物模型与设备抽象

3.7.1 物模型(Thing Model)概念与 Profile 实现

智能温室的温湿度传感器、仓储中的RFID读写器、车间里的振动监测仪——这些设备来自不同厂商,接口协议各异,上报的数据格式也完全不同。A公司的温度传感器以JSON格式上报 {"temp": 25.3, "unit": "C"},B公司的同类设备却用二进制报文,解析依赖一份300页的协议文档。搭建一套物联网平台,大量精力花在“翻译”这些设备数据上。只要接入一个新品牌、新型号的设备,就得重新写一遍适配代码。这种局面让异构设备之间的互操作变得极其昂贵,也拖慢了项目部署节奏。

解决这个问题的核心思路,是给每一类设备一张“能力卡片”——把它的数据类型、控制接口、能上报什么事件,统一用一种可被机器理解的描述语言写清楚。行业通常把这类能力描述称为物模型(Thing Model);IoT DC3 则以 Profile(模板)承载同类设备的能力定义。物模型描述设备类型的能力契约,与记录单个设备运行状态的“设备影子”(Device Shadow)并不是同一概念——影子是运行时的状态快照,物模型是永恒的能力蓝图。

物模型把同型号设备共有的属性、服务、事件聚合在一起,描述“这类设备能采什么、能控什么、会报什么”。 一个设备恰好归属一个物模型,多个设备可以复用同一个物模型。例如同一批100个温湿度传感器,共享同一个物模型定义——它们的基本能力一致,只是ID和当前数值不同。物模型不关心单台设备的瞬时状态,它只描述这类设备的可能行为。

图 3-13 物模型驱动设备互操作的示意图物模型的价值核心在于能力抽象:上层应用只与物模型交互,无需感知底层设备是Modbus RTU、MQTT还是二进制协议。图 3-13 物模型驱动设备互操作的示意图物模型的价值核心在于能力抽象:上层应用只与物模型交互,无需感知底层设备是Modbus RTU、MQTT还是二进制协议。应用消费域· 消费标准化能力的边界物模型抽象域· 将设备能力语义化,屏蔽底层差异物理设备域· 异构设备与协议的存在边界能源管理应用统一消费物模型数据楼宇自控应用不关心底层设备厂商属性汇聚属性 (Property)温度、湿度、功率服务 (Action)校准、重启、设定阈值事件 (Event)温度越界、设备离线温度传感器(A公司 · JSON)HTTP 上报温度传感器(B公司 · Modbus)RTU 寄存器振动监测仪(C公司 · MQTT)Topic 订阅RFID 读写器(D公司 · 二进制)Socket 报文温度温度振动频率读取标签标签碰撞统一输出 · 标准属性值标准属性值标准服务事件推送核心矛盾dev-ax4 与 dev-bx4 都代表温度属性,但因协议不同,应用层无法直接消费。统一抽象物模型层将两条数据流在temperature 属性节点统一,应用层不再接触底层协议。蓝色=物模型抽象层元素,统一色调表示标准化接口青绿/紫/琥珀=设备层元素,不同色相表示协议差异实线=能力映射与服务调用 · 虚线=事件推送粗箭头=温度属性汇聚后的统一输出图 3-13 物模型作为中间抽象层,将异构设备的能力映射到标准的属性、服务和事件,使上层应用可统一消费数据。
图 3-13 物模型驱动设备互操作的示意图

属性(Property)、服务(Service,在 DC3 中也称“指令”或“动作”)和事件(Event)是物模型的三个基本要素。属性是设备的状态值,可读可写或只读——例如一个温度传感器的当前温度、一个智能插座的开关状态、一个电池的电量百分比。服务是设备对外暴露的可执行操作,比如远程重启网关、校准传感器零点、设定报警阈值。事件是设备主动发出的信号,通常表示某种状态变化或异常,比如温度越界报警、设备离线通知、周期性的心跳。这三个要素的定义,本质上是把物理设备的行为抽象成一种可编程接口。应用层工程师只需知道“有一个属性叫temperature,我可以读取它的值”,而不需要知道这个温度值是从Modbus寄存器读出来的,还是通过I²C总线从芯片直接获取的。

主流的物模型标准各有侧重,但核心理念一致。W3C(万维网联盟)提出的 Web of Things (WoT) Thing Description (TD) 是较为成熟的开放规范,它把设备描述为一组属性(Property)、动作(Action)和事件(Event),支持通过JSON Schema定义输入输出数据模式、定义安全方案(OAuth2、PSK等)以及协议绑定(HTTP、CoAP、MQTT)。另一位重要的标准贡献者是 oneM2M,它面向蜂窝物联网场景,对资源模型、订阅与通知等操作做了更精细的定义,强调层级和语义的一致性。无论选用哪种标准,核心设计原则是一致的:把“设备能力”与“设备实现”剥离——物模型定义的是“能干什么”,而不是“怎么干”。这种抽象让应用层开发者只需关心属性值、服务调用和事件接收,无需理解底层是Modbus RTU还是CoAP协议。

在 IoT DC3 这类开源平台中,物模型概念被实际落地,称为 Profile。平台提供一组 RESTful API 来管理物模型:新增、更新、查询、删除。设备实例绑定其所属型号的 Profile,应用层访问设备时不再直面原始协议,而是通过 Profile 接口读取标准化后的属性值或触发服务。这正好呼应了本章开篇提出的感知层演进方向——从“采集数据”到“抽象能力”。物模型把物理世界的千差万别浓缩成一套可编程的接口,让应用层工程师可以像调用函数一样与物理设备交互,而不必理解每种传感器背后的通信细节。

一份 DC3 风格的 Profile 可以精简到十余行 JSON。以本章反复使用的温度传感器为例,其最小骨架如下:

json
{
  "name": "无线温度传感器 T-100",
  "description": "冷链仓储电池供电温度传感器,精度 ±0.1℃",
  "properties": [
    { "name": "currentTemperature", "type": "double", "unit": "℃", "accessMode": "r" },
    { "name": "maxAlarmThreshold", "type": "double", "unit": "℃", "accessMode": "rw" }
  ],
  "services": [
    { "name": "calibrateSensor", "invocation": "async", "input": { "referenceTemperature": "double" } }
  ],
  "events": [
    { "name": "overTemperatureAlarm", "data": { "currentTemperature": "double", "timestamp": "string" } }
  ]
}

与 W3C WoT TD 对照着看更清楚:两者表达的是同一份能力契约——Profile 的属性对应 TD 的 properties,服务对应 actions,事件对应 events。差别在详略:WoT TD 用 @context、forms、security 等字段承载语义标注、协议绑定与安全方案,面向跨平台互操作;DC3 Profile 面向平台内部管理,只保留最小必需字段——属性即位号,服务即平台可下发的指令,事件对接告警通道。invocation: "async" 标注服务的异步调用模式,这一点在 3.7.2 节还会展开。

物模型并非锦上添花的工作。没有它,平台接入每一个新设备品类都像在解一道新的谜题;有了它,设备接入变成填表——厂商只需把自己的设备能力映射到已有的物模型模板上,或者为新型号新增一个模板。这正是规模化部署物联网系统的工程基石:将互操作成本从“逐设备定制”降低到“一次建模、无限复用”。上面只给出了 Profile 的最小骨架,一份完整的物模型文档在工程上还有哪些设计考量?第3.7.2节将用一个具体的温度传感器示例,演示如何定义一份Profile JSON文档。至于物模型如何作为AI Agent与物理世界交互的接口,我们将在第7章AIoT与智能体应用中深入探讨。

3.7.2 物模型设计示例:温度传感器

直接上手,为一种常见的物联网设备——温度传感器——定义物模型。这能让你直观地看到上一节的概念如何落地。

假设你负责为一款冷链仓储用的无线温度传感器 Model-T-100 设计物模型。它每30秒上报一次温度,精度0.1℃,支持远程校准,当温度超出预设范围时主动上报报警。这个场景很适合演示物模型的核心结构。

属性、服务、事件:一张设备能力卡片

物模型本质上是一张“设备能力卡片”。参考业界主流的 W3C Web of Things Thing Description (WoT TD) 规范,以及 IoT DC3 中对物模型的定义方式,这张卡片需要描述三种类型的能力:

  • 属性(Properties):设备可以被读取或设置的状态变量。比如 当前温度(只读)、温度上下限阈值(可写)。
  • 服务(Services):设备能执行的远程操作。比如 校准传感器恢复出厂设置。它们往往是一个过程,可能耗时较长,并返回执行结果。
  • 事件(Events):设备主动发出的消息,用于通知某个条件被触发。比如 温度越界报警,一旦传感器数值越界,就立刻向平台推送一条消息。

物模型的价值在于:它将设备千差万别的能力,用这三类标准接口统一定义成机器可解析的模板。平台开发者只需读懂这个模板,就能和任意符合该模板的设备进行交互,而无需关心它的硬件差异。

下面用 JSON(JavaScript Object Notation)格式(基于 W3C WoT TD 的核心结构并做简化)为 Model-T-100 编写物模型:

json
{
  "@context": "https://www.w3.org/2019/wot/td/v1",
  "id": "urn:dev:profile:temperature-sensor:t-100:v1",
  "title": "Wireless Temperature Sensor T-100",
  "description": "A battery-powered temperature sensor for cold chain monitoring, accuracy ±0.1°C.",
  "@type": "TemperatureSensor",

  "properties": {
    "currentTemperature": {
      "title": "Current Temperature",
      "type": "number",
      "unit": "celsius",
      "readOnly": true,
      "minimum": -40,
      "maximum": 85
    },
    "minAlarmThreshold": {
      "title": "Minimum Alarm Threshold",
      "type": "number",
      "unit": "celsius",
      "readOnly": false,
      "minimum": -40,
      "maximum": 85
    },
    "maxAlarmThreshold": {
      "title": "Maximum Alarm Threshold",
      "type": "number",
      "unit": "celsius",
      "readOnly": false,
      "minimum": -40,
      "maximum": 85
    },
    "batteryLevel": {
      "title": "Battery Level",
      "type": "integer",
      "unit": "percent",
      "readOnly": true,
      "minimum": 0,
      "maximum": 100
    }
  },

  "actions": {
    "calibrateSensor": {
      "title": "Calibrate Sensor",
      "description": "One-point calibration using a reference temperature. The device compares its reading with the provided value and adjusts the offset.",
      "input": {
        "type": "object",
        "properties": { "referenceTemperature": { "type": "number" } },
        "required": ["referenceTemperature"]
      },
      "output": {
        "type": "object",
        "properties": {
          "status": { "type": "string", "enum": ["success", "failure"] },
          "adjustedOffset": { "type": "number" }
        }
      }
    },
    "resetToFactory": {
      "title": "Reset to Factory Defaults",
      "input": { "type": "null" },
      "output": {
        "type": "object",
        "properties": { "status": { "type": "string", "enum": ["success", "failure"] } }
      }
    }
  },

  "events": {
    "overTemperatureAlarm": {
      "title": "Over-Temperature Alarm",
      "data": {
        "type": "object",
        "properties": {
          "currentTemperature": { "type": "number" },
          "thresholdValue": { "type": "number" },
          "timestamp": { "type": "string", "format": "date-time" }
        }
      }
    },
    "underTemperatureAlarm": {
      "title": "Under-Temperature Alarm",
      "data": {
        "type": "object",
        "properties": {
          "currentTemperature": { "type": "number" },
          "thresholdValue": { "type": "number" },
          "timestamp": { "type": "string", "format": "date-time" }
        }
      }
    }
  },

  "links": {
    "properties": "mqtt://broker.iot.example.com/devices/t-100-001/properties",
    "actions": "mqtt://broker.iot.example.com/devices/t-100-001/actions",
    "events": "mqtt://broker.iot.example.com/devices/t-100-001/events"
  }
}

这个 JSON 文件清晰定义了:

  • 这台传感器有 4 个属性,其中 currentTemperaturebatteryLevel 是只读的,两个报警阈值是可写的。平台可以通过修改这些属性来改变设备的行为。
  • 它支持 2 个服务:calibrateSensor 需要输入一个参考温度,并返回校准结果;resetToFactory 不需要输入,执行后返回状态。
  • 它能主动上报 2 个事件:温度过高或过低报警。每个事件携带当时的温度值、阈值和时间戳。

下面这张图展示了物模型作为模板与设备实例之间的关系,以及三类能力在平台侧的交互模式。

图 3-14 物模型与设备实例的关系:属性、动作、事件的交互模式一份物模型模板被多台设备复用,设备与平台间通过属性上报、动作下发、事件推送三类接口交互。图 3-14 物模型与设备实例的关系:属性、动作、事件的交互模式一份物模型模板被多台设备复用,设备与平台间通过属性上报、动作下发、事件推送三类接口交互。智能决策域设备与边缘域数据资产域平台服务域治理域复用复用上报属性值上报属性值下发动作下发动作推送事件推送事件Model-T-100 物模型设备A设备B数据存储远程控制告警服务symbols=dashed-line=复用/模板关系图 3-14 物模型作为模板被多个设备实例复用,设备通过标准的三类接口与平台应用通信。平台无需关心设备内部差异,只需按照物模型定义的数据格式和协议进行交互。
图 3-14 物模型与设备实例的关系:属性、动作、事件的交互模式

工程权衡:设计时的三个决策点

上面示例看起来直接,但实际项目中,以下几个权衡需要仔细考虑。

1. 属性粒度的取舍

是把每个阈值单独作为一个属性,还是把所有配置项合并成一个 JSON 对象属性?示例中 minAlarmThresholdmaxAlarmThreshold 分开定义,好处是平台可以单独修改其中一个,不用读写整个配置对象。如果配置项非常多(比如十几个),单独定义会导致属性列表过长,这时可以考虑用复合属性(如 alarmConfig,类型为 object)来管理。关键在于:频率高的读写操作应使用细粒度属性,低频的批量配置则适合复合属性。

2. 服务的同步与异步

示例中的 calibrateSensor 既有输入也有输出,看起来是同步的。但在许多 IoT 场景下,执行一个服务可能需要几秒甚至更久,设备无法实时返回结果。IoT DC3 中的指令模型采用异步设计:平台下发指令后,设备在另一个独立的信道上回复执行结果。设计服务时,必须明确标注它的调用模式。可以在 actions 定义里增加一个扩展字段,如 "invocation": "async",并说明超时时间和回调机制。

3. 事件的数据载荷

越界报警事件携带了 currentTemperaturethresholdValuetimestamp 三个字段。如果事件携带太多数据,会增加网络开销和平台负载。需要判断哪些是下游告警系统必须立即知晓的,哪些可以放到后续的接口中补充查询。例如,报警事件可以只携带 deviceIdeventType 和时间戳,详细的温度趋势数据设备可以缓存在本地,待平台后续通过属性拉取。这是一个典型的带宽 vs 实时性的权衡。

从物模型到平台交互

物模型定义一旦完成,平台就可以根据它自动生成数据存储模型、API 接口和 UI 控件。IoT DC3 提供了对应的 /profile API 来管理物模型(新增、查询、删除等)。设备接入时,只需要声明自己所属的物模型 ID(如 urn:dev:profile:temperature-sensor:t-100:v1),平台内部就自动知道该设备有哪些属性、支持哪些服务、能上报哪些事件,无需额外适配代码。设计物模型不是在描述“某一个设备此刻的状态”,而是在定义“这类设备能做的一切”。一个设计良好的物模型,能让上层应用开发变得更简单,也能让平台在接入新型号设备时,只需要解析一张新的“能力卡片”,而不是重写一套适配代码。这个思路,在下一节跨平台数据集成中会体现得更加明显。

至于物模型如何被上层 AI Agent 调用,我们将在第7章深入讨论。

3.7.3 物模型在数据互通中的实践

上一节为温度传感器定义了属性、服务、事件的能力卡片,一个型号的设备有了统一描述。但在真实项目中,很少有只接一种设备的情况:A 厂的温湿度变送器走 Modbus RTU,温度数据在第 3–4 字节以十六进制表达;B 厂的空调控制器用 KNX 总线,温度设定值对应一个通讯对象号;C 厂的智能电表遵循 DL/T645 协议,数据标识符层层嵌套。每个新品牌接入,应用团队都要学习私有协议、编写解析代码、反复调试位号映射。物模型真正要解决的核心问题,就是这套“异构数据归一”——让来源各异的物理量汇入同一个语义空间。

物模型在数据互通中扮演三层工程角色。

语义适配层消弭协议鸿沟。 物模型将设备能力抽象为属性(Property,即位号值,point value)、服务(Service)和事件(Event)三类,这与 W3C Web of Things Thing Description 对设备能力分类的逻辑相似。A 厂传感器输出十六进制帧“00 64”,适配层将两字节按大端拼接为 0x0064,即十进制 100,再乘以 0.1 的系数字段,得到 10.0℃;B 厂空调的 KNX 数据点“9.001”表达的也是标准浮点温度值。通过物模型,这两者的“温度”属性归入同一个位号。上层应用读取温度值时,完全不需要知道原始数据来自 Modbus 寄存器、KNX 通讯对象还是 DL/T645 数据标识符。这个适配过程通常在边缘网关或设备驱动层一次性实现,后续同型号设备接入复用同一套映射,无需重复编码。

设备影子(Device Shadow)拆解同步耦合。 物联网设备往往存在离线时刻——低功耗节点大部分时间休眠,或现场网络抖动导致连接断开。如果每次下发指令都要等待设备在线,业务流程会被拖死。设备影子就是缓冲区:平台持有设备的最新物模型状态,应用层对影子的某个属性(如“设定温度”)进行写操作,影子记录期望值;设备下次上线时主动拉取影子中的期望值,与当前状态对比,发现差异就执行同步。写操作不再被设备在线状况阻塞,同步问题转化为异步状态管理。这是物模型在平台解耦中最直接的工程收益——应用不感知设备在线状态,设备不感知应用调用时序。

降低应用对协议的耦合。 假设一套楼宇能源优化策略需要读取各层送风温度。若不同设备映射到兼容的物模型,核心计算可以复用;但单位、精度、采样周期、质量标记和可写范围仍可能不同,部署前必须做契约与现场验证。物模型减少协议适配代码,并不会让业务逻辑与基础设施“彻底解耦”。

用一个流程可以更直观地理解这种数据互通:温度传感器上报原始报文 → 边缘网关上的物模型适配器解析出“温度=25.3℃,湿度=60.2%RH”并更新设备影子 → 云平台应用通过同一物模型读取影子中的属性值。整个过程应用不接触任何私有通信细节,数据从感知层一路带着清晰的语义标签向上传递。实时监控面板、告警规则、能源报表都能在这个统一的语义空间里直接对话,不需要为每个厂商的私有格式单独处理。在 IoT DC3 这类平台中,物模型通过 /profile 系列的 REST API 管理,遵循“一个设备归属一个物模型,多个同型号设备复用一个物模型”的设计原则,将适配层逻辑集成到设备接入模块,让物模型成为整个数据流动的语义锚点。当后续 AI 层需要调用设备能力时,它同样通过物模型读写属性、调用服务,而不必重复处理协议碎片——这是从感知层到智能层实现统一数据模型的关键工程基础。

图 3-15 物模型在数据互通中的三层角色物模型把异构协议归一为统一语义空间,设备影子拆解同步耦合,催生平台无关应用。图 3-15 物模型在数据互通中的三层角色让来源各异的物理量汇入同一个语义空间语义适配层:消弭协议鸿沟A 厂温湿度变送器Modbus RTU温度在第 3~4 字节十六进制表达“01 0A” → 高字节×0.1 = 10.0℃B 厂空调控制器KNX 总线温度设定值对应通讯对象号KNX 数据点“9.001”C 厂智能电表DL/T645 协议数据标识符层层嵌套私有协议需逐个解析统一物模型(语义空间)属性(Property)· 服务(Service)· 事件(Event)三者的“温度”归入同一位号适配逻辑集成到设备接入模块,复用同一套映射设备影子:拆解同步耦合平台持有设备最新物模型状态,应用写影子属性记录期望值,设备下次上线拉取影子对比差异并同步写操作不再被设备在线状况阻塞,同步问题转化为异步状态管理应用不感知设备在线状态,设备不感知应用调用时序低功耗节点休眠或网络抖动时,业务流程不会被拖死催生平台无关的应用开发同一物模型下,楼宇能源优化策略在 BACnet / Modbus / 自定义总线环境都能直接复用开发只依赖物模型属性与服务,不关心设备品牌或总线类型,业务逻辑与基础设施彻底解耦实时监控面板、告警规则、能源报表在统一语义空间直接对话,AI 层同样通过物模型读写能力IoT DC3 经 /profile 系列 REST API 管理物模型:一设备一物模型,多同型号设备复用一个物模型图 3-15 物模型三层角色:语义适配层把 Modbus/KNX/DL/T645 异构数据归一,设备影子拆解同步耦合,平台无关应用实现一次编写多处部署,成为从感知层到智能层的数据语义锚点。
图 3-15 物模型在数据互通中的三层角色

从工业软件到 AI 智能体 · 构建面向智能体演进的多协议、云原生、开源工业物联网平台