4、设备属性上报:属性定义(TSL模型)、使用Python SDK上报设备属性、属性上报的QoS策略
好,咱们进入第四章节。这一章讲的是设备属性上报,说白了就是设备怎么跟云端“说话”,告诉云端它现在是什么状态。
我刚开始做IoT项目的时候,觉得上报属性不就是发个数据嘛,有什么难的?后来踩了坑才发现,这里面的门道还真不少。尤其是TSL模型的定义,如果一开始没规划好,后面改起来那叫一个痛苦。
4.1 属性定义(TSL模型)
TSL模型,全称是Thing Specification Language,也就是物模型规范。你可以把它理解成设备与云端之间的一种“契约”。
举个例子,你有一个温度传感器,它会上报温度值。那这个温度值叫什么名字?是什么数据类型?取值范围是多少?这些都需要在TSL模型里定义清楚。
我个人习惯,在定义属性之前,先画一张表,把设备的所有功能点列出来。比如:
| 属性名称 | 标识符 | 数据类型 | 取值范围 | 读写类型 |
|---|---|---|---|---|
| 当前温度 | CurrentTemperature | float | -40 ~ 125 | 只读 |
| 当前湿度 | CurrentHumidity | float | 0 ~ 100 | 只读 |
| 设备开关 | PowerSwitch | bool | true/false | 读写 |
有了这张表,再去阿里云物联网平台创建TSL模型就清晰多了。平台支持两种方式:一种是直接在控制台可视化编辑,另一种是通过JSON文件导入。
我推荐你用JSON文件导入的方式,尤其是当设备属性比较多的时候。为什么呢?因为可视化编辑一个个点太慢了,而且容易出错。JSON文件可以批量定义,还能用脚本自动生成。
下面是一个简单的TSL属性定义JSON示例:
{
"schema": "https://iot-tsl.aliyun.com/schema/2.0",
"properties": [
{
"identifier": "CurrentTemperature",
"name": "当前温度",
"dataType": {
"type": "float",
"specs": {
"min": "-40",
"max": "125",
"step": "0.1"
}
},
"accessMode": "r",
"required": true
},
{
"identifier": "PowerSwitch",
"name": "设备开关",
"dataType": {
"type": "bool",
"specs": {
"0": "关闭",
"1": "开启"
}
},
"accessMode": "rw",
"required": false
}
]
}
这里要注意,accessMode字段决定了属性是只读(r)还是读写(rw)。只读属性设备只能上报,云端不能下发指令修改。读写属性则两边都可以操作。
4.2 使用Python SDK上报设备属性
模型定义好了,接下来就是写代码了。阿里云提供了Python SDK,叫alibabacloud-iot-device-sdk。安装很简单:
pip install alibabacloud-iot-device-sdk
嗯,这里要提醒一下,SDK的版本迭代比较快,建议你安装时指定版本号,避免后续接口变化导致代码跑不通。
下面是一个完整的属性上报示例:
from alibabacloud_iot_device_sdk.client import Client
import json
import time
# 设备认证信息
product_key = "你的ProductKey"
device_name = "你的DeviceName"
device_secret = "你的DeviceSecret"
# 初始化客户端
client = Client(product_key, device_name, device_secret)
# 连接到阿里云物联网平台
client.connect()
# 构造属性数据
properties = {
"CurrentTemperature": 25.6,
"CurrentHumidity": 68.3,
"PowerSwitch": 1
}
# 上报属性
payload = json.dumps(properties)
topic = f"/sys/{product_key}/{device_name}/thing/event/property/post"
# 发布消息
client.publish(topic, payload, qos=1)
print("属性上报成功")
# 断开连接
client.disconnect()
这段代码看起来简单,但我曾经在这个地方栽过跟头。你猜怎么着?我忘了把字典转成JSON字符串,直接传了个Python字典进去,结果平台一直收不到数据。排查了半天才发现是类型问题。
所以记住:上报的数据必须是JSON字符串格式。
另外,上报的Topic是固定的,格式为/sys/{productKey}/{deviceName}/thing/event/property/post。这个路径不能写错,否则数据发不上去。
/sys/{productKey}/{deviceName}/thing/event/property/post_reply。你可以订阅这个Topic来确认上报是否成功。
4.3 属性上报的QoS策略
QoS,全称是Quality of Service,服务质量等级。MQTT协议定义了三个等级:
- QoS 0:最多一次。消息发出去就不管了,不保证对方一定能收到。适合那些丢了也无所谓的数据,比如每秒上报一次的温度值。
- QoS 1:至少一次。消息会重试直到收到确认。适合那些不能丢的数据,比如设备开关状态。
- QoS 2:恰好一次。最可靠,但性能开销也最大。阿里云物联网平台目前不支持QoS 2。
我建议你根据业务场景来选择。举个例子:
如果你做的是环境监测,温度湿度每秒变化一次,用QoS 0就够了。就算偶尔丢一两条数据,下一秒钟又补上了,不影响整体趋势。
但如果你做的是智能门锁,门锁的开关状态必须准确上报,那就用QoS 1。我曾经遇到过一个项目,门锁状态用QoS 0上报,结果用户出门后APP上还显示“门未关”,吓得用户赶紧跑回家。其实门是关着的,只是那条状态消息丢了。
最后总结一下:
- TSL模型是设备与云端的“契约”,定义要清晰、粒度要细
- Python SDK上报属性时,记得用
json.dumps()转成字符串 - QoS策略根据业务场景选择,不重要的数据用QoS 0,重要的用QoS 1
下一章我们会讲设备事件上报,比属性上报稍微复杂一点,但原理是相通的。到时候我会分享一个我在智能家居项目里遇到的“幽灵事件”案例,很有意思。