You can define custom topic categories in IoT Platform. Then, a device can send messages to a custom topic, and your server can receive the messages through the HTTP/2 SDK. Your server can also call the API operation Pub to send commands to the device.

Scenario

In this example, an electronic thermometer periodically exchanges data with a server. The thermometer sends the current temperature to the server, and the server sends the precision setting command to the thermometer.



Prepare the development environment

In this example, both the devices and the server use Java SDKs, so you need to prepare the Java development environment first. You can download Java tools at Java official website and install the Java development environment.

Add the following Maven dependencies to import the device SDK (Link Kit Java SDK) and IoT 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>3.7.1</version>
  </dependency>
  <dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>aliyun-java-sdk-iot</artifactId>
      <version>6.9.0</version>
  </dependency>
  <dependency>
    <groupId>com.aliyun.openservices</groupId>
    <artifactId>iot-client-message</artifactId>
    <version>1.1.2</version>
</dependency>
</dependencies>

Create a product and a device

First, you need to create a product, define custom topic categories, define the TSL model, configure service subscription, and create a device in the IoT Platform console.

  1. Log on to the IoT Platform console.
  2. In the left-side navigation pane, choose Devices > Product.
  3. Click Create Product to create a thermometer product.

    For more information, see Create a product.

  4. After the product is created, find the product and click View.
  5. On the Topic Categories tab of the Product Details page, add custom topic categories.

    For more information, see Create a topic category.

    In this example, add the following two topic categories:

    • /${productKey}/${deviceName}/user/devmsg: used by devices to publish messages. Set Device Operation Authorizations to Publish for this topic category.
    • /${productKey}/${deviceName}/user/cloudmsg: used by devices to receive subscribed messages. Set Device Operation Authorizations to Subscribe for this topic category.
  6. On the Service Subscription tab, set the type of messages to be pushed to the HTTP/2 SDK to Device Upstream Notification.

    For more information, see Development guide for Java HTTP/2 SDK.



  7. In the left-side navigation pane, choose Devices and add a thermometer device under the thermometer product that has been created. For more information, see Create a device.

The server receives messages from the device

The following figure shows how the device sends a message to the server.



  • Configure the HTTP/2 SDK, which will be installed in the server, and set a callback for the specified topic.

    After service subscription is configured, the server listens to all the messages sent by all the devices under the product.

    • Connect the HTTP/2 SDK to IoT Platform.
      // Configure identity verification information.
      String accessKey = "The AccessKey ID of your Alibaba Cloud account";
      String accessSecret = "The AccessKey Secret of your Alibaba Cloud account";
      String uid = "Your Alibaba Cloud account ID";
      String regionId = "The ID of the region where the device is located";
      String productKey = "The key of the product";
      String deviceName = "The name of the device";
      String endPoint = "https://" + uid + ".iot-as-http2." + regionId + ".aliyuncs.com";
      // Configure the connection.
      Profile profile = Profile.getAccessKeyProfile(endPoint, regionId, accessKey, accessSecret);
      
      // Construct a client.
      MessageClient client = MessageClientFactory.messageClient(profile);
      
      // Receive the message.
      client.connect(new MessageCallback() {
          @Override
          public Action consume(MessageToken messageToken) {
              Message m = messageToken.getMessage();
              System.out.println("\ntopic=" + m.getTopic());
              System.out.println("payload=" + new String(m.getPayload()));
              System.out.println("generateTime=" + m.getGenerateTime());
              // CommitSuccess indicates that the current message has been consumed. In this case, IoT Platform will delete the message. If the message is not marked with CommitSuccess, IoT Platform will retain the message until it expires.
              return MessageCallback.Action.CommitSuccess;
           }
      });
    • Configure the message receiving interface.

      In this example, the server subscribes to the topic /$ {productKey}/$ {deviceName}/user/devmsg. Therefore, you need to set a callback for this topic.

      // Define the callback.
      MessageCallback messageCallback = new MessageCallback() {
      // Obtain and display the message. You can set the required action for the server here.
                  @Override
                  public Action consume(MessageToken messageToken) {
                      Message m = messageToken.getMessage();
                      log.info("receive : " + new String(messageToken.getMessage().getPayload()));
                      System.out.println(messageToken.getMessage());
                      return MessageCallback.Action.CommitSuccess;
                  }
              };
              // Register the callback.
              client.setMessageListener("/" + productKey + "/" + deviceName + "/user/devmsg", messageCallback);

    For more information, see Development guide for Java HTTP/2 SDK.

  • Configure the device SDK to send a message.
    • Configure device authentication information.
      final String productKey = "XXXXXX";
      final String deviceName = "XXXXXX";
      final String deviceSecret = "XXXXXXXXX";
      final String region = "XXXXXX";
    • Set connection initialization parameters, including MQTT connection information, device information, and initial device status.
      LinkKitInitParams params = new LinkKitInitParams();
      // Configure MQTT connection information. Link Kit uses MQTT as the underlying protocol. 
      IoTMqttClientConfig config = new IoTMqttClientConfig();
      config.productKey = productKey;
      config.deviceName = deviceName;
      config.deviceSecret = deviceSecret;
      config.channelHost = productKey + ".iot-as-mqtt." + region + ".aliyuncs.com:1883";
      // Configure device information.
      DeviceInfo deviceInfo = new DeviceInfo();
      deviceInfo.productKey = productKey;
      deviceInfo.deviceName = deviceName;
      deviceInfo.deviceSecret = deviceSecret;
      // Register the initial device status.
      Map<String, ValueWrapper> propertyValues = new HashMap<String, ValueWrapper>();
      
      params.mqttClientConfig = config;
      params.deviceInfo = deviceInfo;
      params.propertyValues = propertyValues;
    • Initialize the connection.
      // Initialize the connection and set the callback that is called when the initialization is successful.
      LinkKit.getInstance().init(params, new ILinkKitConnectListener() {
           @Override
           public void onError(AError aError) {
               System.out.println("Init error:" + aError);
           }
      
           // Set the callback that is called when the initialization is successful.
           @Override
           public void onInitDone(InitResult initResult) {
               System.out.println("Init done:" + initResult);
           }
       });
    • Send a message from the device.

      After connecting to IoT Platform, the device sends a message to the specified topic. Replace the content of the onInitDone callback like the following example:

      @Override
       public void onInitDone(InitResult initResult) {
           // Set the topic to which the message is published and the message content.
           MqttPublishRequest request = new MqttPublishRequest();
           request.topic = "/" + productKey + "/" + deviceName + "/user/devmsg";
           request.qos = 0;
           request.payloadObj = "{\"temperature\":35.0, \"time\":\"sometime\"}";
           // Publish the message and set the callback that is called when the message is published.
           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());
               }
           });
       }

      The server receives the following message:

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

The server sends messages to the device

The following figure shows how the server sends a message to the device.



  • Configure the device SDK to subscribe to a topic.

    For more information about how to configure device authentication information, set connection initialization parameters, and initialize the connection, see the device SDK configuration in the previous section.

    The device needs to subscribe to a specific topic to receive messages sent by the server.

    The following example demonstrates how to configure the device SDK to subscribe to a topic:

    // Set the callback that is called when the initialization is successful.
    @Override
    public void onInitDone(InitResult initResult) {
        // Set the topic to which the device subscribes.
        MqttSubscribeRequest request = new MqttSubscribeRequest();
        request.topic = "/" + productKey + "/" + deviceName + "/user/cloudmsg";
        request.isSubscribe = true;
        // Send a subscription request and set the callbacks that are called when the subscription succeeds and fails, respectively.
        LinkKit.getInstance().subscribe(request, new IConnectSubscribeListener() {
            @Override
            public void onSuccess() {
                System.out.println("");
            }
    
            @Override
            public void onFailure(AError aError) {
    
            }
        });
    
        // Set the listener for listening to subscribed messages.
        IConnectNotifyListener notifyListener = new IConnectNotifyListener() {
            // Define the callback that is called when a subscribed message is received.
            @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);
    }
  • Configure the IoT SDK to call the Pub operation to publish a message.
    • Configure identity verification information.
       String regionId = "The ID of the region where the device is located";
       String accessKey = "The AccessKey ID of your Alibaba Cloud account";
       String accessSecret = "The AccessKey Secret of your Alibaba Cloud account";
       final String productKey = "The key of the product";
    • Set connection parameters.
      // Construct a client.
      DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKey, accessSecret);
      IAcsClient client = new DefaultAcsClient(profile);
    • Set the parameters for publishing a message.
      PubRequest request = new PubRequest();
      request.setQos(0);
      // Set the topic to which the message is published.
      request.setTopicFullName("/" + productKey + "/" + deviceName + "/user/cloudmsg");
      request.setProductKey(productKey);
      // Set the message content. The message content must be encoded in Base64. Otherwise, the message content will be garbled characters.
      request.setMessageContent(Base64.encode("{\"accuracy\":0.001,\"time\":now}"));
    • Publish the message.
      try {
           PubResponse response = client.getAcsResponse(request);
           System.out.println("pub success?:" + response.getSuccess());
       } catch (Exception e) {
           System.out.println(e);
       }
      The device receives the following message:
      msg = [{"accuracy":0.001,"time":now}]

Appendix: demo

Click here to download and view the complete demo for this example.