You can establish 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 sends commands to devices to configure properties or call services. This topic provides sample Java code to describe how to establish TSL-based communication.

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. On the Overview page, find the instance and click the instance name to go to the Instance Details page.
    Notice Enterprise Edition instances are available only in the Japan (Tokyo) region. If your IoT Platform is not activated in the Japan (Tokyo) region, skip this step.
    Overview
  3. In left-side navigation pane, choose Devices > Products.
  4. On the Products page, click Create Product. On the Create Product page, specify a custom name for the product and select Custom Category. Use the default values for other parameters and click OK.
    For more information, see Create a product.
  5. On the Product Details page of the product, click Define Feature. On the Define Feature tab, define a TSL model.

    In this example, an event, a service, and two properties are added to the Default Module section, as shown in the following figure.

    This topic provides a sample TSL model that you can import. For more information about how to import a TSL model, see Batch add TSL features.

    TSL-based communication
  6. In the left-side navigation pane, click Devices. On the Devices page, click Add Device to create a device.
    You can use the sample code to batch configure device properties and batch call device services. You must create at least two devices. For more information, see Create multiple devices at a time.

Download and install an SDK demo

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

  1. Click iotx-api-demo to download the iotx-api-demo package and then decompress the package.
  2. Start the Java development tool and import the decompressed iotx-api-demo folder.
  3. Add the following Maven dependencies to the pom.xml file to import the IoT Platform SDK and a Link SDK:
    <!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-iot -->
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>aliyun-java-sdk-iot</artifactId>
        <version>7.33.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</version>
      <scope>compile</scope>
    </dependency>
  4. In the java/src/main/resources/ directory, open the config file and specify 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, perform the following steps: Log on to the Alibaba Cloud Management console. Move the pointer over your profile picture, and click AccessKey Management to go to the AccessKey Pair page.

    accessKeySecret The AccessKey secret of your Alibaba Cloud account. You can obtain the AccessKey secret the same way you obtain the AccessKey ID.
    regionId The ID of the region where your IoT devices reside. For more information about region IDs, see Regions and zones.

Submit properties and events by using Link SDK

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

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

  • Specify the connection information.

    Replace the values of the productKey, deviceName, and deviceSecret parameters in the sample code with the information about your device certificate. Replace the value of the url parameter with your MQTT endpoint. For more information about how to obtain an endpoint, see View the endpoint of an instance. The endpoint must include port 1883.

    public static void main(String[] args) {
            /**
             * The information about the device certificate. 
             */
            String productKey = "your productKey";
            String deviceName = "your deviceName";
            String deviceSecret = "your deviceSecret";
    
            /*TODO: Replace the following endpoint with the endpoint of your instance.
           */
            String  url = "iot-6d***ql.mqtt.iothub.aliyuncs.com:1883";
    
            /**
             * The information about the MQTT connection. 
             */
            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, url);
        }
  • Initialize the connection parameters.
    public void init(final DeviceInfo deviceInfo, String url) {
            LinkKitInitParams params = new LinkKitInitParams();
            /**
             * Configure the parameters for MQTT initialization. 
             */
            IoTMqttClientConfig config = new IoTMqttClientConfig();
            config.productKey = deviceInfo.productKey;
            config.deviceName = deviceInfo.deviceName;
            config.deviceSecret = deviceInfo.deviceSecret;
            config.channelHost = url;
            /**
             * Specify whether to receive offline messages. 
             * The cleanSession field that corresponds to the MQTT connection. 
             */
            config.receiveOfflineMsg = false;
            params.mqttClientConfig = config;
            ALog.setLevel(LEVEL_DEBUG);
            ALog.i(TAG, "mqtt connetcion info=" + params);
    
            /**
             * Configure the initialization parameters and specify the certificate information about the device. 
             */
            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, "The device properties" + JSON.toJSONString(properties));
    
                    List<Event> getEvents  =   LinkKit.getInstance().getDeviceThing().getEvents();
    
                    ALog.i(TAG, "List of device events" + JSON.toJSONString(getEvents));
    
                    /* Submit properties. TODO: Make sure that the properties that you want to submit are defined in the TSL model of the product. Example: MicSwitch. Otherwise, an error message is returned. */
                    handlePropertySet("MicSwitch", new ValueWrapper.IntValueWrapper(1));
    
                    /* Submit events. TODO: Make sure that the events that you want to submit are defined in the TSL model of the product. Example: Offline_alarm. Otherwise, an error message is returned. */
                    Map<String,ValueWrapper> values = new HashMap<>();
                    values.put("eventValue",new ValueWrapper.IntValueWrapper(0));
                    OutputParams outputParams = new OutputParams(values);
                    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 submits 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 failed 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 submits 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) {
                    // Failed to submit the event. 
                    ALog.i(TAG, "Failed to submit. onError() called with: s = [" + s + "], aError = [" + JSON.toJSONString(aError) + "]");
                }
            });
        }

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

  • Initialize a client.

    The IotClient file in the java/src/main/com.aliyun.iot.client directory contains the sample code.

    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. action: the name of the API operation. 
         * 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 configure properties and call services.

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

    • Call the SetDeviceProperty operation to configure a device property.
      public static void SetDeviceProperty(String InstanceId, 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);
              request.setIotInstanceId(InstanceId);
      
              try {
                  response = client.getAcsResponse(request);
      
                  if (response.getSuccess() != null && response.getSuccess()) {
                      LogUtil.print("The device property is configured.");
                      LogUtil.print(JSON.toJSONString(response));
                  } else {
                      LogUtil.print("Failed to configure the device property.");
                      LogUtil.error(JSON.toJSONString(response));
                  }
      
              } catch (ClientException e) {
                  e.printStackTrace();
                  LogUtil.error("Failed to configure the device property." + JSON.toJSONString(response));
              }
          }
    • Call the SetDevicesProperty operation to batch configure device properties.
      /**
           * Batch configure device properties. 
           *
           * @param ProductKey: the ProductKey of the product to which the devices whose properties you want to configure belong. 
           * @param DeviceNames: the DeviceNames of the devices whose properties you want to configure. 
           * @param Items: the property information that consists of multiple pairs of key-value JSON strings. This parameter is required. 
           *
           * @Des: the description. 
           */
          public static void SetDevicesProperty(String InstanceId, String ProductKey, List<String> DeviceNames, String Items) {
              SetDevicesPropertyResponse response = new SetDevicesPropertyResponse();
              SetDevicesPropertyRequest request = new SetDevicesPropertyRequest();
              request.setDeviceNames(DeviceNames);
              request.setItems(Items);
              request.setProductKey(ProductKey);
              request.setIotInstanceId(InstanceId);
      
              try {
                  response = client.getAcsResponse(request);
      
                  if (response.getSuccess() != null && response.getSuccess()) {
                      LogUtil.print("The properties are batch configured.");
                      LogUtil.print(JSON.toJSONString(response));
                  } else {
                      LogUtil.print("Failed to batch configure the device properties.");
                      LogUtil.error(JSON.toJSONString(response));
                  }
              } catch (ClientException e) {
                  e.printStackTrace();
                  LogUtil.error("Failed to batch configure the device properties." + JSON.toJSONString(response));
              }
          }
    • Call the InvokeThingService operation to call a device service.
           /**
           * @param Identifier: the identifier of the service. This parameter is required. 
           * @param Args: the input parameters that are required to start the service. This parameter is required. 
           */
          public static InvokeThingServiceResponse.Data InvokeThingService(String InstanceId, 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);
              request.setIotInstanceId(InstanceId);
      
              try {
                  response = client.getAcsResponse(request);
      
                  if (response.getSuccess() != null && response.getSuccess()) {
                      LogUtil.print("The service is executed.");
                      LogUtil.print(JSON.toJSONString(response));
                  } else {
                      LogUtil.print("Failed to execute the service.");
                      LogUtil.error(JSON.toJSONString(response));
                  }
                  return response.getData();
      
              } catch (ClientException e) {
                  e.printStackTrace();
                  LogUtil.error("Failed to execute the service." + JSON.toJSONString(response));
              }
              return null;
          }
      Note If you want to synchronously call services, set the Invoking Method parameter 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 batch call device services.
           /**
           * @param Identifier: the identifier of the service. This parameter is required. 
           * @param Args: the input parameters that are required to start the service. This parameter is required. 
           */
          public static void InvokeThingsService(String InstanceId, 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);
              request.setIotInstanceId(InstanceId);
      
              try {
                  response = client.getAcsResponse(request);
      
                  if (response.getSuccess() != null && response.getSuccess()) {
                      LogUtil.print("The services are called.");
                      LogUtil.print(JSON.toJSONString(response));
                  } else {
                      LogUtil.print("Failed to batch call the services.");
                      LogUtil.error(JSON.toJSONString(response));
                  }
      
              } catch (ClientException e) {
                  e.printStackTrace();
                  LogUtil.error("Failed to batch call the services." + JSON.toJSONString(response));
              }
          }

Sample request:

public static void main(String[] args) {
        /** The DeviceName of the online device and the Productkey of the product to which the online device belongs. */
        String deviceName = "2pxuAQB2I7wGPmqq***";
        String deviceProductkey = "a1QbjI2***";

        /** If you use an Enterprise Edition instance or a public instance of the new version, specify the instance ID for the InstanceId parameter. To obtain the instance ID, log on to the IoT Platform console and view the instance ID on the Overview page. 
         * If you use a public instance of the old version, leave the InstanceId parameter empty"". 
         */
        String InstanceId = "iot-***tl02";

        //1. Configure a device property. 
        SetDeviceProperty(InstanceId, null, deviceProductkey, deviceName,"{\"hue\":0}");
        //2. Batch configure device properties. 
        List<String>  deviceNames = new ArrayList<>();
        deviceNames.add(deviceName);
        SetDevicesProperty(InstanceId, deviceProductkey, deviceNames, "{\"hue\":0}");
        //3. Call a device service. 
        InvokeThingService(InstanceId, null, deviceProductkey, deviceName, "ModifyVehicleInfo", "{}");
        //4. Batch call device services. 
        List<String>  deviceNamesService = new ArrayList<>();
        deviceNamesService.add(deviceName);
        InvokeThingsService(null, deviceProductkey, deviceNamesService, "ModifyVehicleInfo", "{}");
    }

Debug the SDKs

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

Check results:

  • View local logs. TSL-based communication
  • On the Device Details page of the device, click Default Module.
    • The Status tab displays the property values that the device most recently submitted.
    • The Events tab displays the events that the device most recently submitted.
    • The Invoke Service tab displays the records of service calls.
    TSL-based communication