基于云云对接SDK,通过桥接服务,可将设备接入阿里云物联网平台,实现设备与物联网平台通信。本文介绍如何配置云云对接SDK,实现设备上下线和消息上下行等基础能力。
获取SDK
物联网平台提供了云云对接SDK的Demo,具体内容,请参见alibabacloud-iot-bridge-core-demo。
流程图
使用云云对接SDK,桥接设备与物联网平台的整体流程图如下。
部署开发环境
部署Java SDK开发环境,并添加云云对接SDK的项目Maven依赖。
<dependency>
<groupId>com.aliyun.openservices</groupId>
<artifactId>iot-as-bridge-sdk-core</artifactId>
<version>2.4.1</version>
</dependency>
初始化
初始化SDK
创建BridgeBootstrap对象实例,调用bootstrap方法,在该方法中,向云云对接SDK注册一个DownlinkChannelHandler回调,用于接收物联网平台下行消息。
完成SDK初始化后,SDK会读取网桥设备信息,并向物联网平台发起网桥设备上线请求等。
代码示例:
BridgeBootstrap bridgeBootstrap = new BridgeBootstrap();
bridgeBootstrap.bootstrap(new DownlinkChannelHandler() {
@Override
public boolean pushToDevice(Session session, String topic, byte[] payload) {
//接收物联网平台下行消息。
String content = new String(bytes);
log.info("Get DownLink message, session:{}, {}, {}", session, topic, content);
return true;
}
@Override
public boolean broadcast(String topic, byte[] payload) {
return false;
}
});
配置网桥设备信息
默认使用配置文件方式:从Java工程默认资源文件路径src/main/resources/下读取配置文件application.conf,格式为HOCON(JSON超集)。
云云对接SDK使用typesafe.config解析配置文件。
配置方法:动态注册网桥设备和指定网桥设备。
动态注册网桥设备的配置,请参见动态创建网桥设备。指定网桥设备的配置如下。
参数
是否必需
说明
productKey
是
网桥设备所属产品的ProductKey。
deviceName
是
网桥设备的DeviceName。
deviceSecret
是
网桥设备的DeviceSecret。
subDeviceConnectMode
否
网桥挂载设备模式:
大型网桥:传入3,单网桥下最大支持挂载500,000个设备。
小型网桥:不传入,单网桥下最大支持挂载1,500个设备。
大型网桥、小型网桥的挂载设备下线策略不同,请参见设备下线。
http2Endpoint
是
HTTP2网关服务地址。网桥设备和物联网平台通过HTTP2协议建立长连接通道。
地址结构:
企业版实例:
https://${IotInstanceId}.http2.iothub.aliyuncs.com:443
。其中,变量${IotInstanceId}需替换成实例ID。
例如:某用户的企业版实例的实例ID为iot-cn-g06kwb****,地址为
https://iot-cn-g06kwb****.http2.iothub.aliyuncs.com:443
。公共实例:新旧版公共实例的地址填写格式不同。
新版公共实例:与企业版实例填写格式一致。
旧版公共实例:
https://${productKey}.iot-as-http2.${RegionId}.aliyuncs.com:443
。其中,变量${productKey}需替换成您的网桥设备所属产品的ProductKey。
变量${RegionId}需替换成您的服务所在地域代码。RegionId的表达方法,请参见地域和可用区。
例如:某用户的网桥设备的productKey为a1abcab****,地域为华东2(上海),地址为
https://a1abcab****.iot-as-http2.cn-shanghai.aliyuncs.com:443
。
实例的详细说明,请参见实例概述。
authEndpoint
是
设备认证服务地址。
地址结构:
企业版实例:
https://${IotInstanceId}.auth.iothub.aliyuncs.com/auth/bridge
。其中,变量${IotInstanceId}需替换成实例ID。
例如:某用户的企业版实例的实例ID为iot-cn-g06kwb****,则地址为
https://iot-cn-g06kwb****.auth.iothub.aliyuncs.com/auth/bridge
。公共实例:新旧版公共实例的地址填写格式不同。
新版公共实例:与企业版实例填写格式一致。
旧版公共实例:
https://iot-auth.${RegionId}.aliyuncs.com/auth/bridge
。其中,变量${RegionId}需替换成您的服务所在地域代码。RegionId的表达方法,请参见地域和可用区。
例如:地域为华东2(上海),则地址为
https://iot-auth.cn-shanghai.aliyuncs.com/auth/bridge
。
以企业版实例为例,指定小型网桥设备的配置代码如下:
// 服务地址 http2Endpoint = "https://iot-2w****.http2.iothub.aliyuncs.com:443" authEndpoint = "https://iot-2w****.auth.iothub.aliyuncs.com/auth/bridge" // 网桥设备信息 productKey = ${bridge-ProductKey-in-Iot-Plaform} deviceName = ${bridge-DeviceName-in-Iot-Plaform} deviceSecret = ${bridge-DeviceSecret-in-Iot-Plaform}
设备认证并上线
配置设备上线
云云对接SDK中的设备上线接口设置如下。
/**
* 设备认证。
* @param newSession 设备Session信息,下行回调的时候会将这个Session传递回来。
* @param originalIdentity 设备原始身份标识符。
* @return
*/
public boolean doOnline(Session newSession, String originalIdentity);
设备上线时,需要传Session
。下行消息回调时,把Session
回调给网桥Server,网桥Server通过Session
中的originalIdentity字段,判断消息的来源设备。
此外,Session
中可选的channel字段,数据类型是Object,可存放设备的连接信息。例如,基于Netty构建的网桥Server,channel字段可存放设备长连接对应的channel对象,消息下行时,可直接从Session
中获取channel进行操作。
云云对接SDK不会对channel数据做任何处理。您可根据使用场景,在channel中存放任何设备相关的信息。
代码示例:
UplinkChannelHandler uplinkHandler = new UplinkChannelHandler();
//创建Session。
Object channel = new Object();
Session session = Session.newInstance(originalIdentity, channel);
//设备上线。
boolean success = uplinkHandler.doOnline(session, originalIdentity);
if (success) {
//设备上线成功,网桥Server接受后续设备通信请求。
} else {
//设备上线失败,网桥Server可以拒绝后续设备通信请求,如断开连接。
}
配置设备原始身份标识符和设备证书信息的映射关系
默认使用配置文件方式:一般从Java工程默认资源文件路径src/main/resources/下读取配置文件devices.conf,格式为HOCON(JSON超集)。
云云对接SDK使用typesafe.config解析配置文件。
文件格式及内容如下。
${device-originalIdentity} {
productKey : ${device-ProductKey-in-Iot-Plaform}
deviceName : ${device-DeviceName-in-Iot-Platform}
deviceSecret : ${device-DeviceSecret-in-Iot-Platform}
}
参数 | 是否必需 | 说明 |
productKey | 是 | 设备所属产品的ProductKey。 |
deviceName | 是 | 设备的DeviceName。 |
deviceSecret | 是 | 设备的DeviceSecret。 |
设备发送上行数据
云云对接SDK的设备上报消息接口设置如下。
/**
* 发送设备上行消息,同步调用接口。
* @param originalIdentity 设备原始身份标识符。
* @param protocolMsg 待发送消息,包含Topic、消息体、QoS等信息。
* @param timeout 超时时间,单位秒。
* @return 超时时间内是否发送成功。
*/
boolean doPublish(String originalIdentity, ProtocolMessage protocolMsg, int timeout);
/**
* 发送设备上行消息,异步调用接口。
* @param originalIdentity 设备原始身份标识符。
* @param protocolMsg 待发送消息,包含Topic、消息体、QoS等信息。
* @return 调用后立即返回CompletableFuture,调用者可进一步处理该future。
*/
CompletableFuture<ProtocolMessage> doPublishAsync(String originalIdentity,
ProtocolMessage protocolMsg);
接口调用代码示例如下。
DeviceIdentity deviceIdentity = ConfigFactory.getDeviceConfigManager().getDeviceIdentity(originalIdentity);
ProtocolMessage protocolMessage = new ProtocolMessage();
protocolMessage.setPayload("Hello world".getBytes());
protocolMessage.setQos(0);
protocolMessage.setTopic(String.format("/%s/%s/update", deviceIdentity.getProductKey(), deviceIdentity.getDeviceName()));
//同步发送。
int timeoutSeconds = 3;
boolean success = upLinkHandler.doPublish(originalIdentity, protocolMessage, timeoutSeconds);
//异步发送。
upLinkHandler.doPublishAsync(originalIdentity, protocolMessage);
网桥Server推送下行数据给设备
网桥Server在调用bootstrap方法时,向云云对接SDK注册了DownlinkChannelHandler。当有下行消息时,云云对接SDK就会回调DownlinkChannelHandler的pushToDevice方法。
您可在pushToDevice中,配置网桥Server处理下行消息。
指定的设备通过云云对接SDK,接入物联网平台后,无需设备订阅Topic,即可收到对应消息。
pushToDevice方法中不要做耗时逻辑,否则会阻塞下行消息接收的线程。如果有耗时或IO逻辑,例如收到物联网平台下行消息后,通过网络长连接发给子设备,请采用异步处理。
代码示例如下。
private static ExecutorService executorService = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors(),
Runtime.getRuntime().availableProcessors() * 2,
60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000),
new ThreadFactoryBuilder().setDaemon(true).setNameFormat("bridge-downlink-handle-%d").build(),
new ThreadPoolExecutor.AbortPolicy());
public static void main(String args[]) {
//默认使用application.conf和devices.conf。
BridgeBootstrap bridgeBootstrap = new BridgeBootstrap();
bridgeBootstrap.bootstrap(new DownlinkChannelHandler() {
@Override
public boolean pushToDevice(Session session, String topic, byte[] payload) {
//接收物联网平台下行消息。
executorService.submit(() -> handleDownLinkMessage(session, topic, payload));
return true;
}
@Override
public boolean broadcast(String s, byte[] bytes) {
return false;
}
});
}
private static void handleDownLinkMessage(Session session, String topic, byte[] payload) {
String content = new String(payload);
log.info("Get DownLink message, session:{}, topic:{}, content:{}", session, topic, content);
Object channel = session.getChannel();
String originalIdentity = session.getOriginalIdentity();
}
参数 | 说明 |
session | 设备doOnline时,传入session,可以用来区分下行消息是发给哪个设备的。 |
topic | 下行消息的Topic。 |
payload | 下行消息的消息体数据,为二进制格式。 |
设备下线
分为以下情况:
小型网桥:网桥Server与物联网平台之间的连接断开时,所有设备会自动从物联网平台离线。
大型网桥:网桥Server与物联网平台之间的连接断开时,设备不会自动从物联网平台离线。网桥重连后,可通过设备下线接口主动更新设备的状态。
子设备的状态表示子设备接入网关的状态,由网关上报到物联网平台刷新该状态。如果网关不能正常上报子设备的状态信息到物联网平台,则展示的子设备状态不会刷新。
例如:某子设备通过网关接入到物联网平台,子设备状态为在线,如果此时网关与物联网平台断开连接,则网关不能上报子设备的状态到物联网平台,该子设备的状态会一直显示在线。
小型网桥和大型网桥:网桥Server与物联网平台之间的连接未断开时,网桥可以主动向物联网平台上报某个设备下线的消息。
网桥Server上报设备下线的接口定义如下:
/** * 向物联网平台上报某个设备下线。 * @param originalIdentity 设备原始身份标识符。 * @return 是否成功上报。 */ boolean doOffline(String originalIdentity);
调用下线接口代码示例如下:
upLinkHandler.doOffline(originalIdentity);
网桥主动断连和重连
网桥可通过BridgeBootstrap对象实例,调用接口disconnectBridge和reconnectBridge分别实现与物联网平台连接主动断开和重连。
reconnectBridge接口仅用于重连,不可用于首次建连。
代码示例:
//主动断开与物联网平台的连接
bridgeBootstrap.disconnectBridge();
Thread.sleep(1000);
//判断与物联网平台是否保持着连接
boolean isConnected = bridgeBootstrap.isBridgeConnected();
//重新建立与物联网平台的连接
bridgeBootstrap.reconnectBridge();
Thread.sleep(1000);
isConnected = bridgeBootstrap.isBridgeConnected();