You can achieve Thing Specification Language (TSL)-based communication between devices and IoT Platform over the Alink protocol. Devices submit properties or events to IoT Platform, and IoT Platform delivers messages to devices to set properties or call services. This article describes how to achieve TSL-based communication by using the Java sample code.

Prerequisites

  • IoT Platform is activated.
  • A Java development environment is installed.

Create a product and a device

You must create a product and a device, and define TSL features for the product.

  1. Log on to the IoT Platform console.
  2. In left-side navigation pane, choose Devices > Products.
  3. Click Create Product to create a product.
    For more information, see Create a product.
  4. Click the name of the product to go to the Product Details page, and click the Define Feature tab to define the TSL model.

    In this example, the following properties, services, and events are defined.

    TSL-based communication

    For more information, see Add a TSL feature.

  5. In the left-side navigation pane, click Devices to create devices.
    This article provides the sample code to set properties of multiple devices and call services of multiple devices. Therefore, you must create at least two devices. For more information, see Create multiple devices at a time.

Download and install the SDK demo

The SDK demo includes the server-side sample code and device-side sample code.

  1. Click here to download the iotx-api-demo package Then, decompress the package.
  2. Open the Java development tool and import the decompressed iotx-api-demo folder.
  3. In the java directory, add the Maven dependencies to the pom file to import IoT Platform SDK and Link SDK.
    <!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-iot -->
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>aliyun-java-sdk-iot</artifactId>
        <version>6.5.0</version>
    </dependency>
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>aliyun-java-sdk-core</artifactId>
        <version>3.5.1</version>
    </dependency>
    <dependency>
      <groupId>com.aliyun.alink.linksdk</groupId>
      <artifactId>iot-linkkit-java</artifactId>
      <version>1.2.0.1</version>
      <scope>compile</scope>
    </dependency>
  4. In the config file in the java/src/main/resources/ directory, enter the required information for initialization.
    user.accessKeyID = <your accessKey ID>
    user.accessKeySecret = <your accessKey Secret>
    iot.regionId = <regionId>
    iot.productCode = Iot
    iot.domain = iot.<regionId>.aliyuncs.com
    iot.version = 2018-01-20
    Parameter Description
    accessKeyID The AccessKey ID of your Alibaba Cloud account.

    To create or view your AccessKey pair, log on to the Alibaba Cloud Management console. Move the pointer over your profile picture, and click AccessKey to go to the User Management page.

    accessKeySecret The AccessKey secret of you Alibaba Cloud account. Obtain the AccessKey secret in the same way as the AccessKey ID.
    regionId The ID of the region where your IoT devices are located. For more information about region IDs, see Regions and zones.

Submit properties and events by using Link SDK

Configure Link SDK to connect with IoT Platform and submit properties and events.

The ThingTemplate file in the java/src/main/com.aliyun.iot.api.common.deviceApi directory provides the sample code.

  • Configure the connection information.

    Replace the productKey, deviceName, and deviceSecret parameters in the sample code with your device certificate. Replace the regionId parameter with your region ID.

    public static void main(String[] args) {
            /**
             * The certificate information about the device. 
             */
            String productKey = "your productKey";
            String deviceName = "your deviceName";
            String deviceSecret = "your deviceSecret";
            /**
             * The information about the MQTT connection. 
             */
            String regionId = "your device regionId";
            ThingTemplate manager = new ThingTemplate();
    
            DeviceInfo deviceInfo = new DeviceInfo();
            deviceInfo.productKey = productKey;
            deviceInfo.deviceName = deviceName;
            deviceInfo.deviceSecret = deviceSecret;
    
            /**
             * The Java HTTP client supports TSLv1.2. 
             */
            System.setProperty("https.protocols", "TLSv2");
            manager.init(deviceInfo, regionId);
        }
  • Initialize the connection.
    public void init(final DeviceInfo deviceInfo, String region) {
            LinkKitInitParams params = new LinkKitInitParams();
            /**
             * Set the MQTT parameters for initialization.
             */
            IoTMqttClientConfig config = new IoTMqttClientConfig();
            config.productKey = deviceInfo.productKey;
            config.deviceName = deviceInfo.deviceName;
            config.deviceSecret = deviceInfo.deviceSecret;
            config.channelHost = deviceInfo.productKey + ".iot-as-mqtt." + region + ".aliyuncs.com:1883";        /**         * Specifies whether to receive offline messages.         * This parameter corresponds to the cleanSession field in the MQTT connection.         */        config.receiveOfflineMsg = false;        params.mqttClientConfig = config;        ALog.setLevel(LEVEL_DEBUG);        ALog.i(TAG, "mqtt connetcion info=" + params);        /**         * Pass in the device certificate for initialization.         */        params.deviceInfo = deviceInfo;        /**Establish a connection.**/        LinkKit.getInstance().init(params, new ILinkKitConnectListener() {            public void onError(AError aError) {                ALog.e(TAG, "Init Error error=" + aError);            }            public void onInitDone(InitResult initResult) {                ALog.i(TAG, "onInitDone result=" + initResult);                List<Property> properties =   LinkKit.getInstance().getDeviceThing().getProperties();                ALog.i(TAG, "Device properties" + JSON.toJSONString(properties));                List<Event> getEvents  =   LinkKit.getInstance().getDeviceThing().getEvents();                ALog.i(TAG, "Device events" + JSON.toJSONString(getEvents));                //Submit properties.                handlePropertySet("MicSwitch", new ValueWrapper.IntValueWrapper(3));                Map<String,ValueWrapper> values = new HashMap<>();
                    values.put("eventValue",new ValueWrapper.IntValueWrapper(0));
                    OutputParams outputParams = new OutputParams(values);
                    //Submit events.
                     handleEventSet("Offline_alarm",outputParams);
    
                }
            });
        }
             * Set the MQTT parameters for initialization. 
             */
            IoTMqttClientConfig config = new IoTMqttClientConfig();
            config.productKey = deviceInfo.productKey;
            config.deviceName = deviceInfo.deviceName;
            config.deviceSecret = deviceInfo.deviceSecret;
            config.channelHost = deviceInfo.productKey + ".iot-as-mqtt." + region + ".aliyuncs.com:1883";
            /**
             * Pass in the device certificate for initialization.  
             * This parameter corresponds to the cleanSession field in the MQTT connection. 
             */
            config.receiveOfflineMsg = false;
            params.mqttClientConfig = config;
            ALog.setLevel(LEVEL_DEBUG);
            ALog.i(TAG, "mqtt connetcion info=" + params);
    
            /**
             * Pass in the device certificate for initialization.  
             */
            params.deviceInfo = deviceInfo;
    
            /**Establish a connection. **/
            LinkKit.getInstance().init(params, new ILinkKitConnectListener() {
                public void onError(AError aError) {
                    ALog.e(TAG, "Init Error error=" + aError);
                }
    
                public void onInitDone(InitResult initResult) {
                    ALog.i(TAG, "onInitDone result=" + initResult);
    
                    List<Property> properties =   LinkKit.getInstance().getDeviceThing().getProperties();
    
                    ALog.i(TAG, "Device properties" + JSON.toJSONString(properties));
    
                    List<Event> getEvents  =   LinkKit.getInstance().getDeviceThing().getEvents();
    
                    ALog.i(TAG, "Device events" + JSON.toJSONString(getEvents));
    
                    //Submit properties.  
                    handlePropertySet("MicSwitch", new ValueWrapper.IntValueWrapper(3));
    
                    Map<String,ValueWrapper> values = new HashMap<>();
                    values.put("eventValue",new ValueWrapper.IntValueWrapper(0));
                    OutputParams outputParams = new OutputParams(values);
                    //Submit events. 
                     handleEventSet("Offline_alarm",outputParams);
    
                }
            });
        }
    Note The property and event identifiers in the code must be the same as the identifiers that are defined in the TSL model.
  • Configure Link SDK to submit properties.
    /**
         * The device submit properties in the Alink JSON format. 
         * @param identifier: the identifier of the property. 
         * @param value: the value of the property. 
         * @return
         */
        private void handlePropertySet(String identifier, ValueWrapper value ) {
            ALog.i(TAG, "Identifier of the property=" + identifier);
    
            Map<String, ValueWrapper> reportData = new HashMap<>();
            reportData.put(identifier, value);
    
            LinkKit.getInstance().getDeviceThing().thingPropertyPost(reportData, new IPublishResourceListener() {
    
                public void onSuccess(String s, Object o) {
                    // The property is submitted. 
                    ALog.i(TAG, "Submitted. onSuccess() called with: s = [" + s + "], o = [" + o + "]");
                }
    
                public void onError(String s, AError aError) {
                    // The property value fails to be submitted. 
                    ALog.i(TAG, "Failed to submit. onError() called with: s = [" + s + "], aError = [" + JSON.toJSONString(aError) + "]");
                }
            });
        }
  • Configure Link SDK to submit events.
    /**
         * The device submit events in the Alink JSON format. 
         * @param identifier: the identifier of the event. 
         * @param params: the parameters of the event. 
         * @return
         */
        private void handleEventSet(String identifyID, OutputParams params ) {
            ALog.i(TAG, "Identifier of the event=" + identifyID + "  params=" + JSON.toJSONString(params));
    
    
            LinkKit.getInstance().getDeviceThing().thingEventPost( identifyID,  params, new IPublishResourceListener() {
    
                public void onSuccess(String s, Object o) {
                    // The event is submitted. 
                    ALog.i(TAG, "Submitted. onSuccess() called with: s = [" + s + "], o = [" + o + "]");
                }
    
                public void onError(String s, AError aError) {
                    // Fails to submit the event. 
                    ALog.i(TAG, "Failed to submit. onError() called with: s = [" + s + "], aError = [" + JSON.toJSONString(aError) + "]");
                }
            });
        }

Send commands to set properties and call services by using IoT Platform SDK

  • Initialize a client.
    public class IotClient {
      private static String accessKeyID;
      private static String accessKeySecret;
      private static String regionId;
      private static String domain;
      private static String version;
      public static DefaultAcsClient getClient() {
        DefaultAcsClient client = null;
        Properties prop = new Properties();
        try {
          prop.load(Object.class.getResourceAsStream("/config.properties"));
          accessKeyID = prop.getProperty("user.accessKeyID");
          accessKeySecret = prop.getProperty("user.accessKeySecret");
          regionId = prop.getProperty("iot.regionId");
                domain = prop.getProperty("iot.domain");
                version = prop.getProperty("iot.version");
    
          IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyID, accessKeySecret);
          DefaultProfile.addEndpoint(regionId, regionId, prop.getProperty("iot.productCode"),
              prop.getProperty("iot.domain"));
          // Initialize the client. 
          client = new DefaultAcsClient(profile);
    
        } catch (Exception e) {
          LogUtil.print("Failed to initialize the client. exception:" + e.getMessage());
        }
        return client;
      }
        public static String getRegionId() {
            return regionId;
        }
        public static void setRegionId(String regionId) {
            IotClient.regionId = regionId;
        }
        public static String getDomain() {
            return domain;
        }
        public static void setDomain(String domain) {
            IotClient.domain = domain;
        }
        public static String getVersion() {
            return version;
        }
        public static void setVersion(String version) {
            IotClient.version = version;
        }
    }
  • Initialize the CommonRequest public class.

    The AbstractManager file in the java/src/main/com.aliyun.iot.api.common.openApi directory encapsulates the CommonRequest public class.

    public class AbstractManager {
        private static DefaultAcsClient client;
        static {
            client = IotClient.getClient();
        }
        /**
         *  Initialize the CommonRequest class. 
         * domain: the endpoint. 
         * version: the API version. 
         */
        public static CommonRequest executeTests(String action) {
            CommonRequest request = new CommonRequest();
            request.setDomain(IotClient.getDomain());
            request.setMethod(MethodType.POST);
            request.setVersion(IotClient.getVersion());
            request.setAction(action);
            return request;
        }
  • Call the API operations of IoT Platform to set properties and call services.

    The ThingManagerForPopSDk file in the java/src/main/com.aliyun.iot.api.common.openApi directory provides the sample code.

    • Call the SetDeviceProperty operation to set a device property.
      public static void SetDeviceProperty(String IotId, String ProductKey, String DeviceName , String Items) {
              SetDevicePropertyResponse response =null;
              SetDevicePropertyRequest request=new SetDevicePropertyRequest();
              request.setDeviceName(DeviceName);
              request.setIotId(IotId);
              request.setItems(Items);
              request.setProductKey(ProductKey);
      
              try {
                  response = client.getAcsResponse(request);
      
                  if (response.getSuccess() != null && response.getSuccess()) {
                      LogUtil.print("The device property is set.");
                      LogUtil.print(JSON.toJSONString(response));
                  } else {
                      LogUtil.print("Failed to set the device property.");
                      LogUtil.error(JSON.toJSONString(response));
                  }
      
              } catch (ClientException e) {
                  e.printStackTrace();
                  LogUtil.error("Failed to set the device property." + JSON.toJSONString(response));
              }
          }
    • Call the SetDevicesProperty operation to set properties of multiple devices.
      /**
           * Set properties of multiple devices. 
           *
           * @param ProductKey: the properties to be set.  
           * @param DeviceNames: Each property must be in the key:value format.  
           * @param Items: Data type: JSON String. This parameter is required.  
           *
           * @Des: the description. 
           */
          public static void SetDevicesProperty(String ProductKey, List<String> DeviceNames, String Items) {
              SetDevicesPropertyResponse response = new SetDevicesPropertyResponse();
              SetDevicesPropertyRequest request = new SetDevicesPropertyRequest();
              request.setDeviceNames(DeviceNames);
              request.setItems(Items);
              request.setProductKey(ProductKey);
      
              try {
                  response = client.getAcsResponse(request);
      
                  if (response.getSuccess() != null && response.getSuccess()) {
                      LogUtil.print("The device properties are set.");
                      LogUtil.print(JSON.toJSONString(response));
                  } else {
                      LogUtil.print("Failed to set device properties.");
                      LogUtil.error(JSON.toJSONString(response));
                  }
              } catch (ClientException e) {
                  e.printStackTrace();
                  LogUtil.error("Failed to set device properties." + JSON.toJSONString(response));
              }
          }
    • Call the InvokeThingService operation to call a device service.
           /**
           * @param Identifier: the identifier the service. This parameter is required. 
           * @param Args: the input parameters of the service. This parameter is required. 
           */
          public static InvokeThingServiceResponse.Data InvokeThingService(String IotId, String ProductKey, String DeviceName,
                                                                           String Identifier, String Args) {
              InvokeThingServiceResponse response =null;
              InvokeThingServiceRequest request = new InvokeThingServiceRequest();
              request.setArgs(Args);
              request.setDeviceName(DeviceName);
              request.setIotId(IotId);
              request.setIdentifier(Identifier);
              request.setProductKey(ProductKey);
      
              try {
                  response = client.getAcsResponse(request);
      
                  if (response.getSuccess() != null && response.getSuccess()) {
                      LogUtil.print("The service is implemented.");
                      LogUtil.print(JSON.toJSONString(response));
                  } else {
                      LogUtil.print("Failed to implement the service.");
                      LogUtil.error(JSON.toJSONString(response));
                  }
                  return response.getData();
      
              } catch (ClientException e) {
                  e.printStackTrace();
                  LogUtil.error("Failed to implement the service."  + JSON.toJSONString(response));
              }
              return null;
          }
      Note If you want to synchronously call services, set Invoking Method to Synchronization when you define TSL models. When you develop devices, you must write the code to process synchronous service calls.
    • Call the InvokeThingsService operation to call services of multiple devices.
           /**
           * @param Identifier: the identifier the service. This parameter is required. 
           * @param Args: the input parameters of the service. This parameter is required. 
           */
          public static void InvokeThingsService(String IotId, String ProductKey, List<String> DeviceNames,
                                                 String Identifier, String Args) {
              InvokeThingsServiceResponse response =null;
              InvokeThingsServiceRequest request = new InvokeThingsServiceRequest();
              request.setArgs(Args);
              request.setIdentifier(Identifier);
              request.setDeviceNames(DeviceNames);
              request.setProductKey(ProductKey);
      
      
              try {
                  response = client.getAcsResponse(request);
      
                  if (response.getSuccess() != null && response.getSuccess()) {
                      LogUtil.print("The device services are implemented.");
                      LogUtil.print(JSON.toJSONString(response));
                  } else {
                      LogUtil.print("Failed to implement the device services.");
                      LogUtil.error(JSON.toJSONString(response));
                  }
      
              } catch (ClientException e) {
                  e.printStackTrace();
                  LogUtil.error("Failed to implement the device services." + JSON.toJSONString(response));
              }
          }

Sample request:

public static void main(String[] args) {
        /**Enable devices to go online.
        String deviceName = "2pxuAQB2I7wGPmqq****";
        String deviceProductkey = "a1QbjI2***";
        //1. Set a device property. 
        SetDeviceProperty(null, deviceProductkey, deviceName,"{\"hue\":0}");
        //2 Set properties of multiple devices. 
        List<String>  deviceNames = new ArrayList<>();
        deviceNames.add(deviceName);
        SetDevicesProperty(deviceProductkey, deviceNames, "{\"hue\":0}");
        //3. Call a device service. 
        InvokeThingService(null, deviceProductkey, deviceName, "ModifyVehicleInfo", "{}");
        //4. Call services of multiple devices. 
        List<String>  deviceNamesService = new ArrayList<>();
        deviceNamesService.add(deviceName);
        InvokeThingsService(null, deviceProductkey, deviceNamesService, "ModifyVehicleInfo", "{}");
    }

Debug the SDKs

After you configure Link SDK and IoT Platform SDK, run these SDKs.

Check results:

  • View local logs. TSL-based communication
  • In the IoT Platform console, go to the Device Details page.
    • Click the Status tab to check the property values that the device submitted last time.
    • Click the Events tab to check the events that the device submitted last time.
    • Click the Invoke Service tab to check the records of service calls.
    TSL-based communication