You can use the HTTP/2 SDK for Java on your server to receive device messages that are pushed from IoT Platform. This article describes how to develop the HTTP/2 SDK for Java to use the server-side subscription feature.

Background information

Download the server-side HTTP/2 SDK demo for Java.

Configure server-side subscription

To set the type of messages to which you want to subscribe, perform the following steps:

  1. Log on to the IoT Platform console.
  2. In the left-side navigation pane, choose Devices > Products.
  3. In the product list, find the product for which you want to configure server-side subscription and click View in the Actions column. You are redirected to the Product Details page.
  4. On the Product Details page, click the Server-side Subscription tab and click Set.
  5. Select the types of messages that you want to subscribe to.
    Console screenshot
    • Device Upstream Notification: indicates the messages of the topics to which devices are allowed to publish messages. If this message type is selected, the HTTP/2 SDK can receive messages that are published by devices.

      This type of messages includes custom data and Thing Specification Language (TSL) data that is submitted by devices. The upstream TSL data includes property data, event data, responses to property setting requests, and responses to service calling requests.

      For example, the following three topic categories are defined for a product:
      • /${YourProductKey}/${YourDeviceName}/user/get: The Allowed Operations parameter of this topic category is set to Subscribe.
      • /${YourProductKey}/${YourDeviceName}/user/update: The Allowed Operations parameter of this topic category is set to Publish.
      • /sys/${YourProductKey}/${YourDeviceName}/thing/event/property/post: The Allowed Operations parameter of this topic category is set to Publish.

      The server-side subscription feature pushes messages of the topic categories /${YourProductKey}/${YourDeviceName}/user/update and /sys/${YourProductKey}/${YourDeviceName}/thing/event/property/post. The messages of /sys/${YourProductKey}/${YourDeviceName}/thing/event/property/post are processed by the system before they are pushed.

    • Device Status Change Notification: indicates the notifications that are sent when the statuses of devices change, for example, notifications for when devices go online or go offline. The topic that is used to submit device status changes is /as/mqtt/status/${YourProductKey}/${YourDeviceName}. If this notification type is selected, the HTTP/2 SDK can receive device status change notifications.
    • Sub-Device Data Report Detected by Gateway: indicates that gateways can submit the information of sub-devices that are locally discovered. To use this message type, make sure that the applications on the gateways support this message type. This message type is specific to gateways.
    • Device Topological Relation Changes: indicates notifications about creation and removal of the topological relationship between a gateway and its sub-devices. This message type is specific to gateways.
    • Device Changes Throughout Lifecycle: indicates notifications about device creation, deletion, disabling, and enabling.
    Note For messages of TSL data, Device Status Change Notification, Sub-Device Data Report Detected by Gateway, Device Topological Relation Changes, and Device Changes Throughout Lifecycle, the QoS is 0 by default. For Device Upstream Notification messages except messages of TSL data, you can set the QoS to 0 or 1 on your device SDK.

Connect the HTTP/2 SDK to IoT Platform

Add the following dependencies to your Maven project to install IoT Platform SDK:

<dependency>
    <groupId>com.aliyun.openservices</groupId>
    <artifactId>iot-client-message</artifactId>
    <version>1.1.3</version>
</dependency>

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>3.7.1</version>
</dependency>

Authenticate the identity

To use the server-side subscription feature, you must use the AccessKey pair of your Alibaba Cloud account for identity authentication and establish a connection between the HTTP/2 SDK and IoT Platform.

The following sample code describes how to establish a connection:

// The AccessKey ID of your Alibaba Cloud account.
String accessKey = "xxxxxxxxxxxxxxx";
// The AccessKey secret of your Alibaba Cloud account.
String accessSecret = "xxxxxxxxxxxxxxx";
// The region ID of your IoT Platform service.
String regionId = "cn-shanghai";
// The ID of your Alibaba Cloud account.
String uid = "xxxxxxxxxxxx";
// The endpoint https://${uid}.iot-as-http2.${region}.aliyuncs.com.
String endPoint = "https://" + uid + ".iot-as-http2." + regionId + ".aliyuncs.com";

// Configure connection parameters.
Profile profile = Profile.getAccessKeyProfile(endPoint, regionId, accessKey, accessSecret);

// Construct the client.
MessageClient client = MessageClientFactory.messageClient(profile);
// Receive data.
client.connect(messageToken -> {
    Message m = messageToken.getMessage();
    System.out.println("receive message from " + m);
    return MessageCallback.Action.CommitSuccess;
});

The following table describes how to obtain the account information in the preceding sample code.

Parameter Description
accessKey The AccessKey ID of your Alibaba Cloud account.

To obtain the AccessKey ID, log on to the Alibaba Cloud console, move the pointer over your account avatar, and then click AccessKey. You are redirected to the Security Management page of the User Management console.

accessSecret The AccessKey secret of your Alibaba Cloud account. Obtain the AccessKey secret in the same way you obtain the AccessKey ID.
uid The ID of your Alibaba Cloud account.

To obtain the account ID, log on to the Alibaba Cloud console by using your Alibaba Cloud account, and click the account avatar. You are redirected to the Security Settings page of the Account Management console.

regionId The ID of the region where IoT Platform resides.

In the IoT Platform console, you can view the region in the upper-left corner of the top navigation bar. For more information about the format of the RegionId parameter, see Regions and zones.

Call the connection-related methods

Method Description
connect Calls this method to establish a connection between the HTTP/2 SDK on the server and IoT Platform. After the connection is established, the server immediately receives the messages that are pushed by IoT Platform.
void connect(MessageCallback callback);
disconnect Calls this method to disconnect the HTTP/2 SDK on the server from IoT Platform and stop receiving messages.
void disconnect();
isConnected Calls this method to check whether the HTTP/2 SDK on the server is connected to IoT Platform.
boolean isConnected();
setConnectionCallback Calls this method to set the callback for monitoring the connection status.
void setConnectionCallback(ConnectionCallback var1);

Example:

client.setConnectionCallback(new ConnectionCallback() {
    @Override
    public void onConnectionLost() {
        System.out.println("The connection is closed.");
    }

    @Override
    public void onConnected(boolean isReconnected) {
        System.out.println("The connection is successful. Check whether the connection is reestablished: " + isReconnected);

    }
});

Configure the message receiving operation

After the connection is established, the server immediately pushes the subscribed messages to the HTTP/2 SDK. Therefore, when you establish a connection, you must configure the default message receiving operation to receive messages for which no callback is configured. We recommend that you call the setMessageListener() method to configure a callback before you connect the HTTP/2 SDK to IoT Platform.

Use the consume method of the MessageCallback operation and the setMessageListener() method of the messageClient operation to configure the message receiving operation.

The return result of the consume method determines whether the SDK sends an ACK.

The following sample code describes how to configure the message receiving operation:

MessageCallback messageCallback = new MessageCallback() {
    @Override
    public Action consume(MessageToken messageToken) {
        Message m = messageToken.getMessage();
        log.info("receive : " + new String(messageToken.getMessage().getPayload()));
        return MessageCallback.Action.CommitSuccess;
    }
};
messageClient.setMessageListener("/${YourProductKey}/#",messageCallback);

Parameter description:

  • The MessageToken parameter indicates the message body of the message receipt. You can use the MessageToken.getMessage() method to obtain the message body. The MessageToken parameter is required when you manually return ACKs.

    The message body contains the following information:

    public class Message {
        // The message body.
        private byte[] payload;
        // Topic 
        private String topic;
        // The message ID.
        private String messageId;
        // QoS
        private int qos;
    }

    For more information about the formats of various messages, see Data formats.

    Note To prevent message timing issues, we recommend that you determine the final device status based on the lastTime parameter in messages.
  • In the sample code, messageClient.setMessageListener("/${YourProductKey}/#",messageCallback); is a method that is used to specify topics for callbacks.

    You can specify topics for callbacks or use the generic callback.

    • Topic-specific callbacks

      A topic-specific callback has higher priority than the generic callback. When a message matches multiple topics, the callback with the topic whose elements rank higher in the lexicographical order is called and only one callback is performed.

      When you configure a callback, you can specify a topic with wildcards, for example, /${YourProductKey}/${YourDeviceName}/#.

      Example:
      messageClient.setMessageListener("/alEddfaXXXX/device1/#",messageCallback);
      // When the received message matches the specified topic, for example, "/alEddfaXXXX/device1/update", the callback with this topic is called.
    • Generic callback

      If you do not specify a topic for a callback, the generic callback is called.

      The following sample code describes how to configure the generic callback:
      messageClient.setMessageListener(messageCallback);
      // If the received message matches no specified topics that are configured for callbacks, the generic callback is called.
  • Configure ACK replies.

    After a QoS=1 message is consumed, an ACK must be sent as the reply. The HTTP/2 SDK allows you to send ACKs as replies both automatically and manually. By default, ACKs are automatically returned. In this example, no ACK reply setting is configured, so ACKs are automatically returned.

    • Automatically return ACKs: If the returned value of MessageCallback.consume is true, the HTTP/2 SDK automatically returns an ACK. If the returned value is false or an exception occurs, the HTTP/2 SDK does not return an ACK. If no ACK is returned for a QoS=1 message, the server sends the message again.
    • The following sample code describes how to manually return ACKs:
      CompletableFuture<Boolean> ack(MessageToken var1);

      The MessageToken request parameter is specified in the call to indicate the message for which an ACK is required. You can obtain the parameter value from the result of MessageCallback.

      The following sample code describes how to manually return ACKs:

      client.connect(messageToken -> {
          System.out.println(messageToken.getMessage());
          asyncHandleMessage(messageToken);
          return MessageCallback.Action.CommitAckManually;
      });
      public void asyncHandleMessage(MessageToken messageToken) {
        client.ack(messageToken)
      }

Documentation

  • For more information about limits on server-side subscriptions, see Limits.
  • For more information about the formats of various messages, see Data formats.