4. 创建第一个腾讯云IoT产品与设备

在腾讯云物联网开发平台(IoT Explorer)中,设备接入的第一步不是写代码,而是把物理世界里的一个真实设备,在云端"登记"成平台可识别的数字身份。这个过程由四个动作组成:创建产品、定义物模型、注册设备、获取三元组。四者存在严格的先后依赖——没有产品就无法定义物模型,没有物模型就无法注册设备,没有设备就拿不到三元组。理解这条依赖链,比记住每个按钮的位置更重要。

产品:同一类设备的公共模板

产品(Product)是腾讯云IoT对"一类具有相同功能定义的设备"的抽象。例如你有一批型号相同的温湿度传感器,它们上报的数据字段、可下发的控制指令完全一致,那么它们共享同一个产品。产品本身不产生数据,它只是模板和容器。

创建产品时需要在控制台填写几个关键项:产品名称(如"教室温湿度监测器")、产品品类(选择"温湿度传感器"或自定义品类)、数据协议(默认"数据模板",即物模型方式)、认证方式(密钥认证或证书认证)。其中认证方式一旦选定,后续注册的设备都遵循该方式,密钥认证使用 DeviceSecret 做对称密钥签名,证书认证使用非对称密钥对,前者更简单、适合教学与快速验证,后者安全性更高。

创建完成后,平台会分配一个全局唯一的 ProductID,通常形如 ABCDE12345,由字母和数字组成,长度约 10 位。这个 ID 是产品级标识,同一产品下所有设备共用它。

物模型:把物理量翻译成云端可读的结构

物模型(Thing Model)是产品的"功能说明书",它用三类元素描述设备能力:

  • 属性(Property):设备的状态数据,可读可写,如温度、湿度、开关状态。
  • 事件(Event):设备主动上报的、有信息量的事情,如"高温告警""按键触发"。
  • 行为(Action):云端向设备下发的指令,如"重启""校准"。

以温湿度传感器为例,在控制台"物模型"页签中新增两个属性:温度 temperature,数据类型 float,取值范围 -40~80,单位 ℃,读写权限"只读";湿度 humidity,数据类型 float,取值范围 0~100,单位 %RH,只读。再新增一个事件 high_temp_alarm,包含一个输出参数 current_temp(float)。

物模型定义完成后,平台会自动生成该产品的 Topic 通信地址,例如属性上报 Topic 为:

$thing/up/property/{ProductID}/{DeviceName}

设备向这个 Topic 发布符合物模型格式的 JSON,云端就能自动解析出温度、湿度字段,而不需要你在服务端手写解析逻辑。这正是物模型的核心价值:把"字节流"变成"有语义的数据"。

注册设备与三元组

产品与物模型就绪后,进入"设备"页签点击"添加设备"。这里有两种方式:单个添加,或批量添加(填写数量,平台自动生成 DeviceName 序列)。单个添加时,你需要指定 DeviceName,例如 classroom_sensor_01。DeviceName 在产品内必须唯一,它是设备在平台内的"名字"。

注册成功后,平台为每台设备生成一个 DeviceSecret,通常是一串 32 位十六进制字符。至此,设备的三元组齐备:

要素示例值作用
ProductIDABCDE12345标识设备属于哪个产品
DeviceNameclassroom_sensor_01标识产品内的具体设备
DeviceSecreta1b2c3d4e5f6...(32位)设备身份密钥,用于签名认证
DeviceSecret 只在设备注册时完整显示一次,关闭页面后无法再次查看明文。若遗失,只能在控制台"重置密钥"重新生成,重置后旧密钥立即失效,已烧录旧密钥的设备将无法连接。因此拿到三元组后应立即安全保存。

设备身份认证机制

三元组不是简单地"填进代码就能连",它参与的是一个基于 MQTT 用户名密码 + HMAC-SHA1 签名的认证流程。腾讯云IoT要求设备在建立 MQTT 连接时提供:

  • ClientID:格式为 {ProductID}{DeviceName},例如 ABCDE12345classroom_sensor_01。
  • Username:格式为 {ProductID}{DeviceName};{SDKAppID};{connid};{timestamp},教学场景可简化为 {ProductID}{DeviceName};12010126;{connid};{timestamp}。
  • Password:由 DeviceSecret 对特定内容做 HMAC-SHA1 计算后得到的十六进制字符串。

签名的核心逻辑是:以 DeviceSecret 为密钥,对 {拼接内容} 做 HMAC-SHA1,再转十六进制。平台侧用同样的 DeviceSecret 和同样的算法重算一遍,若结果一致则认证通过。这意味着 DeviceSecret 从不直接在网络上传输,传输的只是它的签名结果,即使被截获也无法反推出密钥。

下面这张图展示了从控制台操作到设备认证的完整关系:产品与物模型构成模板层,设备注册产生三元组,三元组驱动签名计算,最终由平台校验决定连接是否放行。

模板层(控制台创建) 产品 Product ProductID: ABCDE12345 物模型 Thing Model 温度/湿度/高温告警 属性上报 Topic: $thing/up/property/{ProductID}/{DeviceName} 设备层(注册产生) 设备 Device DeviceName: classroom_sensor_01 DeviceSecret(32位十六进制,仅显示一次) a1b2c3d4e5f6...(示例) 依赖 三元组(设备身份) ProductID + DeviceName + DeviceSecret 设备端:签名计算 ClientID = ProductID + DeviceName Username = ProductID+DeviceName;...;timestamp Password = HMAC-SHA1(拼接内容, DeviceSecret) DeviceSecret 不直接传输,只传签名结果 平台端:认证校验 1. 用 ProductID+DeviceName 查设备 2. 取出该设备 DeviceSecret 3. 重算 HMAC-SHA1 并比对 一致 → 允许连接;不一致 → 拒绝 比对

一次完整的验证操作

拿到三元组后,最直接的验证方式是用 MQTT 客户端工具(如 MQTT.fx 或腾讯云提供的在线调试)发起连接。以密钥认证为例,在客户端中填入:

Broker地址: ABCDE12345.iotcloud.tencentdevices.com
端口: 1883(非加密)或 8883(TLS)
ClientID: ABCDE12345classroom_sensor_01
Username: ABCDE12345classroom_sensor_01;12010126;0;1735689600
Password: 由 DeviceSecret 经 HMAC-SHA1 计算得到的十六进制串

连接成功后,向属性上报 Topic 发布一条 JSON:

{
  "method": "report",
  "clientToken": "token-001",
  "params": {
    "temperature": 26.5,
    "humidity": 58.2
  }
}

此时回到控制台"设备"详情页的"设备日志"或"物模型数据"中,应能看到 temperature 与 humidity 两个字段被正确解析并显示最新值。如果连接被拒绝,优先检查三处:ClientID 是否为 ProductID 与 DeviceName 的直接拼接(中间无分隔符)、Username 中的 timestamp 是否在有效期内、Password 的签名内容与平台要求是否完全一致。这三处是初学者最常见的失败点。

建议在第一次成功连接后,立即把三元组写入设备的配置文件或安全存储区,并在代码中把 Broker 地址、ClientID 拼接规则、签名函数封装成独立模块。后续增加设备时,只需替换 DeviceName 与 DeviceSecret,其余逻辑完全复用——这正是"产品—物模型—设备"三层抽象带来的工程收益。

完成本节后,你应当能够独立在控制台走完"建产品 → 定物模型 → 注册设备 → 取三元组"的全过程,并说清 DeviceSecret 在认证中扮演的角色:它不是密码本身,而是生成密码的密钥;网络上流动的是签名,不是密钥。理解这一点,后续无论是用 SDK 接入还是排查连接失败,都能快速定位问题所在。