You can create custom topic categories in the IoT Platform console. Then, a device can send messages to a custom topic that belongs to a topic category. Your server can receive the messages by using an AMQP SDK. Your server can also call the Pub API operation to send commands to the device. Communication based on custom topics does not use the TSL model. In this case, you can define the data structure of the message.

Background information

In this example, an electronic thermometer exchanges data with a server at a regular interval. The thermometer sends the real-time temperature data to the server, and the server sends the precision setting command to the thermometer.

Communication based on custom topics

Prepare the development environment

In this example, both devices and IoT Platform use SDKs for Java. You need to prepare the Java development environment first. You can download Java from the Java official website and install the Java development environment.

Create a product and a device

  1. Log on to the IoT Platform console.
  2. In the left-side navigation pane, choose Devices > Products.
  3. Click Create Product to create a thermometer product.
    For more information, see Create a product.
  4. After the thermometer product is created, find it on the Products page and click View in the Actions column.
  5. On the Products Details page, click the Topic Categories tab. Then, you can create topic categories for the product.

    For more information, see Edit a topic category.

    In this example, you must define the following two topic categories:

    • /${productKey}/${deviceName}/user/devmsg: Devices send messages to this topic. Set the Publish permission for this topic category.
    • /${productKey}/${deviceName}/user/cloudmsg: Devices subscribe to this topic. Set the Subscribe permission for this topic category.
  6. Click the Server-side Subscription tab. Then, you can create an AMQP server-side subscription to subscribe to Device Upstream Notification.
    For more information, see Configure an AMQP server-side subscription.
  7. In the left-side navigation pane, choose Devices > Devices. Then, you can add a thermometer device to the thermometer product.
    For more information, see Create a device.

The device sends a message to the server

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

Topic-based communication

This section describes how to configure the server and the device to implement the process.

  • The server receives messages by using an AMQP client. Therefore, you must configure the AMQP client to connect with IoT Platform and listen to device messages.

    For more information, see Connect an AMQP client to IoT Platform.

    The following example shows how to use a Qpid JMS 0.47.0 client as an AMQP client and connect with IoT Platform.

    • Add the following Maven dependency:
      <!-- amqp 1.0 qpid client -->
       <dependency>
         <groupId>org.apache.qpid</groupId>
         <artifactId>qpid-jms-client</artifactId>
         <version>0.57.0</version>
       </dependency>
       <!-- util for base64-->
       <dependency>
         <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.10</version>
      </dependency>
    • Download the demo package. Then, use the sample code to connect the client with IoT Platform and listen to device messages. For more information, see Connect a client to IoT Platform by using the SDK for Java.
  • Configure the device SDK to connect the device with IoT Platform and enable the device to send messages.
    • Set the parameters to authenticate the device.
      final String productKey = "XXXXXX";
      final String deviceName = "XXXXXX";
      final String deviceSecret = "XXXXXXXXX";
      final String region = "XXXXXX";
    • Set the parameters to initialize the connection, including the MQTT connection parameters, device parameters, TSL model parameters.
      LinkKitInitParams params = new LinkKitInitParams();
      // Set the MQTT connection parameters. Link SDK 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";
      // Set the device parameters. 
      DeviceInfo deviceInfo = new DeviceInfo();
      deviceInfo.productKey = productKey;
      deviceInfo.deviceName = deviceName;
      deviceInfo.deviceSecret = deviceSecret;
      // Set the initial status of the device. 
      Map<String, ValueWrapper> propertyValues = new HashMap<String, ValueWrapper>();
      
      params.mqttClientConfig = config;
      params.deviceInfo = deviceInfo;
      params.propertyValues = propertyValues;
    • Initialize the connection.
      // Initialize the connection and configure the callback function that is used after the initialization succeeds. 
      LinkKit.getInstance().init(params, new ILinkKitConnectListener() {
           @Override
           public void onError(AError aError) {
               System.out.println("Init error:" + aError);
           }
      
           // Implement the callback function. 
           @Override
           public void onInitDone(InitResult initResult) {
               System.out.println("Init done:" + initResult);
           }
       });
    • Send a message from the device.

      After the device is connected to IoT Platform, you can send a message to the specified topic. Replace the content of the onInitDone function, as shown in 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 configure the callback functions that are used after 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 a message to the device

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

Topic-based communication
  • Configure the device SDK to subscribe to a topic.

    For more information about how to specify the parameters to authenticate the device and initialize the connection, see the sample code in the The device sends a message to the server section.

    The device must subscribe to a specific topic before the device can receive messages sent by the server.

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

    // Implement the callback function. 
    @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 configure the callback functions that are used after the subscription succeeds or fails. 
        LinkKit.getInstance().subscribe(request, new IConnectSubscribeListener() {
            @Override
            public void onSuccess() {
                System.out.println("");
            }
    
            @Override
            public void onFailure(AError aError) {
    
            }
        });
    
        // Set the listener that listens to downstream messages. 
        IConnectNotifyListener notifyListener = new IConnectNotifyListener() {
            // Configure the callback function that is used after the downstream messages are 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 Platform SDK so that IoT Platform can publish a message by calling the Pub API operation.
    • Set the parameters to verify identities.
       String regionId = "XXXXXX";
       String accessKey = "XXXXXX";
       String accessSecret = "XXXXXXXXX";
       final String productKey = "XXXXXX";
    • Set the connection parameters.
      // Set the parameters of the client. 
      DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKey, accessSecret);
      IAcsClient client = new DefaultAcsClient(profile);
    • Set the parameters that are used to publish 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 MessageContent parameter. The message content must be Base64 encoded. Otherwise, the message content appears as 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: Sample code

You can download the sample code in this article. To download the code, click PubSubDemo.

For more information about how to connect an AMQP client with IoT Platform, see the following articles: