物聯(lián)網(wǎng)平臺(tái)支持廣播通信,即向指定產(chǎn)品下的全量設(shè)備(設(shè)備無(wú)需訂閱廣播Topic),或訂閱了指定Topic的所有設(shè)備發(fā)送消息。設(shè)備在線,即可收到服務(wù)器發(fā)送的廣播消息。本文以向全量在線設(shè)備廣播消息為例,介紹廣播通信的具體配置流程。

背景信息

  • 向全量在線設(shè)備廣播消息

    業(yè)務(wù)服務(wù)器調(diào)用PubBroadcast接口,傳入指定產(chǎn)品的ProductKeyMessageContent消息內(nèi)容,產(chǎn)品的全量在線設(shè)備可通過(guò)廣播Topic/sys/${productKey}/${deviceName}/broadcast/request/${MessageId},收到MessageContent消息內(nèi)容。

    廣播Topic中的MessageId是物聯(lián)網(wǎng)平臺(tái)生成的消息ID,成功發(fā)送消息后,將作為PubBroadcast接口的返回?cái)?shù)據(jù)返回業(yè)務(wù)服務(wù)器。

    例如,廠家有多個(gè)智能門鎖接入物聯(lián)網(wǎng)平臺(tái),可通過(guò)業(yè)務(wù)服務(wù)器向全部在線設(shè)備發(fā)送一條相同的指令,使某個(gè)密碼失效。

    廣播通信
  • 向訂閱了指定Topic的所有設(shè)備廣播消息

    設(shè)備端訂閱相同的廣播Topic,業(yè)務(wù)服務(wù)器調(diào)用PubBroadcast接口,傳入指定產(chǎn)品的ProductKeyMessageContent消息內(nèi)容和要接收廣播消息的Topic全稱(格式為:/broadcast/${productKey}/自定義字段),已訂閱廣播Topic的在線設(shè)備,收到MessageContent消息內(nèi)容。

    重要
    • 廣播Topic是在設(shè)備開發(fā)時(shí)編碼定義的,無(wú)需在物聯(lián)網(wǎng)平臺(tái)控制臺(tái)創(chuàng)建。
    • 一個(gè)廣播Topic最多可被1,000個(gè)設(shè)備訂閱。如果您的設(shè)備超過(guò)數(shù)量限制,您可以對(duì)設(shè)備進(jìn)行分組。例如,如果您有5,000個(gè)設(shè)備,您可以將設(shè)備按每組1,000個(gè),而分成5組。您需要分5次調(diào)用廣播Topic,自定義字段分別設(shè)置為group1、group2、group3、group4、group5,然后讓每組設(shè)備分別訂閱各自分組的廣播Topic。

    廣播接口調(diào)用的更多詳細(xì)說(shuō)明,請(qǐng)參見PubBroadcast

使用限制

  • 廣播消息僅推送給產(chǎn)品下當(dāng)前在線的設(shè)備。
  • 指定在線設(shè)備廣播時(shí),需指定Topic訂閱廣播,廣播接口最大調(diào)用頻次:1次/秒。
  • 全量在線設(shè)備廣播時(shí),無(wú)需訂閱廣播Topic,廣播接口最大調(diào)用頻次:1次/分鐘。
  • 廣播消息體報(bào)文最大為64 KB。
重要 廣播消息不會(huì)被實(shí)例的消息上下行TPS規(guī)格限流。例如,消息上下行TPS為100條/秒,當(dāng)前在線設(shè)備為500個(gè)時(shí),每次調(diào)用廣播接口,消息不會(huì)只發(fā)送給100個(gè)在線設(shè)備,而是可以發(fā)送給500個(gè)在線設(shè)備。

準(zhǔn)備開發(fā)環(huán)境

本示例中,設(shè)備端和云端均使用Java語(yǔ)言的SDK,需先準(zhǔn)備Java開發(fā)環(huán)境。您可從Java 官方網(wǎng)站下載,并安裝Java開發(fā)環(huán)境。

添加Maven項(xiàng)目依賴

新建項(xiàng)目,在pom.xml中,添加以下Maven依賴。

說(shuō)明 以下IoT Java SDK版本為示例值,您可在API在線調(diào)試工具頁(yè)面查看SDK依賴信息。
<dependencies>
  <dependency>
     <groupId>com.aliyun.alink.linksdk</groupId>
     <artifactId>iot-linkkit-java</artifactId>
     <version>1.2.0.1</version>
     <scope>compile</scope>
  </dependency>
  <dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>aliyun-java-sdk-core</artifactId>
      <version>4.5.6</version>
  </dependency>
  <dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>aliyun-java-sdk-iot</artifactId>
      <version>7.41.0</version>
  </dependency>
  <dependency>
    <groupId>com.aliyun.openservices</groupId>
    <artifactId>iot-client-message</artifactId>
    <version>1.1.2</version>
  </dependency>
</dependencies>

創(chuàng)建產(chǎn)品和設(shè)備

  1. 登錄物聯(lián)網(wǎng)平臺(tái)控制臺(tái)
  2. 實(shí)例概覽頁(yè)面,選擇目標(biāo)環(huán)境,找到對(duì)應(yīng)的實(shí)例,單擊實(shí)例ID或備注名稱。
    重要 目前僅開通企業(yè)版實(shí)例服務(wù)的地域下,執(zhí)行此步驟。其他地域,請(qǐng)?zhí)^(guò)此步驟。地域及實(shí)例的支持說(shuō)明,請(qǐng)參見實(shí)例概述
    實(shí)例概覽
  3. 在左側(cè)導(dǎo)航欄,單擊設(shè)備管理 > 產(chǎn)品
  4. 單擊創(chuàng)建產(chǎn)品,創(chuàng)建智能門鎖產(chǎn)品。具體操作,請(qǐng)參見創(chuàng)建產(chǎn)品
  5. 在左側(cè)導(dǎo)航欄,單擊設(shè)備管理 > 設(shè)備,然后在智能門鎖產(chǎn)品下,創(chuàng)建三個(gè)設(shè)備。具體操作,請(qǐng)參見批量創(chuàng)建設(shè)備

配置設(shè)備端SDK

  • 配置設(shè)備端接入物聯(lián)網(wǎng)平臺(tái)。
    • 配置設(shè)備認(rèn)證信息。
      final String productKey = "<yourProductKey>";
      final String deviceName = "<yourDeviceName>";
      final String deviceSecret = "<yourDeviceSecret>";
      final String region = "<yourRegionID>";

      productKeydeviceNamedeviceSecret是設(shè)備證書信息,請(qǐng)?jiān)?span props="CHINA INTL">物聯(lián)網(wǎng)平臺(tái)控制臺(tái),對(duì)應(yīng)實(shí)例下,選擇設(shè)備管理 > 設(shè)備,單擊設(shè)備對(duì)應(yīng)的查看,進(jìn)入設(shè)備詳情頁(yè)獲取。

      region是設(shè)備所屬地域。region的表達(dá)方法,請(qǐng)參見地域列表

    • 設(shè)置初始化連接參數(shù),包括MQTT配置、設(shè)備信息和初始狀態(tài)。
      LinkKitInitParams params = new LinkKitInitParams();
      //LinkKit底層是MQTT協(xié)議,設(shè)置MQTT配置。
      IoTMqttClientConfig config = new IoTMqttClientConfig();
      config.productKey = productKey;
      config.deviceName = deviceName;
      config.deviceSecret = deviceSecret;
      config.channelHost = productKey + ".iot-as-mqtt." + region + ".aliyuncs.com:1883";
      //設(shè)備信息。
      DeviceInfo deviceInfo = new DeviceInfo();
      deviceInfo.productKey = productKey;
      deviceInfo.deviceName = deviceName;
      deviceInfo.deviceSecret = deviceSecret;
      //報(bào)備的設(shè)備初始狀態(tài)。
      Map<String, ValueWrapper> propertyValues = new HashMap<String, ValueWrapper>();
      params.mqttClientConfig = config;
      params.deviceInfo = deviceInfo;
      params.propertyValues = propertyValues;

      channelHost是MQTT接入地址,公共實(shí)例和企業(yè)版實(shí)例中接入地址的獲取方法,請(qǐng)參見查看實(shí)例終端節(jié)點(diǎn)

    • 初始化連接。
      //連接并設(shè)置連接成功以后的回調(diào)函數(shù)。
      LinkKit.getInstance().init(params, new ILinkKitConnectListener() {
           @Override
           public void onError(AError aError) {
               System.out.println("Init error:" + aError);
           }
           //初始化成功以后的回調(diào)。
           @Override
           public void onInitDone(InitResult initResult) {
               System.out.println("Init done:" + initResult);
           }
       });
  • 在回調(diào)函數(shù)onInitDone中,通過(guò)前綴來(lái)識(shí)別廣播Topic,廣播Topic的前綴為:/sys/${productKey}/${deviceName}/broadcast/request/
    public void onInitDone(InitResult initResult) {
    
                    //設(shè)置下行消息到來(lái)時(shí)的回調(diào)函數(shù)。
                    IConnectNotifyListener notifyListener = new IConnectNotifyListener() {
                        //此處定義收到下行消息以后的回調(diào)函數(shù)。
                        @Override
                        public void onNotify(String connectId, String topic, AMessage aMessage) {
    
                            //過(guò)濾得到廣播消息。
                            if(topic.startsWith(broadcastTopic)){
                                System.out.println(
                                        "received broadcast message from topic=" + topic + ",\npayload=" + new String((byte[])aMessage.getData()));
                            }
    
                        }
    
                        @Override
                        public boolean shouldHandle(String s, String s1) {
                            return false;
                        }
    
                        @Override
                        public void onConnectStateChange(String s, ConnectState connectState) {
    
                        }
                    };
                    LinkKit.getInstance().registerOnNotifyListener(notifyListener);
                }

配置服務(wù)端SDK

配置云端Java SDK發(fā)送廣播消息。

  • 配置身份認(rèn)證信息。
     String regionId = "<yourRegionID>";
     String accessKey = "<yourAccessKey>";
     String accessSecret = "<yourAccessSecret>";
     final String productKey = "<yourProductKey>";
  • 配置服務(wù)端調(diào)用云端API PubBroadcast廣播消息。
    //設(shè)置client的參數(shù)。
    DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKey, accessSecret);
    IAcsClient client = new DefaultAcsClient(profile);
    PubBroadcastRequest request = new PubBroadcastRequest();
    //設(shè)置廣播消息的產(chǎn)品productKey。
    request.setProductKey(productKey);
    //設(shè)置消息的內(nèi)容,一定要用base64編碼,否則亂碼。
    request.setMessageContent(Base64.encode("{\"pwd\":\"2892nd6Y\"}"));
    //設(shè)置實(shí)例ID。
    request.setIotInstanceId("iot-cn-***");
  • 服務(wù)端發(fā)送廣播消息。
    try {
        PubBroadcastResponse response = client.getAcsResponse(request);
    System.out.println("broadcast pub success: broadcastId =" + response.getMessageId());
    } catch (Exception e) {
        System.out.println(e);
    }

驗(yàn)證操作

先運(yùn)行各設(shè)備的Link SDK代碼,使設(shè)備上線,然后運(yùn)行云端SDK代碼,調(diào)用接口PubBroadcast向設(shè)備廣播消息。

云端SDK中,向設(shè)備端廣播的消息內(nèi)容為:"{\"pwd\":\"2892nd6Y\"}"

設(shè)備端本地日志都將顯示收到廣播消息:{\"pwd\":\"2892nd6Y\"}

門鎖1:

門鎖1

門鎖2:

門鎖2

門鎖3:

門鎖3

附錄:Demo

查看以下完整的配置代碼Demo,其中包含物聯(lián)網(wǎng)平臺(tái)云端SDK和設(shè)備端SDK示例。