4、设备侧SDK集成(Mqtt方式):基于华为云IoT Device SDK(Java/Python),实现设备端MQTT连接、属性上报与命令响应
好,咱们进入实战环节的核心部分——设备侧SDK集成。
前面几章我们把平台侧的准备工作和注册流程都捋了一遍。现在,该让真正的设备“开口说话”了。我个人习惯用华为云IoT Device SDK来做这件事,因为它把底层的MQTT协议细节封装得比较干净,我们只需要关注业务逻辑就行。
这一章,我会分别用Java和Python两个版本,带你走通“连接-上报-响应”这条完整链路。你想想看,设备接入物联网平台,本质上就这三件事:连得上、发得出去、听得懂指令。
4.1 准备工作:SDK获取与工程搭建
在写代码之前,先把环境搭好。华为云IoT Device SDK在GitHub上开源,你直接去搜“huaweicloud-iot-device-sdk”就能找到。
Java版本(Maven依赖):
<dependency>
<groupId>com.huaweicloud.iot</groupId>
<artifactId>iot-device-sdk-java</artifactId>
<version>1.2.0</version>
</dependency>
Python版本(pip安装):
pip install huaweicloud-iot-device-sdk-python
嗯,这里要注意一点:Python SDK目前对Python 3.7+支持得比较好。我曾经在Python 3.6的环境上踩过坑,有个异步回调的库不兼容,折腾了半天。所以建议你直接用Python 3.8或3.9,省心。
4.2 设备端MQTT连接:从“离线”到“在线”
设备要跟平台通信,第一步就是建立MQTT连接。连接时需要四个关键参数:设备ID、设备密钥、平台地址、端口号。这些信息你在上一章注册设备时应该已经拿到了。
Java示例代码:
// 初始化设备
IoTDevice device = new IoTDevice("ssl://iot-mqtts.cn-north-4.myhuaweicloud.com:8883",
"5e1a7c3d2f8b_my_device", // 设备ID
"my_secret_key", // 设备密钥
new DefaultDeviceShadowListener());
// 建立连接
if (device.init() == 0) {
System.out.println("设备连接成功!");
} else {
System.out.println("设备连接失败,请检查参数。");
}
Python示例代码:
from huaweicloud_iot_device_sdk import IoTDevice
device = IoTDevice(
server_uri="ssl://iot-mqtts.cn-north-4.myhuaweicloud.com:8883",
device_id="5e1a7c3d2f8b_my_device",
secret="my_secret_key"
)
# 建立连接
if device.connect() == 0:
print("设备连接成功!")
else:
print("设备连接失败,请检查参数。")
连接成功后,SDK会自动维护心跳保活。你不需要自己写心跳包,SDK默认每120秒发一次PINGREQ。如果你觉得这个间隔不合适,可以在初始化时通过setKeepAliveInterval()方法调整。
4.3 属性上报:让平台知道设备的状态
设备连上来了,总得干点正事。属性上报,说白了就是把传感器数据或者设备状态告诉平台。比如温度、湿度、开关状态这些。
华为云IoT的属性上报,走的是系统预置的Topic:$oc/devices/{device_id}/sys/properties/report。SDK已经帮你封装好了,直接调用接口就行。
Java示例代码:
// 构造属性数据
Map<String, Object> properties = new HashMap<>();
properties.put("temperature", 25.6);
properties.put("humidity", 68.3);
properties.put("switch", 1);
// 上报属性
int result = device.getClient().reportProperties(properties);
if (result == 0) {
System.out.println("属性上报成功!");
} else {
System.out.println("属性上报失败,错误码:" + result);
}
Python示例代码:
# 构造属性数据
properties = {
"temperature": 25.6,
"humidity": 68.3,
"switch": 1
}
# 上报属性
result = device.report_properties(properties)
if result == 0:
print("属性上报成功!")
else:
print("属性上报失败,错误码:", result)
上报频率怎么控制?我个人建议,对于变化不明显的属性(比如室温),每30秒到1分钟上报一次就够了。对于变化快的(比如电机转速),可以缩短到5秒。但别太频繁,否则平台会限流,而且设备功耗也会上去。
4.4 命令响应:听平台的指令,做该做的事
设备不光要“说”,还得会“听”。平台下发命令时,设备需要及时响应。比如远程开关灯、调整温度设定值这些。
命令的收发也是走系统Topic:$oc/devices/{device_id}/sys/commands/request_id={request_id}。SDK提供了监听器机制,你只需要注册一个回调函数就行。
Java示例代码:
// 注册命令监听器
device.getClient().setCommandListener(new CommandListener() {
@Override
public void onCommand(String requestId, String serviceId, String commandName, Map<String, Object> paras) {
System.out.println("收到命令:" + commandName);
System.out.println("参数:" + paras.toString());
// 处理命令,比如控制GPIO
if ("setSwitch".equals(commandName)) {
int switchState = (int) paras.get("switch");
// 这里写控制硬件的代码...
System.out.println("开关状态已设置为:" + switchState);
}
// 响应平台,告诉它命令执行成功
device.getClient().respondCommand(requestId, 0, "命令执行成功");
}
});
Python示例代码:
# 定义命令处理函数
def on_command(request_id, service_id, command_name, paras):
print("收到命令:", command_name)
print("参数:", paras)
# 处理命令
if command_name == "setSwitch":
switch_state = paras.get("switch")
# 这里写控制硬件的代码...
print("开关状态已设置为:", switch_state)
# 响应平台
device.respond_command(request_id, 0, "命令执行成功")
# 注册命令监听器
device.set_command_listener(on_command)
命令的requestId是平台生成的唯一标识,你响应时必须原样返回。这样平台才能把响应跟具体的命令请求匹配上。说白了,这就是个“对账”的过程。
4.5 完整流程串讲:一个Demo跑通全链路
好,我们把上面三部分串起来,写一个完整的Demo。这个Demo做的事情很简单:设备连接平台后,每10秒上报一次温度和湿度;同时监听平台下发的开关命令,收到后打印日志并响应。
Java完整Demo核心逻辑:
public class DeviceDemo {
public static void main(String[] args) {
IoTDevice device = new IoTDevice("ssl://iot-mqtts.cn-north-4.myhuaweicloud.com:8883",
"5e1a7c3d2f8b_demo_device", "demo_secret",
new DefaultDeviceShadowListener());
if (device.init() != 0) {
System.out.println("连接失败,退出程序");
return;
}
// 注册命令监听
device.getClient().setCommandListener((requestId, serviceId, commandName, paras) -> {
System.out.println("收到命令:" + commandName);
device.getClient().respondCommand(requestId, 0, "ok");
});
// 定时上报属性
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
Map<String, Object> props = new HashMap<>();
props.put("temperature", 25.0 + Math.random() * 5);
props.put("humidity", 60.0 + Math.random() * 10);
device.getClient().reportProperties(props);
System.out.println("属性已上报");
}, 0, 10, TimeUnit.SECONDS);
}
}
Python完整Demo核心逻辑:
import time
import random
from huaweicloud_iot_device_sdk import IoTDevice
device = IoTDevice(
server_uri="ssl://iot-mqtts.cn-north-4.myhuaweicloud.com:8883",
device_id="5e1a7c3d2f8b_demo_device",
secret="demo_secret"
)
if device.connect() != 0:
print("连接失败,退出程序")
exit(1)
# 注册命令监听
def on_command(request_id, service_id, command_name, paras):
print("收到命令:", command_name)
device.respond_command(request_id, 0, "ok")
device.set_command_listener(on_command)
# 定时上报属性
while True:
props = {
"temperature": round(25.0 + random.random() * 5, 1),
"humidity": round(60.0 + random.random() * 10, 1)
}
device.report_properties(props)
print("属性已上报")
time.sleep(10)
嗯,这一章的内容就到这里。下一章我们会聊聊设备分组管理,看看怎么把成百上千的设备管得井井有条。到时候见。