全部產品
Search
文件中心

IoT Platform:使用自訂Topic進行通訊

更新時間:Jun 30, 2024

使用MQTT協議接入的裝置和物聯網平台,通過訂閱Topic或向Topic發布訊息的方式進行通訊。Topic分為系統Topic、物模型Topic和自訂Topic,其中自訂Topic需要使用者在控制台定義。 本文為您介紹裝置使用自訂Topic與物聯網平台進行上下行通訊,以及物聯網平台和商務服務器之間通訊的步驟。

背景資訊

本樣本中,電子溫度計通過訂閱自訂Topic接收指令,通過向自訂Topic發布訊息從而上報溫度,物聯網平台將收到的溫度資訊通過AMQP服務端轉寄到使用者服務器,使用者服務器調用Pub介面向自訂Topic發布訊息從而實現對裝置的遠程精度設定。

自訂Topic通訊

準備開發環境

本樣本中,裝置端和雲端均使用Java語言的SDK,需先準備Java開發環境。您可從Java官方網站下載並安裝Java開發環境。

本樣本使用環境如下:

建立產品和裝置

  1. 登入物聯網平台控制台

  2. 執行個體概覽頁簽的全部環境下,找到對應的執行個體,單擊執行個體卡片。

  3. 在左側導覽列,單擊裝置管理 > 產品

  4. 單擊建立產品,建立溫度計產品,擷取productKey,例如a1uzcH0****

    詳細操作指導,請參見建立產品

  5. 建立產品成功後,單擊該產品對應的查看

  6. 產品詳情頁面的Topic類列表頁簽下,單擊自訂Topic,增加自訂Topic類。

    詳細操作指導,請參見使用自訂Topic通訊

    本樣本中,定義了以下兩個Topic類:

    • 裝置發布訊息Topic:/a1uzcH0****/${deviceName}/user/devmsg,許可權為發布。

    • 裝置訂閱訊息Topic:/a1uzcH0****/${deviceName}/user/cloudmsg,許可權為訂閱。

  7. 服務端訂閱頁簽下,單擊建立訂閱,設定AMQP服務端訂閱,訂閱裝置上報訊息預設消費組

    裝置上報訊息包含自訂Topic訊息和物模型訊息。詳細操作和說明,請參見配置AMQP服務端訂閱

  8. 在左側導覽列,選擇裝置管理 > 裝置,然後在剛建立的溫度計產品下,添加裝置device1,擷取裝置認證ProductKeyDeviceNameDeviceSecret

    詳細操作指導,請參見單個建立裝置

裝置發送訊息給伺服器

流程圖:

自訂Topic通訊

在整個流程中:

  • 伺服器通過AMQP用戶端接收訊息,需配置AMQP用戶端接入物聯網平台,監聽裝置訊息。具體操作,請參見Java SDK接入樣本

    重要

    AMQP訂閱訊息的消費組,必須與裝置在相同的物聯網平台執行個體下。

  • 配置裝置端SDK接入物聯網平台,並發送訊息。

    • 配置裝置認證資訊。

      final String productKey = "a1uzcH0****";
      final String deviceName = "device1";
      final String deviceSecret = "uwMTmVAMnxB****";
      final String region = "cn-shanghai";
      final String iotInstanceId = "iot-2w****";

      實際業務情境中,您需修改以下參數值。

      參數

      樣本

      說明

      productKey

      a1uzcH0****

      裝置認證資訊。您可在物聯網平台控制台的裝置詳情頁面查看。具體操作,請參見查看具體裝置資訊

      deviceName

      device1

      deviceSecret

      uwMTmVAMnxB****

      region

      cn-shanghai

      您物聯網平台裝置所在地區的Region ID。Region ID表達方法,請參見地區列表

      iotInstanceId

      iot-2w****

      裝置所屬執行個體的ID。

      您可在控制台的執行個體概覽頁面查看。

      • 若有ID值,必須傳入該ID值。

      • 若無執行個體概覽頁面或ID值,傳入空值,即iotInstanceId = ""

    • 設定初始化串連參數,包括MQTT串連配置、裝置資訊和初始物模型屬性。

      LinkKitInitParams params = new LinkKitInitParams();
      //LinkKit底層是MQTT協議,設定MQTT的配置。
      IoTMqttClientConfig config = new IoTMqttClientConfig();
      config.productKey = productKey;
      config.deviceName = deviceName;
      config.deviceSecret = deviceSecret;
      config.channelHost = productKey + ".iot-as-mqtt." + region + ".aliyuncs.com:1883";
      //裝置的資訊。
      DeviceInfo deviceInfo = new DeviceInfo();
      deviceInfo.productKey = productKey;
      deviceInfo.deviceName = deviceName;
      deviceInfo.deviceSecret = deviceSecret;
      //報備的裝置初始狀態。
      Map<String, ValueWrapper> propertyValues = new HashMap<String, ValueWrapper>();
      
      params.mqttClientConfig = config;
      params.deviceInfo = deviceInfo;
      params.propertyValues = propertyValues;

      實際業務情境中,您需修改以下參數值。

      參數

      樣本

      說明

      config.channelHost

      config.channelHost = productKey + ".iot-as-mqtt." + region + ".aliyuncs.com:1883";

      MQTT裝置接入網域名稱。

      • 舊版公用執行個體:config.channelHost = productKey + ".iot-as-mqtt." + region + ".aliyuncs.com:1883";

      • 新版公用執行個體和企業版執行個體:config.channelHost = iotInstanceId + ".mqtt.iothub.aliyuncs.com:1883";

    • 初始化串連。

      //串連並設定串連成功以後的回呼函數。
      LinkKit.getInstance().init(params, new ILinkKitConnectListener() {
           @Override
           public void onError(AError aError) {
               System.out.println("Init error:" + aError);
           }
      
           //初始化成功以後的回調。
           @Override
           public void onInitDone(InitResult initResult) {
               System.out.println("Init done:" + initResult);
           }
       });
    • 裝置發送訊息。

      裝置端串連物聯網平台後,向自訂的Topic發送訊息。您需將onInitDone函數內容替換為以下內容:

      @Override
       public void onInitDone(InitResult initResult) {
           //設定Pub訊息的Topic和內容。
           MqttPublishRequest request = new MqttPublishRequest();
           request.topic = "/" + productKey + "/" + deviceName + "/user/devmsg";
           request.qos = 0;
           request.payloadObj = "{\"temperature\":35.0, \"time\":\"sometime\"}";
           //發送訊息並設定成功以後的回調。
           LinkKit.getInstance().publish(request, new IConnectSendListener() {
               @Override
               public void onResponse(ARequest aRequest, AResponse aResponse) {
                   System.out.println("onResponse:" + aResponse.getData());
               }
      
               @Override
               public void onFailure(ARequest aRequest, AError aError) {
                   System.out.println("onFailure:" + aError.getCode() + aError.getMsg());
               }
           });
       }

      實際業務情境中,您需修改以下參數值。

      參數

      樣本

      說明

      request.topic

      "/" + productKey + "/" + deviceName + "/user/devmsg"

      具有發布許可權的自訂Topic。

      request.payloadObj

      "{\"temperature\":35.0, \"time\":\"sometime\"}"

      自訂的訊息內容。

      伺服器收到訊息如下:

      Message
      {payload={"temperature":35.0, "time":"sometime"},
      topic='/a1uzcH0****/device1/user/devmsg',
      messageId='1131755639450642944',
      qos=0,
      generateTime=1558666546105}

伺服器發送訊息給裝置

流程圖:

自訂Topic通訊

  • 配置裝置端SDK訂閱Topic。

    配置裝置認證資訊、設定初始化串連參數、初始化串連,請參見裝置發送訊息給伺服器中的相應範例程式碼。

    裝置要接收伺服器發送的訊息,還需訂閱訊息Topic。

    配置裝置端訂閱Topic樣本如下:

    //初始化成功以後的回調。
    @Override
    public void onInitDone(InitResult initResult) {
        //設定訂閱的Topic。
        MqttSubscribeRequest request = new MqttSubscribeRequest();
        request.topic = "/" + productKey + "/" + deviceName + "/user/cloudmsg";
        request.isSubscribe = true;
        //發出訂閱請求並設定訂閱成功或者失敗的回呼函數。
        LinkKit.getInstance().subscribe(request, new IConnectSubscribeListener() {
            @Override
            public void onSuccess() {
                System.out.println("");
            }
    
            @Override
            public void onFailure(AError aError) {
    
            }
        });
    
        //設定訂閱的下行訊息到來時的回呼函數。
        IConnectNotifyListener notifyListener = new IConnectNotifyListener() {
            //此處定義收到下行訊息以後的回呼函數。
            @Override
            public void onNotify(String connectId, String topic, AMessage aMessage) {
                System.out.println(
                    "received message from " + topic + ":" + 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);
    }

    其中,request.topic值需修改為具有訂閱許可權的自訂Topic。

  • 配置雲端SDK調用物聯網平台介面Pub發布訊息。參數說明,請參見Pub,使用說明,請參見Java SDK使用說明

    • 設定身份認證資訊。

       String regionId = "cn-shanghai";
       String accessKey = "LTAI4GFGQvKuqHJhFaj****";
       String accessSecret = "iMS8ZhCDdfJbCMeA005sieKe****";
       final String productKey = "a1uzcH0****";
       final String deviceName = "device1";
       final String iotInstanceId = "iot-2w****";

      實際業務情境中,您需修改以下參數值。

      參數

      樣本

      說明

      accessKey

      LTAI4GFGQvKuqHJhFaj****

      您的阿里雲帳號的AccessKey ID和AccessKey Secret。

      登入物聯網平台控制台,將滑鼠移至帳號頭像上,然後單擊AccessKey管理,擷取AccessKey ID和AccessKey Secret。

      說明

      如果使用RAM使用者,您需授予該RAM使用者管理物聯網平台的許可權(AliyunIOTFullAccess),否則將串連失敗。授權方法請參見授權RAM使用者訪問物聯網平台

      accessSecret

      iMS8ZhCDdfJbCMeA005sieKe****

      productKey

      a1uzcH0****

      裝置認證資訊。您可在物聯網平台控制台的裝置詳情頁面查看。具體操作,請參見查看具體裝置資訊

      deviceName

      device1

      region

      cn-shanghai

      您物聯網平台裝置所在地區的Region ID。Region ID表達方法,請參見地區列表

      iotInstanceId

      iot-2w****

      裝置所屬執行個體的ID。

      您可在控制台的執行個體概覽頁面查看。

      • 若有ID值,必須傳入該ID值。

      • 若無執行個體概覽頁面或ID值,傳入空值,即iotInstanceId = ""

    • 設定串連參數。

      //設定client的參數。
      DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKey, accessSecret);
      IAcsClient client = new DefaultAcsClient(profile);
    • 設定訊息發布參數。

      PubRequest request = new PubRequest();
      request.setIotInstanceId(iotInstanceId);
      request.setQos(0);
      //設定發布訊息的Topic。
      request.setTopicFullName("/" + productKey + "/" + deviceName + "/user/cloudmsg");
      request.setProductKey(productKey);
      //設定訊息的內容,一定要用Base64編碼,否則亂碼。
      request.setMessageContent(Base64.encode("{\"accuracy\":0.001,\"time\":now}"));

      實際業務情境中,您需修改調用介面的請求參數。詳細說明,請參見Pub

    • 發送訊息。

      try {
           PubResponse response = client.getAcsResponse(request);
           System.out.println("pub success?:" + response.getSuccess());
       } catch (Exception e) {
           System.out.println(e);
       }

      裝置端接收到的訊息如下:

      msg = [{"accuracy":0.001,"time":now}]

附錄:程式碼範例

重要

實際業務情境中,請按照上文描述,修改相關代碼及相關參數的值。

下載Pub/Sub demo,包含本樣本的雲端SDK和裝置端SDK配置代碼Demo。

AMQP用戶端接入物聯網平台樣本,請參見: