官网上假设的一个智能家居场景,结合腾讯云物联网通信设备端 IoT Hub JAVA-SDK 体验基于设备间的消息和规则引擎实现设备之间的联动。请参考官网 场景一:设备互通
体验设备互通,需要按照官网文档中创建两类智能设备(Door、AirConditioner)。 还需要配置规则引擎,请参考官网 规则引擎概述 一章 , 将 数据转发到另一Topic。
示例代码及源码在 hub-device-java 的module下。
本示例使用的开发环境如下:
- 操作系统:macOS
- JDK版本:JDK13
- 集成开发环境:IntelliJ IDEA CE
示例工程中使用的是源码依赖,也可以在maven中添加依赖,请参考 README-工程配置
Door模型在SDK Demo示例中对应的是 Door.java 文件,需要填好该文件中对应的参数。
public class Door {
private static final String PRODUCT_ID = "YOUR_PRODUCT_ID"; //产品ID
private static final String DEVICE_NAME = "YOUR_DEVICE_NAME"; //设备名称
private static final String SECRET_KEY = "YOUR_SECRET_KEY"; //设备密钥(密钥认证)
private static final String DEVICE_CERT_NAME = "YOUR_DEVICE_NAME_cert.crt"; //设备证书文件名称(证书认证)
private static final String DEVICE_KEY_NAME = "YOUR_DEVICE_NAME_private.key"; //设备私钥文件名称(证书认证)
}
Airconditioner模型在SDK Demo示例中对应的是 Airconditioner.java 文件,需要填好该文件中对应的参数。
public class Airconditioner {
private static final String PRODUCT_ID = "YOUR_PRODUCT_ID"; //产品ID
protected static final String DEVICE_NAME = "YOUR_DEVICE_NAME"; //设备名称
private static final String SECRET_KEY = "YOUR_SECRET_KEY"; //设备密钥(密钥认证)
private static final String DEVICE_CERT_NAME = "YOUR_DEVICE_NAME_cert.crt"; //设备证书文件名称(证书认证)
private static final String DEVICE_KEY_NAME = "YOUR_DEVICE_NAME_private.key"; //设备私钥文件名称(证书认证)
}
当 MQTT 认证方式为密钥认证时,在 MqttConnectOptions 中不需要做 SSL 配置,走TCP,当您使用的sdk版本为3.3.0及以下时,密钥认证需要在 MqttOptions 中做 SSL 配置 options.setSocketFactory(AsymcSslUtils.getSocketFactory());
当 MQTT 认证方式为证书认证时,在 MqttConnectOptions 中添加 SSL 配置 options.setSocketFactory(AsymcSslUtils.getSocketFactoryByAssetsFile(mContext, DEVICE_CERT_NAME, DEVICE_KEY_NAME));
运行 DeviceInterworkingApp.java ,初始化Airconditioner,将 Airconditioner 进行 MQTT 认证连接,认证连接通过后就订阅自身 Topic ${productId}/${deviceName}/control
。示例代码如下:
public static void main(String[] args) {
mAir = new Airconditioner(new AirconditionerMqttActionCallBack()); // 初始化Airconditioner实例,会进行 MQTT 认证连接,设置 MQTT 回调
mDoor = new Door(); // 初始化Door实例,不会进行 MQTT 认证连接
}
private static class AirconditionerMqttActionCallBack extends TXMqttActionCallBack {
@Override
public void onConnectCompleted(Status status, boolean reconnect, Object userContext, String msg) { // MQTT 认证连接完成
if (status.equals(Status.OK)) {
mAir.subScribeTopic(); // 订阅自身 Topic
}
}
...
@Override
public void onMessageReceived(String topic, MqttMessage message) { // 收到来自云端的消息
String logInfo = String.format("Airconditioner onMessageReceived, topic[%s], message[%s]", topic, message.toString());
System.out.println(logInfo);
if (message.toString().contains("come_home")) {
logInfo = "receive command: open airconditioner ";
} else {
logInfo = "receive command: close airconditioner ";
}
System.out.println(logInfo);
}
}
观察Logcat日志。
TXMqttConnection connect 297 - Start connecting to ssl://XMN6AZ4M0Y.iotcloud.tencentdevices.com:8883
[MQTT Call: XMN6AZ4M0YairConditioner1] INFO TXMqttConnection onSuccess 268 - onSuccess!
connected to ssl://XMN6AZ4M0Y.iotcloud.tencentdevices.com:8883
TXMqttConnection subscribe 633 - Starting subscribe topic: XMN6AZ4M0Y/airConditioner1/control
onSubscribeCompleted, status[OK], message[subscribe success]
以上日志为 Airconditioner 设备 MQTT 已连接 成功,订阅自身 Topic 成功,观察控制台中创建的 Airconditioner 设备的状态已更改为上线。
Door 实例调用 enterRoom 方法,会进行 MQTT 认证连接,连接成功后发布自身 Topic:${productId}/${deviceName}/event
,由于配置了规则引擎将数据转发,将会由云端规则引擎转发 Topic 消息给到 Airconditioner 设备。示例代码如下:
public void enterRoom() {
...
mqttConnection = new TXMqttConnection(PRODUCT_ID, DEVICE_NAME, SECRET_KEY, new DoorMqttActionCallBack());
mqttConnection.connect(options, null);
...
if (mqttConnection.getConnectStatus().equals(TXMqttConstants.ConnectStatus.kConnected)) { // 如果已经连接状态,就直接发布自身 Topic
...
mqttConnection.publish(topic, message, null);
}
...
}
private class DoorMqttActionCallBack extends TXMqttActionCallBack {
@Override
public void onConnectCompleted(Status status, boolean reconnect, Object userContext, String msg) { // MQTT 认证连接完成
if (status.equals(Status.OK)) { // 连接成功
if (!reconnect) { // 不是重连 就发布自身 Topic
MqttMessage message = new MqttMessage();
message.setPayload(COME_HOME_MESSAGE.getBytes());
String topic = String.format("%s/%s/%s", PRODUCT_ID, DEVICE_NAME, "event");
mqttConnection.publish(topic, message, null);
}
}
}
...
}
观察Logcat日志。
TXMqttConnection connect 297 - Start connecting to ssl://9RW4A8OOFK.iotcloud.tencentdevices.com:8883
[MQTT Call: 9RW4A8OOFKdoor1] INFO TXMqttConnection onSuccess 268 - onSuccess!
TXMqttConnection publish 451 - Starting publish topic: 9RW4A8OOFK/door1/event Message: {"action": "come_home", "targetDevice": "airConditioner1"}
Airconditioner onMessageReceived, topic[XMN6AZ4M0Y/airConditioner1/control], message[{"action":"come_home","targetDevice":"airConditioner1"}]
receive command: open airconditioner
以上日志为 Door 设备 MQTT 已连接 成功,Door 设备发布自身 Topic ,并携带了 action 为 come_home 的 message 消息,之后 Airconditioner 设备也接收到了由云端规则引擎转发来的 Topic 进门回家的消息,至此实现进门打开空调设备的目的。
Door 实例调用 leaveRoom 方法,将会触发 Door 设备发布自身 Topic:${productId}/${deviceName}/event
,由于配置了规则引擎将数据转发,将会由云端规则引擎转发 Topic 消息给到 Airconditioner 设备, Door 设备断开 MQTT 连接。示例代码如下:
public void leaveRoom() {
...
MqttMessage message = new MqttMessage();
message.setPayload(LEAVE_HOME_MESSAGE.getBytes());
String topic = String.format("%s/%s/%s", PRODUCT_ID, DEVICE_NAME, "event");
mqttConnection.publish(topic, message, null); // 发布自身 Topic 携带 LEAVE_HOME_MESSAGE(leave_home) 的消息
closeConnection(); // 关闭 Door 设备的 MQTT 连接
}
观察Logcat日志。
TXMqttConnection publish 451 - Starting publish topic: 9RW4A8OOFK/door1/event Message: {"action": "leave_home", "targetDevice": "airConditioner1"}
Airconditioner onMessageReceived, topic[XMN6AZ4M0Y/airConditioner1/control], message[{"action":"leave_home","targetDevice":"airConditioner1"}]
receive command: close airconditioner
以上日志为 Door 设备发布订阅自身 Topic ,并携带了 action 为 leave_home 的 message 消息并断开 MQTT 连接,之后 Airconditioner 设备也接收到了由云端规则引擎转发来的 Topic 出门离开了的消息,至此实现出门关闭空调设备的目的。