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 devices

  1. Log on to the IoT Platform console.
  2. In left-side navigation pane, choose Devices > Products.
  3. Click Create Product to create a thermometer product. You must obtain the productKey, such as a1uzcH0****.
    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 Product Details page, click the Topic Categories tab. On this tab, click Topic Category to add a custom topic category.

    For more information, see Custom topics.

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

    • /a1uzcH0****/${deviceName}/user/devmsg: Devices send messages to this topic. Set the Publish permission for this topic category.
    • /a1uzcH0****/${deviceName}/user/cloudmsg: Devices subscribe to this topic. Set the Subscribe permission for this topic category.
  6. On the Server-side Subscription tab, click Create Subscription to create an AMQP server-side subscription. Set Message Type to Device Upstream Notification and Message Type to Default Consumer Group.
    For more information, see Configure an AMQP server-side subscription.
  7. In the left-side navigation pane, click Devices. Then, add the device1 device to the created thermometer product. Obtain the device certificate information including ProductKey, DeviceName, and DeviceSecret.
    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 a client to IoT Platform by using the SDK for Java.
    Notice The consumer group in the AMQP server-side subscription must be in the same IoT Platform instance as the device.
  • 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 = "a1uzcH0****";
      final String deviceName = "device1";
      final String deviceSecret = "uwMTmVAMnxB***";
      final String region = "cn-shanghai";
    • Set the parameters to initialize the connection, including the MQTT connection parameters, device parameters, and 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}

    In actual business scenarios, you must modify the following parameter values.

    Parameter Example Description
    productKey a1uzcH0****

    The device authentication information. For more information, see Step 7 in the Create a product and devices section.

    deviceName device1
    deviceSecret uwMTmVAMnxB***
    region cn-shanghai The ID of the region where your IoT Platform instance resides. For more information about region IDs, see Regions and zones.
    request.topic "/" + productKey + "/" + deviceName + "/user/devmsg" The custom topic that has the Publish permission.
    request.payloadObj "{\"temperature\":35.0, \"time\":\"sometime\"}" The content of the custom message.

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);
    }

    You must change the value of the request.topic parameter to a custom topic that has the Subscribe permission.

  • Configure IoT Platform SDK to call the Pub operation to publish a message. For more information about the parameters, see Pub. For more information about how to configure the SDK, see Use IoT Platform SDK for Java.
    • Set the parameters to authenticate the device.
       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 encoded in Base64. 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

Note In actual business scenarios, you must modify the parameter values in the 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: