基础用法

基于云云对接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就会回调DownlinkChannelHandlerpushToDevice方法。

您可在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对象实例,调用接口disconnectBridgereconnectBridge分别实现与物联网平台连接主动断开和重连。

说明

reconnectBridge接口仅用于重连,不可用于首次建连。

代码示例:

//主动断开与物联网平台的连接
bridgeBootstrap.disconnectBridge();
Thread.sleep(1000);
//判断与物联网平台是否保持着连接
boolean isConnected = bridgeBootstrap.isBridgeConnected();

//重新建立与物联网平台的连接
bridgeBootstrap.reconnectBridge();
Thread.sleep(1000);
isConnected = bridgeBootstrap.isBridgeConnected();