Alibaba Cloud Alibaba Cloud

物联物网联平网台 平台 BeBset Psrta Pctricaecstices

Document Version: 20200922

Document Version: 20200922 物联网平台 Best Practices · Legal disclaimer

Legal disclaimer

Alibaba Cloud reminds you to carefully read and fully understand the terms and conditions of this legal disclaimer before you read or use this document. If you have read or used this document, it shall be deemed as your total acceptance of this legal disclaimer.

1. You shall download and obtain this document from the Alibaba Cloud website or other Alibaba Cloud-authorized channels, and use this document for your own legal business activities only. The content of this document is considered confidential information of Alibaba Cloud. You shall strictly abide by the confidentiality obligations. No part of this document shall be disclosed or provided to any third party for use without the prior written consent of Alibaba Cloud.

2. No part of this document shall be excerpted, translated, reproduced, transmitted, or disseminated by any organization, company or individual in any form or by any means without the prior written consent of Alibaba Cloud.

3. The content of this document may be changed because of product version upgrade, adjustment, or other reasons. Alibaba Cloud reserves the right to modify the content of this document without notice and an updated version of this document will be released through Alibaba Cloud- authorized channels from time to time. You should pay attention to the version changes of this document as they occur and download and obtain the most up-to-date version of this document from Alibaba Cloud-authorized channels.

4. This document serves only as a reference guide for your use of Alibaba Cloud products and services. Alibaba Cloud provides this document based on the "status quo", "being defective", and "existing functions" of its products and services. Alibaba Cloud makes every effort to provide relevant operational guidance based on existing technologies. However, Alibaba Cloud hereby makes a clear statement that it in no way guarantees the accuracy, integrity, applicability, and reliability of the content of this document, either explicitly or implicitly. Alibaba Cloud shall not take legal responsibility for any errors or lost profits incurred by any organization, company, or individual arising from download, use, or trust in this document. Alibaba Cloud shall not, under any circumstances, take responsibility for any indirect, consequential, punitive, contingent, special, or punitive damages, including lost profits arising from the use or trust in this document (even if Alibaba Cloud has been notified of the possibility of such a loss).

5. By law, all the contents in Alibaba Cloud documents, including but not limited to pictures, architecture design, page layout, and text description, are intellectual property of Alibaba Cloud and/or its affiliates. This intellectual property includes, but is not limited to, trademark rights, patent rights, copyrights, and trade secrets. No part of this document shall be used, modified, reproduced, publicly transmitted, changed, disseminated, distributed, or published without the prior written consent of Alibaba Cloud and/or its affiliates. The names owned by Alibaba Cloud shall not be used, published, or reproduced for marketing, advertising, promotion, or other purposes without the prior written consent of Alibaba Cloud. The names owned by Alibaba Cloud include, but are not limited to, "Alibaba Cloud", "Aliyun", "HiChina", and other brands of Alibaba Cloud and/or its affiliates, which appear separately or in combination, as well as the auxiliary signs and patterns of the preceding brands, or anything similar to the company names, trade names, trademarks, product or service names, domain names, patterns, logos, marks, signs, or special descriptions that third parties identify as Alibaba Cloud and/or its affiliates.

6. Please directly contact Alibaba Cloud for any errors of this document.

> Document Version:20200922 I 物联网平台 Best Practices · Document conventions

Document conventions

Style Description Example

A danger notice indicates a situation Danger: Danger that will cause major system changes, Resetting will result in the loss of faults, physical injuries, and other user configuration data. adverse results.

Warning: A warning notice indicates a situation Warning that may cause major system changes, Restarting will cause business faults, physical injuries, and other interruption. About 10 minutes are adverse results. required to restart an instance.

A caution notice indicates warning Notice: Notice information, supplementary If the weight is set to 0, the server instructions, and other content that no longer receives new requests. the user must understand.

Note: A note indicates supplemental Note instructions, best practices, tips, and You can use Ctrl + A to select all other content. files.

Closing angle brackets are used to Click Settings> Network> Set network > indicate a multi-level menu cascade. type.

Bold formatting is used for buttons , Bold menus, page names, and other UI Click OK. elements.

Run the cd /d :/window command to Courier font Courier font is used for commands enter the Windows system folder.

Italic formatting is used for bae log list --instanceid Italic parameters and variables. Instance_ID

This format is used for an optional [] or [a|b] value, where only one item can be ipconfig [-all|-t] selected.

This format is used for a required {} or {a|b} value, where only one item can be switch {active|stand} selected.

> Document Version:20200922 I 物联网平台 Best Practices · Table of Contents

Table of Contents

1.Device access 06

1.1. Access IoT Platform by using Paho 06

1.1.1. Using Paho MQTT C client 06

1.1.2. Using Paho MQTT Java client 15

1.1.3. Using Paho MQTT Go client 19

1.1.4. Using Paho MQTT C# client 23

1.1.5. Using Paho MQTT Android client 28

1.1.6. Troubleshooting 35

1.2. Access IoT Platform by using CoAP 36

1.3. Access IoT Platform by using HTTP 46

1.4. Dynamic registration based on unique-certificate-per-pro…duct aut5h3entication by using MQTT

1.5. Dynamic registration based on unique-certificate-per-pro…duct aut6h0entication by using HTTPS

1.6. Access IoT Platform by using MQTT.fx 66

1.7. Connect Android Things to IoT Platform 74

1.8. Connect an RTOS device to IoT Platform by using a TCP… commun80ication module

1.8.1. Overview 80

1.8.2. Create a product and add a device 80

1.8.3. Build a development environment for devices 81

1.8.4. Develop for a device 87

1.9. Connect a bare-metal device to IoT Platform by using T…CP 94

1.9.1. Overview 94

1.9.2. Create a product and add a device 95

1.9.3. Build a development environment for devices 95

1.9.4. Provision a device 100

1.10. Connect a serial device to IoT Platform by using a DTU… device 106

1.10.1. Overview 106

> Document Version:20200922 I Best Practices · Table of Contents 物联网平台

1.10.2. Configure a product and a device 107

1.10.3. Configure a DTU device 113

1.10.4. Test data communication 114

1.11. Connect environmental sensors to IoT Platform by usin…g HTTPS11 5

1.12. Connect a Linux device to IoT Platform 121

2.Communications 125

2.1. Use custom topics for communication 125

2.2. Control Raspberry Pi servers from IoT Platform 137

2.3. TSL model communication 151

2.4. Communication between devices 165

2.4.1. M2M communication 165

2.4.2. Use the rules engine to establish M2M communicati…on 165

2.4.3. Use topic-based message routing to establish M2M c…ommun1i6c9ation

2.5. Create a server-side subscription of the MNS type 170

2.6. Parse pass-through data from devices 175

3.Device management 181

3.1. Set desired property values to control the light bulb sta…tus 181

3.2. Call a synchronous service 197

3.3. Connect a sub-device to IoT Platform 209

4.Data forwarding 210

4.1. Integrate with a weather service 210

4.2. Upload temperature and humidity data to DingTalk cha…tbots 217

II > Document Version:20200922 物联网平台 Best Practices · Device access

1.Device access 1.1. Access IoT Platform by using Paho 1.1.1. Using Paho MQTT C client

This topic describes how to use the open-source Paho MQTT C/C++ client to access Alibaba Cloud IoT Platform for message exchanges. IoT Internet of Things Paho.MQTT. C

Prerequisites

Products and devices are created in IoT Platform.

For more information, see Create a product and Create a device.

Prepare the development environment

In this example, Ubuntu 16.04-LTS is used for building the development environment. Run the following command to build the development environment.

sudo apt-get update sudo apt-get install build-essential git sed cmake

Download the Paho MQTT library for C

Run the following command to clone the C language version of the Paho MQTT library.

git clone [email protected]:eclipse/paho.mqtt.embedded-c.git

Note The demo example uses the master branch. The commit id is 29ab2aa29c5e47794284376d7f8386cfd54c3eed .

The Paho MQTT for C project provides three sub-projects: MQTTPacket: Provides serialization and deserialization of MQTT data packets and some additional helper functions. MQTTClient: Encapsulates the high-level C++ client program generated by MQTTPacket. MQTTClient-C: Encapsulates the high-level C client program generated by MQTTPacket. MQTTClient-C includes:

> Document Version:20200922 6 Best Practices · Device access 物联网平台

├── CMakeLists.txt ├── samples │ ├── CMakeLists.txt │ ├── FreeRTOS │ └── linux ├── src │ ├── CMakeLists.txt │ ├── FreeRTOS │ ├── MQTTClient.c │ ├── MQTTClient.h │ ├── cc3200 │ └── linux └── test ├── CMakeLists.txt └── test1.c

The samples directory provides sample code for FreeRTOS and Linux systems. The src directory provides the code for MQTTClient and network drivers for porting to FreeRTOS, CC3200, and Linux.

For more information about the Paho MQTT APIs, see MQTTClient.h.

Connect to IoT Platform

1. Click aiot_mqtt_signal.c to view and download the source code that is provided by Alibaba Cloud to calculate the MQTT connection parameters. The aiot_mqtt_signal.c file defines the function aiotMqttSign(). The following describes the function. Prototype

int aiotMqttSign(const char *productKey, const char *deviceName, const char *deviceSecret, char clientId[150], char username[65], char password[65]);

Functionality Calculates the username, password, and clientId parameters for MQTT connections to IoT Platform. Input parameters

Parameter Type Description

The ProductKey of the product to which the device productKey const char * belongs.

deviceName const char * The name of the device.

deviceSecret const char * The device key.

7 > Document Version:20200922 物联网平台 Best Practices · Device access

Output parameters

Parameter Type Description

username char * The username required for the MQTT connection.

password char * The password required for the MQTT connection.

clientId char * The ID of the MQTT client.

Return codes

Return code Description

0 Successful

-1 Failed

2. Add the program file that enables the device to access IoT Platform. You must write a program that calls the function aiotMqttSign() in the aiot_mqtt_sign.c file to calculate the MQTT connection parameters. Then use the parameters to connect to IoT Platform for communications. The development instructions and sample code are as follows. Call the aiotMqttSign() function to generate the three connection parameters clientId, username, and password.

> Document Version:20200922 8 Best Practices · Device access 物联网平台

#define EXAMPLE_PRODUCT_KEY "a11xsrW****"

#define EXAMPLE_DEVICE_NAME "paho_****" #define EXAMPLE_DEVICE_SECRET "Y877Bgo8X5owd3lcB5wWDjryNPoB****"

extern int aiotMqttSign(const char *productKey, const char *deviceName, const char *deviceSecr et,

char clientId[150], char username[65], char password[65]);

/* invoke aiotMqttSign to generate mqtt connect parameters */ char clientId[150] = {0};

char username[65] = {0}; char password[65] = {0};

if ((rc = aiotMqttSign(EXAMPLE_PRODUCT_KEY, EXAMPLE_DEVICE_NAME, EXAMPLE_DEVICE_SECRE T, clientId, username, password) <0)) {

printf("aiotMqttSign -%0x4x\n", -rc); return -1;

} printf("clientid: %s\n", clientId);

printf("username: %s\n", username); printf("password: %s\n", password);

Connect to IoT Platform. Configure the following items: Call the NetworkInit and NetworkConnect functions to establish a TCP connection. Call the MQTTClientInit function to initialize the MQTT client. Configure the MQTTPacket_connectData structure for the MQTT connection parameters.

The sample code is as follows:

9 > Document Version:20200922 物联网平台 Best Practices · Device access

/* network init and establish network to aliyun IoT platform */ NetworkInit(&n);

rc = NetworkConnect(&n, host, port); printf("NetworkConnect %d\n", rc);

/* init mqtt client */ MQTTClientInit(&c, &n, 1000, buf, sizeof(buf), readbuf, sizeof(readbuf));

/* set the default message handler */

c.defaultMessageHandler = messageArrived;

/* set mqtt connect parameter */ MQTTPacket_connectData data = MQTTPacket_connectData_initializer; data.willFlag = 0;

data.MQTTVersion = 3; data.clientID.cstring = clientId;

data.username.cstring = username; data.password.cstring = password;

data.keepAliveInterval = 60; data.cleansession = 1;

printf("Connecting to %s %d\n", host, port);

rc = MQTTConnect(&c, &data);

printf("MQTTConnect %d, Connect aliyun IoT Cloud Success! \n", rc);

Publish a message. Call the MQTTPublish() function and publish messages to a custom topic.

> Document Version:20200922 10 Best Practices · Device access 物联网平台

char *pubTopic = "/"EXAMPLE_PRODUCT_KEY"/"EXAMPLE_DEVICE_NAME"/user/update";

int cnt = 0; unsigned int msgid = 0;

while (! toStop) { MQTTYield(&c, 1000);

if (++cnt % 5 == 0) {

MQTTMessage msg = { QOS1,

0, 0,

0, "Hello world", strlen("Hello world"),

}; msg.id = ++msgid;

rc = MQTTPublish(&c, pubTopic, &msg); printf("MQTTPublish %d, msgid %d\n", rc, msgid);

} }

For more information about topics, seeWhat is a topic?. Subscribe to a topic and obtain messages from the cloud.

void messageArrived(MessageData* md)

{ MQTTMessage* message = md->message;

printf("%.*s\t", md->topicName->lenstring.len, md->topicName->lenstring.data);

printf("%.*s\n", (int)message->payloadlen, (char*)message->payload); }

char *subTopic = "/"EXAMPLE_PRODUCT_KEY"/"EXAMPLE_DEVICE_NAME"/user/get";

printf("Subscribing to %s\n", subTopic); rc = MQTTSubscribe(&c, subTopic, 1, messageArrived);

printf("MQTTSubscribe %d\n", rc);

For more information about the communication methods of devices, servers, and IoT Platform, see Communication methods.

11 > Document Version:20200922 物联网平台 Best Practices · Device access

3. Copy the aiot_mqtt_signal.c file and the file coded in Step 2 to ../paho.mqtt.embedded-c/MQ TTClient-C/samples/linux and then compile the project.

Demo

Use the demo code to access IoT Platform. 1. Download the demo package. Then decompress the package. After decompression, the code package contains the following two files:

.

+-- aiot_c_demo.c +-- aiot_mqtt_sign.c

File Description

The code in this file is used to generate MQTT connection parameters. When you run aiot_c_demo.c, it calls the aiotMqttSign() function to aiot_mqtt_sign.c calculate the connection parameters, such as username, password, and clientId.

This file contains the code for connections and communication between aiot_c_demo.c the device and IoT Platform.

2. In the aiot_c_demo.c file, change the device information to your device information. Replace the EXAMPLE_PRODUCT_KEY, EXAMPLE_DEVICE_NAME, and EXAMPLE_DEVICE_SECRET parameter values with your device certificate information.

Replace cn-shanghai in char *host = EXAMPLE_PRODUCT_KEY".iot-as-mqtt.cn-shanghai.aliyuncs. com" with the region ID of your IoT Platform device. For more information about region IDs, see . 3. Move the aiot_mqtt_signal.c and modified aiot_c_demo.c files to the ../paho.mqtt.embedded -c/MQTTClient-C/samples/linux directory of the Paho project. 4. Compile the project and run the program. The following shows two methods to compile executable programs. Use CMake.

> Document Version:20200922 12 Best Practices · Device access 物联网平台

a. Add aiot_c_demo.c and aiot_mqtt_signal.c to the CMakeLists.txt file of the /paho.mqtt. embedded-c/MQTTClient-C/samples/linux directory. The content of the modified CMakeLists.txt file is as follows:

add_executable( stdoutsubc

stdoutsub.c )

add_executable(

aiot_c_demo aiot_c_demo.c aiot_mqtt_sign.c )

target_link_libraries(stdoutsubc paho-embed-mqtt3cc paho-embed-mqtt3c) target_include_directories(stdoutsubc PRIVATE ".. /../src" ".. /../src/linux") target_compile_definitions(stdoutsubc PRIVATE MQTTCLIENT_PLATFORM_HEADER=MQTTLin ux.h)

target_link_libraries(aiot_c_demo paho-embed-mqtt3cc paho-embed-mqtt3c) target_include_directories(aiot_c_demo PRIVATE ".. /../src" ".. /../src/linux") target_compile_definitions(aiot_c_demo PRIVATE MQTTCLIENT_PLATFORM_HEADER=MQTTLi nux.h)

b. Go back to the /paho.mqtt.embedded-c directory and run the following command to complete the compilation.

mkdir build.paho cd build.paho cmake .. make

c. After the compilation is completed, in the /paho.mqtt.embedded-c/build.paho directory, run the following command to run the program.

. /MQTTClient-C/samples/linux/aiot_c_demo

Use the build.sh file.

13 > Document Version:20200922 物联网平台 Best Practices · Device access

a. Modify the build.sh file in the /paho.mqtt.embedded-c/MQTTClient-C/samples/linux directory by copying the following code into the file.

cp .. /../src/MQTTClient.c . sed -e 's/""/"MQTTLinux.h"/g' .. /../src/MQTTClient.h > MQTTClient.h

gcc \ -o aiot_c_demo \ -I .. /../src -I .. /../src/linux -I .. /.. /.. /MQTTPacket/src \ aiot_mqtt_sign.c aiot_c_demo.c \ MQTTClient.c \

.. /../src/linux/MQTTLinux.c \ .. /.. /.. /MQTTPacket/src/MQTTFormat.c \ .. /.. /.. /MQTTPacket/src/MQTTPacket.c \ .. /.. /.. /MQTTPacket/src/MQTTDeserializePublish.c \

.. /.. /.. /MQTTPacket/src/MQTTConnectClient.c \ .. /.. /.. /MQTTPacket/src/MQTTSubscribeClient.c \ .. /.. /.. /MQTTPacket/src/MQTTSerializePublish.c \ .. /.. /.. /MQTTPacket/src/MQTTConnectServer.c \ .. /.. /.. /MQTTPacket/src/MQTTSubscribeServer.c \

.. /.. /.. /MQTTPacket/src/MQTTUnsubscribeServer.c \ .. /.. /.. /MQTTPacket/src/MQTTUnsubscribeClient.c

b. After the modification, run the command ./build.sh in the current directory to complete the compilation. After compilation, the aiot_c_demo executable file is generated.

c. Run the ./aiot_c_demo command to run the program.

After the program starts, the local log for accessing IoT Platform is as follows:

> Document Version:20200922 14 Best Practices · Device access 物联网平台

clientid: paho_mqtt&a11xsrW****|timestamp=2524608000000,_v=sdk-c-1.0.0,securemode=3,signmet hod=hmacsha256,lan=C|

username: paho_mqtt&a11xsrW**** password: 36E955DC3D9D012EF62C80657A29328B1CFAE6186C611A17DC7939FAB637**** NetworkConnect 0 Connecting to a11xsrW****.iot-as-mqtt.cn-shanghai.aliyuncs.com 443 MQTTConnect 0, Connect aliyun IoT Cloud Success!

Subscribing to /a11xsrW****/paho_mqtt/user/get MQTTSubscribe 0 MQTTPublish 0, msgid 1 MQTTPublish 0, msgid 2

MQTTPublish 0, msgid 3 MQTTPublish 0, msgid 4 MQTTPublish 0, msgid 5 ...

In the IoT Platform console, you can view the device status and logs. Choose Devices > Devices. You can view that the status of the device is Online. Choose Maintenance > Device Log. You can view the Device Activity Analysis and Upstream Analysis logs. 1.1.2. Using Paho MQTT Java client

This topic describes how to use the Paho MQTT Java client to access Alibaba Cloud IoT Platform for message exchanges. IoT Internet of Things Paho.MQTT Java

Prerequisites

Products and devices are created in IoT Platform, and a LightSwitch property is defined on the Define Feature tab page.

For more information, see Create a product, Create a device, and Add a TSL feature.

Prepare the development environment

The following describes the development environment for this example. Operating system: macOS JDK Version: JDK8 Integrated development environment: IntelliJ IDEA Community Edition

Download the Java Paho MQTT library

Add the following dependencies to the Maven project:

15 > Document Version:20200922 物联网平台 Best Practices · Device access

org.eclipse.paho

org.eclipse.paho.client.mqttv3 1.2.0

Connect to IoT Platform

1. Click MqttSign.java to download the code provided by Alibaba Cloud for calculating the MQTT connection parameters. The MqttSign.java file defines the MqttSign class. Prototype

class MqttSign

Functionality Calculates the username, password, and clientId parameters for MQTT connections to IoT Platform. Methods

Type Method description

calculate(String productKey, String deviceName, String deviceSecret)

public void You can call this method to calculate the username, password, and clientid based on the productKey, deviceName, and deviceSecret of the device.

getUsername()

public String You can call this method to obtain the MQTT connection parameter username.

getPassword()

public String You can call this method to obtain the MQTT connection parameter password.

getClientid()

public String You can call this method to obtain the MQTT connection parameter clientid.

2. Open IntelliJ IDEA and create a project.

> Document Version:20200922 16 Best Practices · Device access 物联网平台

3. Import the MqttSign.java file into the project. 4. In the project, add a program file that enables devices to access IoT Platform. You must write a program which can call the MqttSign class in the MqttSign.java file to calculate the parameters for MQTT connections and connect to IoT Platform. The instructions for development and sample code are as follows. Use the MqttSign class to calculate the MQTT connection parameters.

String productKey = "****";

String deviceName = "Lamp"; String deviceSecret = "ga7XA6KdlEeiPXQPpRbAjOZXwG8y****";

// Calculate the MQTT connection parameters

MqttSign sign = new MqttSign(); sign.calculate(productKey, deviceName, deviceSecret);

System.out.println("username: " + sign.getUsername()); System.out.println("password: " + sign.getPassword());

System.out.println("clientid: " + sign.getClientid());

Call the Paho MQTT client to connect to IoT Platform.

// The domain name to access IoT Platform.

String port = "443"; String broker = "ssl://" + productKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com" + ":" + port;

// Paho MQTT client

MqttClient sampleClient = new MqttClient(broker, sign.getClientid(), persistence);

// Connection parameters for Paho MQTT. MqttConnectOptions connOpts = new MqttConnectOptions(); connOpts.setCleanSession(true);

connOpts.setKeepAliveInterval(180); connOpts.setUserName(sign.getUsername()); connOpts.setPassword(sign.getPassword().toCharArray()); sampleClient.connect(connOpts);

System.out.println("Broker: "+ broker +" Connected");

Note Replace cn-shanghai in the code with the region ID of your IoT Platform device. For more information about region IDs, see .

Publish messages.

17 > Document Version:20200922 物联网平台 Best Practices · Device access

The following sample code is used to report the value of LightSwitch property to IoT Platform.

// Publish messages with Paho MQTT String topic = "/sys/" + productKey + "/" + deviceName + "/thing/event/property/post"; String content = "{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":1}}"; MqttMessage message = new MqttMessage(content.getBytes()); message.setQos(0); sampleClient.publish(topic, message);

For more information about the TSL data format, see Device properties, events, and services.

If you want to use custom topics for communication, see What is a topic?. Subscribe to topics for obtaining messages sent from IoT Platform. You can use the following example to subscribe to the topic for the response messages of IoT Platform after the property values are reported.

class MqttPostPropertyMessageListener implements IMqttMessageListener { @Override public void messageArrived(String var1, MqttMessage var2) throws Exception { System.out.println("reply topic : " + var1); System.out.println("reply payload: " + var2.toString()); } } ... // The topic to which Paho MQTT subscribes for messages

String topicReply = "/sys/" + productKey + "/" + deviceName + "/thing/event/property/post_repl y"; sampleClient.subscribe(topicReply, new MqttPostPropertyMessageListener());

For more information about the communication methods of devices, servers, and IoT Platform, see Communication methods. 5. Compile the project.

Demo

Use the demo code to access IoT Platform. 1. Download the demo package. Then decompress the package. 2. Open IntelliJ IDEA and import the sample project aiot-java-demo from the demo package. 3. In the src/main/java/com.aliyun.iot/App file, change the device information to your device information. Replace the productKey, deviceName, and deviceSecret with your device certificate information.

Replace cn-shanghai in String broker = "ssl://" + productKey + ".iot-as-mqtt.cn-shanghai.aliyun

> Document Version:20200922 18 Best Practices · Device access 物联网平台

cs.com" + ":" + port; with the region ID of your IoT Platform device. For more information about region IDs, see . 4. Run the App program. In the IoT Platform console, you can view the device status and logs. Choose Devices > Devices. You can view that the status of the device is Online. Choose Maintenance > Device Log. You can view the Device Activity Analysis and Upstream Analysis logs. 1.1.3. Using Paho MQTT Go client

This topic describes how to use the Golang library of Paho MQTT to access Alibaba Cloud IoT Platform for message exchanges. IoT IoT Platform Paho MQTT Go

Prerequisites

Products and devices are created in IoT Platform.

For more information, see Create a product and Create a device.

Prepare the development environment

Install the Go language package. Run the following command for installation on macOS:

brew install go

Run the following commands for installation in Ubuntu:

sudo apt-get install golang-go

For Windows, download the installation package from the Golang official website.

Download the Go library for Paho MQTT

For more information about the Paho project and supported development languages, see Eclipse Paho Downloads. Use the following command to download the Go library for Paho MQTT and the dependencies.

go get github.com/eclipse/paho.mqtt.golang go get github.com/gorilla/websocket go get golang.org/x/net/proxy

Connect to IoT Platform

1. Click MqttSign.go to view and download the source code provided by Alibaba Cloud to calculate the MQTT connection parameters.

The MqttSign.go file defines the function for calculating the MQTT connection parameters for devices to access IoT Platform. The following describes the parameters.

19 > Document Version:20200922 物联网平台 Best Practices · Device access

Prototype

type AuthInfo struct { password, username, mqttClientId string; }

func calculate_sign(clientId, productKey, deviceName, deviceSecret, timeStamp string) AuthInfo

;

Functionality Calculates the username, password, and mqttClientId parameters for MQTT connections to IoT Platform. Input parameters

Parameter Type Description

The ProductKey of the product to which the device ProductKey String belongs.

deviceName String The name of the device.

deviceSecret String The device key.

The device ID. It can be set to a string of no more than clientId String 64 characters. We recommend that you use the serial number or MAC address of the device ID.

timeStamp String The timestamp of the current time in milliseconds.

Output parameters

The return value of this function is an AuthInfo structure with the following parameters.

Parameter Type Description

username String The username required for the MQTT connection.

password String The password required for the MQTT connection.

mqttClientId String The ID of the MQTT client.

2. Add the program file that enables the device to access IoT Platform. You must write a program which can call the MqttSign.go file to calculate the MQTT connection parameters and connect to IoT Platform. The development instructions and code examples are as follows. Set the device information.

> Document Version:20200922 20 Best Practices · Device access 物联网平台

// set the device info, include product key, device name, and device secret var productKey string = "a1Zd7n5***" var deviceName string = "testdevice" var deviceSecret string = "UrwclDV33NaFSmk0JaBxNTqgSrJW****"

// set timestamp, clientid, subscribe topic and publish topic

var timeStamp string = "1528018257135" var clientId string = "192.168.****" var subTopic string = "/" + productKey + "/" + deviceName + "/user/get"; var pubTopic string = "/" + productKey + "/" + deviceName + "/user/update";

Set MQTT connection information. Call the calculate_sign function defined in MqttSign.go. Calculate the username, password, and mqttClientId based on the input parameters clientId, productKey, deviceName, deviceSecret, and timeStamp. Add the information to the opts structure.

// set the login broker url var raw_broker bytes.Buffer raw_broker.WriteString("tls://") raw_broker.WriteString(productKey) Raw_broker.WriteString (".iot-as-mqtt.cn-shanghai.aliyuncs.com: 1883") opts := MQTT.NewClientOptions().AddBroker(raw_broker.String());

// calculate the login auth info, and set it into the connection options auth := calculate_sign(clientId, productKey, deviceName, deviceSecret, timeStamp) opts.SetClientID(auth.mqttClientId) opts.SetUsername(auth.username) opts.SetPassword(auth.password) opts.SetKeepAlive(60 * 2 * time.Second) opts.SetDefaultPublishHandler(f)

Note Replace cn-shanghai in the code with the region ID of your IoT Platform device. For more information about region IDs, see .

Call the MQTT Connect() function to access IoT Platform.

// create and start a client using the above ClientOptions c := MQTT.NewClient(opts)

if token := c.Connect(); token.Wait() && token.Error() ! = nil { panic(token.Error()) } fmt.Print("Connect aliyun IoT Cloud Sucess\n");

21 > Document Version:20200922 物联网平台 Best Practices · Device access

Call the Publish function to publish messages. You must specify target topics and the payload of messages.

// publish 5 messages to pubTopic("/a1Zd7n5****/deng/user/update") for i := 0; i < 5; i++ { fmt.Println("publish msg:", i) text := fmt.Sprintf("ABC #%d", i)

token := c.Publish(pubTopic, 0, false, text) fmt.Println("publish msg: ", text) token.Wait() time.Sleep(2 * time.Second) }

For more information about communication topics, see What is a topic?. Call the Subscribe function to subscribe to topics and receive messages from the cloud.

// subscribe to subTopic("/a1Zd7n5***/deng/user/get") and request messages to be delivere d

if token := c.Subscribe(subTopic, 0, nil); token.Wait() && token.Error()! = nil { fmt.Println(token.Error()) os.Exit(1) } fmt.Print("Subscribe topic " + subTopic + " success\n");

For more information about the communication methods of devices, servers, and IoT Platform, see Communication methods. 3. Compile the project.

Demo

Use the demo code to access IoT Platform. 1. Download the demo package and extract the files. aiot-go-demo contains the following files.

File Description

This file contains the code for generating the connection parameters that are used to access IoT Platform over MQTT. When you run the iot.g MqttSign.go o file, the calculate_sign function is called to calculate the connection parameters username, password, and mqttClientId.

This file contains the code for connections and communications iot.go between the device and IoT Platform.

The root certificate of IoT Platform is required for devices to access IoT x509 Platform.

> Document Version:20200922 22 Best Practices · Device access 物联网平台

2. In the iot.go file, change the device information to your device information. You can use tools such as Linux vi to modify the iot.go file. Replace the productKey, deviceName, and deviceSecret with your device certificate information. (Optional) Replace the timeStamp and clientId parameter values. clientId can be replaced with the serial number and MAC address of your physical device.

Replace cn-shanghai in raw_broker.WriteString (".iot-as-mqtt.cn-shanghai.aliyuncs.com: 1883") with the region ID of your IoT Platform device. For more information about region IDs, see . 3. Run the following command in the command line to run the iot.go file.

go run iot.go MqttSign.go

After running, you can view the local logs.

clientId192.168.****deviceNametestdeviceproductKeya1Zd7n5****timestamp1528018257135 1b865320fc183cc747041c9faffc9055fc45**** Connect aliyun IoT Cloud Sucess Subscribe topic /a1Zd7n5****/testdevice/user/get success publish msg: 0

publish msg: ABC #0 publish msg: 1 publish msg: ABC #1 publish msg: 2 publish msg: ABC #2 publish msg: 3 publish msg: ABC #3 publish msg: 4 publish msg: ABC #4

publish msg: 5 publish msg: ABC #5

In the IoT Platform console, you can view the device status and logs. Choose Devices > Devices. You can view that the status of the device is Online. Choose Maintenance > Device Log. You can view the Device Activity Analysis and Upstream Analysis logs. 1.1.4. Using Paho MQTT C# client

This topic describes how to use the C# library of Paho MQTT to connect to Alibaba Cloud IoT Platform and perform Thing Specification Language (TSL) data communication.

IoT Internet of Things Paho-MQTT C# .NET

Prerequisites

23 > Document Version:20200922 物联网平台 Best Practices · Device access

Products and devices are created in IoT Platform, and a LightSwitch property is defined on the Define Feature tab page.

For more information, see Create a product, Create a device, and Add a TSL feature.

Context

The MQTT C# open-source code provided by Paho contains the Visual Studio solutions. Each project of a solution can generate corresponding class libraries for different .NET platforms. In this example, a console project is created in the solution and the project calls the MQTT class library of Paho to connect to Alibaba Cloud IoT Platform.

Prepare the development environment

The operating system and development tools used in this example are as follows: Operating system: Window 10 Integrated development environment: Visual Studio 2019 Install the development environment: 1. Download Visual Studio 2019 Community Edition, and decompress the package. 2. Run the Visual Studio Installer. Select .NET desktop development and click Installation.

Download the Paho client

Visit Eclipse Paho and download Paho MQTT for C# from the GitHub page for .Net(C #). The demo code uses the master branch. The commit id is b2e64bc4485721a0bd5ae805d9f4917e8d040e81 .

The source code provided by Paho contains the Visual Studio solution file M2MMqtt.sln. You can use it to develop your own device.

Connect to IoT Platform

1. Click MqttSign.cs to view and download the code provided by Alibaba Cloud to calculate the MQTT connection parameters.

The MqttSign.cs file defines the MqttSign class.

Prototype

class MqttSign

Functionality Calculates the username, password, and clientId parameters for MQTT connections to IoT Platform. Methods

Type Method description

> Document Version:20200922 24 Best Practices · Device access 物联网平台

Type Method description

calculate(String productKey, String deviceName, String deviceSecret)

public bool You can call this method to calculate the username, password, and clientid based on the productKey, deviceName, and deviceSecret of the device.

getUsername()

public String You can call this method to obtain the MQTT connection parameter username.

getPassword()

public String You can call this method to obtain the MQTT connection parameter password.

getClientid()

public String You can call this method to obtain the MQTT connection parameter clientid.

2. Open Visual Studio. Import the Visual Studio solution file M2Mqtt.sln from the source code of Paho, and create a project. 3. Import the MqttSign.cs file to the project. 4. In the application project, add a program file that enables devices to access IoT Platform. You must write a program which can call the MqttSign class in the MqttSign.cs file to calculate the MQTT connection parameters. The instructions for development and sample code are as follows. Calculate the MQTT connection parameters. Use the MqttSign class in the MqttSign.cs file to calculate the MQTT connection parameters.

25 > Document Version:20200922 物联网平台 Best Practices · Device access

String productKey = "a1X2bEn****"; String deviceName = "example1";

String deviceSecret = "ga7XA6KdlEeiPXQPpRbAjOZXwG8y****";

// Calculate the MQTT connection parameters MqttSign sign = new MqttSign(); sign.calculate(productKey, deviceName, deviceSecret);

Console.WriteLine("username: " + sign.getUsername()); Console.WriteLine("password: " + sign.getPassword()); Console.WriteLine("clientid: " + sign.getClientid());

Call the Paho MQTT client to connect to IoT Platform.

// Use Paho to connect to Alibaba Cloud IoT Platform int port = 443; String broker = productKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com";

MqttClient mqttClient = new MqttClient(broker, port, true, MqttSslProtocols.TLSv1_2, null, null); mqttClient.Connect(sign.getClientid(), sign.getUsername(), sign.getPassword());

Console.WriteLine("Broker: " + broker + " Connected");

Note Replace cn-shanghai in the code with the region ID of your IoT Platform device. For more information about region IDs, see .

Publish messages. The following sample code is used to report the value of the property LightSwitch.

// Paho MQTT publishes a message String topic = "/sys/" + productKey + "/" + deviceName + "/thing/event/property/post"; String message = "{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}"; mqttClient.Publish(topic, Encoding.UTF8.GetBytes(message));

For more information about the TSL data format, see Device properties, events, and services.

If you want to use custom topics for communication, see What is a topic?. Subscribe to topics to receive data sent from IoT Platform. In the following example, the topic subscribed is used for receiving response messages from IoT Platform after property values are reported.

> Document Version:20200922 26 Best Practices · Device access 物联网平台

// The topic to which Paho MQTT subscribes for messages String topicReply = "/sys/" + productKey + "/" + deviceName + "/thing/event/property/post_repl y";

mqttClient.MqttMsgPublishReceived += MqttPostProperty_MqttMsgPublishReceived; mqttClient.Subscribe(new string[] { topicReply }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_MOS T_ONCE }); ... private static void MqttPostProperty_MqttMsgPublishReceived(object sender, uPLibrary.Networ king.M2Mqtt.Messages.MqttMsgPublishEventArgs e) { Console.WriteLine("reply topic :" + e.Topic); Console.WriteLine("reply payload:" + e.Message.ToString());

}

For more information about the communication methods of devices, servers, and IoT Platform, see Communication methods. 5. Compile the project.

Demo

1. Download the demo package. The demo package contains the complete program for devices to access IoT Platform and report property values.

File Description

The code for calculating MQTT connection parameters. When you run Pr MqttSign.cs ogram.cs, it calls the MqttSign() function to calculate the connection parameters, such as username, password, and clientId.

This file contains the code for a device to connect to IoT Platform and Program.cs communicate with IoT Platform.

2. Open Visual Studio 2019 Community Edition and select Open Project/Solution. 3. Import the aiot-csharp-demo file from the demo package. 4. In the Program.cs file, change the device information to your device information. Replace the productKey, deviceName, and deviceSecret with your device certificate information.

Replace cn-shanghai in String broker = productKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com"; with the region ID of your IoT Platform device. For more information about region IDs, see . 5. Run the Program.cs program to access IoT Platform. After the program is connected, you can view the success messages for the connection, data reporting, and message subscription.

27 > Document Version:20200922 物联网平台 Best Practices · Device access

... broker: a1X2bEn****.iot-as-mqtt.cn-shanghai.aliyuncs.com Connected ... publish: {"id":"1","version":"1.0","params":{"LightSwitch":0}} ...

subscribe: /sys/a1X2bEn****/example1/thing/event/property/post_reply ...

In the IoT Platform console, you can view the device status and logs. Choose Devices > Devices. You can view that the status of the device is Online. Choose Maintenance > Device Log. You can view the Device Activity Analysis and Upstream Analysis logs. 1.1.5. Using Paho MQTT Android client

This topic describes how to use Paho Android Service to access Alibaba Cloud IoT Platform and send and receive data. IoT Internet of Things Paho.MQTT Android

Prerequisites

Products and devices are created in IoT Platform.

For more information, see Create a product and Create a device.

Context

The Paho Android Service is an MQTT client library based on the Java Paho MQTT Library.

Prepare the development environment

In this example, Android Studio is of version 3.5.1 and Gradle is of version 3.5.1. Visit the Android Studio official website to download Android Studio. For more information about Android development, see the Android Studio official documentation.

Install Paho Android client

1. Create an Android project. 2. In the Gradle file, add the Paho Android client dependencies. In this example, PahoAndroidClient 1.1.1 is used. In the build.gradle project, add the Paho repository address. This example uses the release repository.

repositories { maven { url "https://repo.eclipse.org/content/repositories/paho-releases/" }

}

> Document Version:20200922 28 Best Practices · Device access 物联网平台

In the build.gradle project, add Paho Android Service. In this example, the Paho Android Service 1.1.1 is used. It is based on paho.client.mqttv3-1.1.0.

dependencies { implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0' implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'

}

3. To bind an app to the Paho Android Service, you add the following information to AndroidMa nifest.xml. Add the following services.

Add required permissions for the Paho MQTT Service.

Connect to IoT Platform

1. Click AiotMqttOption.java to download the source code provided by Alibaba Cloud to calculate the MQTT connection parameters. The AiotMqttOption.java file defines the AiotMqttOption() class. Prototype

class AiotMqttOption

Functionality Calculates the username, password, and clientId parameters for MQTT connections to IoT Platform. Methods

Type Method description

getMqttOption(String productKey, String deviceName, String deviceS ecret) public AiotMqttOption You can call this method to calculate the username, password, and clientid based on the productKey, deviceName, and deviceSecret of the device.

29 > Document Version:20200922 物联网平台 Best Practices · Device access

Type Method description

getUsername()

public String You can call this method to obtain the MQTT connection parameter username.

getPassword()

public String You can call this method to obtain the MQTT connection parameter password.

getClientid()

public String You can call this method to obtain the MQTT connection parameter clientid.

2. Import AiotMqttOption.java to the Android project. 3. In the Android project, add a program file that enables devices to access IoT Platform. You must write a program which can call the AiotMqttOption() class in the AiotMqttOption.java file to calculate the MQTT connection parameters for communications with IoT Platform. The development instructions and sample code are as follows.

Calculate the MQTT connection parameters clientId,username, and password. Configure the username and password parameters in the MqttConnectOptions object.

> Document Version:20200922 30 Best Practices · Device access 物联网平台

final private String PRODUCTKEY = "a11xsrW****";

final private String DEVICENAME = "paho_android"; final private String DEVICESECRET = "tLMT9QWD36U2SArglGqcHCDK9rK9****";

/* Obtain the MQTT connection information clientId, username, and password. */ AiotMqttOption aiotMqttOption = new AiotMqttOption().getMqttOption(PRODUCTKEY, DEVICENA

ME, DEVICESECRET); if (aiotMqttOption == null) {

Log.e(TAG, "device info error"); } else {

clientId = aiotMqttOption.getClientId(); userName = aiotMqttOption.getUsername();

passWord = aiotMqttOption.getPassword();

}

/* Create an MqttConnectOptions object and configure the username and password. */ MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();

mqttConnectOptions.setUserName(userName); mqttConnectOptions.setPassword(passWord.toCharArray());

Connect the device to IoT Platform.

Create an MqttAndroidClient object, and set the callback interface. Use the mqttConnectOptions object to call the connect() method and establish the connection.

31 > Document Version:20200922 物联网平台 Best Practices · Device access

/* Create an MqttAndroidClient object and set a callback interface. */ mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), host, clientId);

mqttAndroidClient.setCallback(new MqttCallback() { @Override

public void connectionLost(Throwable cause) {

Log.i(TAG, "connection lost"); }

@Override

public void messageArrived(String topic, MqttMessage message) throws Exception { Log.i(TAG, "topic: " + topic + ", msg: " + new String(message.getPayload()));

}

@Override

public void deliveryComplete(IMqttDeliveryToken token) { Log.i(TAG, "msg delivered");

} });

/* Establish an MQTT connection */

try { mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {

@Override

public void onSuccess(IMqttToken asyncActionToken) { Log.i(TAG, "connect succeed");

subscribeTopic(SUB_TOPIC);

}

@Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) {

Log.i(TAG, "connect failed");

} });

} catch (MqttException e) {

e.printStackTrace(); }

Publishes messages.

> Document Version:20200922 32 Best Practices · Device access 物联网平台

Encapsulate the publish method.

public void publishMessage(String payload) { try {

if (mqttAndroidClient.isConnected() == false) { mqttAndroidClient.connect();

}

MqttMessage message = new MqttMessage();

message.setPayload(payload.getBytes()); message.setQos(0);

mqttAndroidClient.publish(PUB_TOPIC, message,null, new IMqttActionListener() { @Override

public void onSuccess(IMqttToken asyncActionToken) { Log. I (TAG, "publish succeed! ") ;

}

@Override

public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.i(TAG, "publish failed!") ;

} });

} catch (MqttException e) { Log.e(TAG, e.toString());

e.printStackTrace(); }

}

For more information about communication topics, seeWhat is a topic?.

Encapsulate the subscribe() method. You can use this method to subscribe to a specified topic and obtain messages from the cloud.

33 > Document Version:20200922 物联网平台 Best Practices · Device access

public void subscribeTopic(String topic) { try {

mqttAndroidClient.subscribe(topic, 0, null, new IMqttActionListener() { @Override

public void onSuccess(IMqttToken asyncActionToken) { Log.i(TAG, "subscribed succeed");

}

@Override

public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.i(TAG, "subscribed failed");

} });

} catch (MqttException e) {

e.printStackTrace();

} }

For more information about the communication methods of devices, servers, and IoT Platform, see Communication methods. 4. Compile the project.

Demo

Use the Demo code to access the IoT Platform. 1. Click here to download the Demo package and decompress it. 2. Import the aiot-csharp-demo file to Android Studio. 3. In the MainActivity file of the app/src/main/java/com.linkkit.aiot_android_demo directory, replace the device information with your device information. Replace the productKey, deviceName, and deviceSecret with your device information.

Replace cn-shanghai in final String host = "tcp://" + PRODUCTKEY + ".iot-as-mqtt.cn-shanghai.a liyuncs.com:443"; with the region ID of your IoT Platform device. For more information about region IDs, see . 4. Create and run the application. After running the application, you can view the local logs in Logcat.

> Document Version:20200922 34 Best Practices · Device access 物联网平台

2019-12-04 19:44:01.824 5952-5987/com.linkkit.aiot_android_demo W/OpenGLRenderer: Failed to c

hoose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without... 2019-12-04 19:44:01.829 5952-5987/com.linkkit.aiot_android_demo D/EGL_emulation: eglCreateCon

text: 0xec073240: maj 3 min 0 rcv 3 2019-12-04 19:44:01.830 5952-5987/com.linkkit.aiot_android_demo D/EGL_emulation: eglMakeCurre

nt: 0xec073240: ver 3 0 (tinfo 0xec09b470) 2019-12-04 19:44:01.852 5952-5987/com.linkkit.aiot_android_demo W/Gralloc3: mapper 3.x is not su

pported

2019-12-04 19:44:01.854 5952-5987/com.linkkit.aiot_android_demo D/HostConnection: createUniqu e: call

......

2019-12-04 19:44:01.860 5952-5987/com.linkkit.aiot_android_demo D/eglCodecCommon: allocate: A sk for block of size 0x1000

2019-12-04 19:44:01.861 5952-5987/com.linkkit.aiot_android_demo D/eglCodecCommon: allocate: io ctl allocate returned offset 0x3ff706000 size 0x2000

2019-12-04 19:44:01.897 5952-5987/com.linkkit.aiot_android_demo D/EGL_emulation: eglMakeCurre

nt: 0xec073240: ver 3 0 (tinfo 0xec09b470) 2019-12-04 19:44:02.245 5952-6023/com.linkkit.aiot_android_demo D/AlarmPingSender: Register al

armreceiver to MqttServiceMqttService.pingSender.a11xsrW****.paho_android|timestamp=1575459 841629,_v=sdk-android-1.0.0,securemode=2,signmethod=hmacsha256|

2019-12-04 19:44:02.256 5952-6023/com.linkkit.aiot_android_demo D/AlarmPingSender: Schedule n ext alarm at 1575459902256

2019-12-04 19:44:02.256 5952-6023/com.linkkit.aiot_android_demo D/AlarmPingSender: Alarm sche ule using setExactAndAllowWhileIdle, next: 60000

2019-12-04 19:44:02.272 5952-5952/com.linkkit.aiot_android_demo I/AiotMqtt: connect succeed

2019-12-04 19:44:02.301 5952-5952/com.linkkit.aiot_android_demo I/AiotMqtt: subscribed succeed

In the IoT Platform console, you can view the device status and logs. Choose Devices > Devices. You can view that the status of the device is Online. Choose Maintenance > Device Log. You can view the Device Activity Analysis and Upstream Analysis logs. 1.1.6. Troubleshooting

If a device fails to establish MQTT connections with IoT Platform, you can troubleshoot the problem based on the error code.

IoT Platform uses the standard MQTT protocol. For more information about the MQTT protocol, see Standard MQTT protocol. The following table lists the response codes.

35 > Document Version:20200922 物联网平台 Best Practices · Device access

Response code Response message Description

0 0x00 Connection Accepted The connection is established.

The error message returned because 0x01 Connection Refused, the server does not support the MQTT 1 unacceptable protocol version protocol version that is used by the device.

The error message returned because 0x02 Connection Refused, identifier 2 the server does not support the UTF-8 rejected encoded client ID.

The error message returned because 0x03 Connection Refused, Server the MQTT service is unavailable even 3 unavailable though the network connection has been established.

The error message returned because 0x04 Connection Refused, bad user 4 the format of the username or name or password password parameter is invalid.

0x05 Connection Refused, not The error message returned because 5 authorized the device is not authorized.

1.2. Access IoT Platform by using CoAP

This topic describes how to connect a device to IoT Platform by using Constrained Application Protocol (CoAP).

CoAP is suitable for devices such as NB-IoT devices that have constrained resources and run at low power. For more information about how to connect a device to IoT Platform by using CoAP, see Establish connections over CoAP.

Note The feature is available only in the China (Shanghai) region.

When you connect a device to IoT Platform by using CoAP, you must specify the required parameters, generate a signature for the device, and perform other operations. Eclipse Californium-based sample code is used as an example to describe the configuration process. To ensure data security, symmetric encryption is applied.

pom.xml

Add the following dependencies to the pom.xml file to import the Californium open-source framework, Apache Commons toolkit, and Alibaba fastjson package.

> Document Version:20200922 36 Best Practices · Device access 物联网平台

org.eclipse.californium californium-core

2.0.0-M17

org.apache.commons

commons-lang3 3.5

commons-codec

commons-codec 1.13

com.alibaba fastjson

1.2.61

Sample code

/* * Copyright © 2019 Alibaba. All rights reserved.

*/

package com.aliyun.iot.demo;

import java.io.IOException; import java.nio.charset.StandardCharsets;

import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;

import java.util.Set; import java.util.SortedMap;

import java.util.TreeMap;

import javax.crypto.Cipher;

import javax.crypto.Mac; import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.SecretKeySpec;

37 > Document Version:20200922 物联网平台 Best Practices · Device access

import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex;

import org.apache.commons.lang3.RandomUtils;

import org.eclipse.californium.core.CoapClient; import org.eclipse.californium.core.CoapResponse;

import org.eclipse.californium.core.Utils; import org.eclipse.californium.core.coap.CoAP;

import org.eclipse.californium.core.coap.CoAP.Code; import org.eclipse.californium.core.coap.CoAP.Type;

import org.eclipse.californium.core.coap.MediaTypeRegistry; import org.eclipse.californium.core.coap.Option;

import org.eclipse.californium.core.coap.OptionNumberRegistry;

import org.eclipse.californium.core.coap.OptionSet; import org.eclipse.californium.core.coap.Request;

import org.eclipse.californium.elements.exception.ConnectorException;

import com.alibaba.fastjson.JSONObject;

/** * The following Eclipse Californium-based code shows how to connect a device to IoT Platform by usin

g CoAP.

* For more information about how to develop custom code and specify the required parameters, see t he Use the symmetric encryption method Section in Establish connections over CoAP.

*/ public class IotCoapClientWithAes {

// ======The start of the section where you can specify the required parameters=

======// The ID of the region. Only the China (Shanghai) region is available.

private static String regionId = "cn-shanghai";

// The key of the product. private static String productKey = "The productKey of your device";

// The name of the device. private static String deviceName = "The deviceName of your device";

// The key of the device. private static String deviceSecret = "The deviceSecret of your device";

// ======The end of the section where you can specify the required parameters======

// Set the HMAC_ALGORITHM parameter to hmacsha1 or hmacmd5. The value that you set must be th

> Document Version:20200922 38 Best Practices · Device access 物联网平台

e same as that of the signmethod parameter.

private static final String HMAC_ALGORITHM = "hmacsha1";

// The endpoint that is used to authenticate CoAP clients. The port number of the endpoint is 5682 if you use symmetric encryption.

private static String serverURI = "coap://" + productKey + ".coap." + regionId + ".link.aliyuncs.com:56 82";

// The topic to which messages are sent. In the IoT Platform console, you can create a custom topic and grant the publish permission to devices.

private static String updateTopic = "/" + productKey + "/" + deviceName + "/user/update";

// token option private static final int COAP2_OPTION_TOKEN = 2088;

// seq option private static final int COAP2_OPTION_SEQ = 2089;

// Specify the SHA-256 encryption algorithm. private static final String SHA_256 = "SHA-256";

private static final int DIGITAL_16 = 16;

private static final int DIGITAL_48 = 48;

// Create a CoAP client. private CoapClient coapClient = new CoapClient();

// The validity period of a token is seven days. After a token expires, you must obtain a new token. private String token = null;

private String random = null; @SuppressWarnings("unused")

private long seqOffset = 0;

/** * Initialize a CoAP client

*

* @param productKey The key of the product * @param deviceName The name of the device

* @param deviceSecret The key of the device */

public void connect(String productKey, String deviceName, String deviceSecret) { try {

39 > Document Version:20200922 物联网平台 Best Practices · Device access

try {

// The endpoint for authentication. String uri = serverURI + "/auth";

// Only the POST method is available. Request request = new Request(Code.POST, Type.CON);

// Specify options

OptionSet optionSet = new OptionSet(); optionSet.addOption(new Option(OptionNumberRegistry.CONTENT_FORMAT, MediaTypeRegistr

y.APPLICATION_JSON)); optionSet.addOption(new Option(OptionNumberRegistry.ACCEPT, MediaTypeRegistry.APPLICATI

ON_JSON));

request.setOptions(optionSet);

// Specify the endpoint that you can use to authenticate the device request.setURI(uri);

// Specify the required parmeters for an authentication request

request.setPayload(authBody(productKey, deviceName, deviceSecret));

// Send the authentication request

CoapResponse response = coapClient.advanced(request); System.out.println(Utils.prettyPrint(response));

System.out.println();

// Parse the response JSONObject json = JSONObject.parseObject(response.getResponseText());

token = json.getString("token"); random = json.getString("random");

seqOffset = json.getLongValue("seqOffset");

} catch (ClientException e) { e.printStackTrace();

} catch (IOException e) { e.printStackTrace();

} }

/**

* Send messages

* @param topic The topic to which messages are sent.

> Document Version:20200922 40 Best Practices · Device access 物联网平台

@param topic The topic to which messages are sent.

* @param payload The contents of messages. */

public void publish(String topic, byte[] payload) { try {

// The endponit of the topic. The syntax of a topic is /topic/${topic}. String uri = serverURI + "/topic" + topic;

// Use seq=RandomUtils.nextInt() to encrypt the seq option by using the AES encryption algorit hm.

String shaKey = encod(deviceSecret + "," + random); byte[] keys = Hex.decodeHex(shaKey.substring(DIGITAL_16, DIGITAL_48));

byte[] seqBytes = encrypt(String.valueOf(RandomUtils.nextInt()).getBytes(StandardCharsets.U TF_8), keys);

// Only the POST method is available

Request request = new Request(CoAP.Code.POST, CoAP.Type.CON);

// Specify options

OptionSet optionSet = new OptionSet(); optionSet.addOption(new Option(OptionNumberRegistry.CONTENT_FORMAT, MediaTypeRegistr

y.APPLICATION_JSON)); optionSet.addOption(new Option(OptionNumberRegistry.ACCEPT, MediaTypeRegistry.APPLICATI

ON_JSON)); optionSet.addOption(new Option(COAP2_OPTION_TOKEN, token));

optionSet.addOption(new Option(COAP2_OPTION_SEQ, seqBytes));

request.setOptions(optionSet);

// Specify the endpoint of the topic. request.setURI(uri);

// Specify the payload parmameter.

request.setPayload(encrypt(payload, keys));

// Send messages.

CoapResponse response = coapClient.advanced(request); System.out.println(Utils.prettyPrint(response));

// Parse the result.

String result = null; if (response.getPayload() ! = null) {

41 > Document Version:20200922 物联网平台 Best Practices · Device access

result = new String(decrypt(response.getPayload(), keys)); }

System.out.println("Received: " + result);

System.out.println(); } catch (ConnectorException e) {

e.printStackTrace(); } catch (IOException e) {

e.printStackTrace(); } catch (DecoderException e) {

e.printStackTrace(); }

}

/**

* Generate the required parameters for authentication *

* @param productKey The name of the product * @param deviceName The name of the device

* @param deviceSecret The key of the device * @return An authentication request

*/

private String authBody(String productKey, String deviceName, String deviceSecret) {

// Create an authentication request JSONObject body = new JSONObject();

body.put("productKey", productKey); body.put("deviceName", deviceName);

body.put("clientId", productKey + "." + deviceName); //signMap.put("timestamp", String.valueOf(System.currentTimeMillis()));

body.put("signmethod", HMAC_ALGORITHM);

body.put("seq", DIGITAL_16); body.put("sign", sign(body, deviceSecret));

System.out.println("----- auth body -----");

System.out.println(body.toJSONString());

return body.toJSONString(); }

/** * Generate a signature for a device

> Document Version:20200922 42 Best Practices · Device access 物联网平台

* Generate a signature for a device

* * @param params The required parameters that you can use to generate a signature.

* @param deviceSecret The key of the device. * @return The signature in the hexadecimal format.

*/ private String sign(JSONObject params, String deviceSecret) {

// Sort request parameters in the alphabetical order Set keys = getSortedKeys(params);

// Remove the sign, signmethod, version, and resources parameters.

keys.remove("sign"); keys.remove("signmethod");

keys.remove("version"); keys.remove("resources");

// Obtain the plaintext of the signature. StringBuffer content = new StringBuffer();

for (String key : keys) { content.append(key);

content.append(params.getString(key)); }

// Generate a signature.

String sign = encrypt(content.toString(), deviceSecret);

System.out.println("sign content=" + content); System.out.println("sign result=" + sign);

return sign;

}

/** * Convert a JSON object to a set of key-value pairs.

*

* @param json The JSON object to be converted. * @return A set of key-value pairs that are converted from a JSON object.

*/ private Set getSortedKeys(JSONObject json) {

SortedMap map = new TreeMap(); for (String key : json.keySet()) {

String vlaue = json.getString(key);

43 > Document Version:20200922 物联网平台 Best Practices · Device access

String vlaue = json.getString(key); map.put(key, vlaue);

}

return map.keySet(); }

/**

* Specify an encryption algorithm in the HMAC_ALGORITHM parameter. *

* @param content Plaintext. * @param secret An encryption key.

* @return Ciphertext.

*/ private String encrypt(String content, String secret) {

try { byte[] text = content.getBytes(StandardCharsets.UTF_8);

byte[] key = secret.getBytes(StandardCharsets.UTF_8); SecretKeySpec secretKey = new SecretKeySpec(key, HMAC_ALGORITHM);

Mac mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey);

return Hex.encodeHexString(mac.doFinal(text));

} catch (Exception e) { e.printStackTrace();

return null; }

}

/** * SHA-256

*

* @param str A message to be encrypted. */

private String encod(String str) { MessageDigest messageDigest;

String encdeStr = ""; try {

messageDigest = MessageDigest.getInstance(SHA_256); byte[] hash = messageDigest.digest(str.getBytes(StandardCharsets.UTF_8));

encdeStr = Hex.encodeHexString(hash);

} catch (NoSuchAlgorithmException e) { System.out.println(String.format("Exception@encod: str=%s;", str));

> Document Version:20200922 44 Best Practices · Device access 物联网平台

e.printStackTrace(); return null;

} return encdeStr;

}

// Encrypt and decrypt data based on the AES algorithm.

private static final String IV = "543yhjy97ae7fyfg"; private static final String TRANSFORM = "AES/CBC/PKCS5Padding";

private static final String ALGORITHM = "AES";

/** * key length = 16 bits

*/ private byte[] encrypt(byte[] content, byte[] key) {

return encrypt(content, key, IV);

}

/** * key length = 16 bits

*/ private byte[] decrypt(byte[] content, byte[] key) {

return decrypt(content, key, IV); }

/** * aes 128 cbc key length = 16 bits

*/ private byte[] encrypt(byte[] content, byte[] key, String ivContent) {

try { SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);

Cipher cipher = Cipher.getInstance(TRANSFORM); IvParameterSpec iv = new IvParameterSpec(ivContent.getBytes(StandardCharsets.UTF_8));

cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);

return cipher.doFinal(content); } catch (Exception ex) {

System.out.println( String.format("AES encrypt error, %s, %s, %s", content, Hex.encodeHex(key), ex.getMessag

e())); return null;

}

45 > Document Version:20200922 物联网平台 Best Practices · Device access

} }

/** * aes 128 cbc key length = 16 bits

*/ private byte[] decrypt(byte[] content, byte[] key, String ivContent) {

try { SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);

Cipher cipher = Cipher.getInstance(TRANSFORM); IvParameterSpec iv = new IvParameterSpec(ivContent.getBytes(StandardCharsets.UTF_8));

cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);

return cipher.doFinal(content); } catch (Exception ex) {

System.out.println(String.format("AES decrypt error, %s, %s, %s", Hex.encodeHex(content), Hex.encodeHex(key), ex.getMessage()));

return null; }

}

public static void main(String[] args) throws InterruptedException {

IotCoapClientWithAes client = new IotCoapClientWithAes(); client.connect(productKey, deviceName, deviceSecret);

client.publish(updateTopic, "hello coap".getBytes(StandardCharsets.UTF_8)); client.publish(updateTopic, new byte[] { 0x01, 0x02, 0x03, 0x05 });

} }

1.3. Access IoT Platform by using HTTP

This topic describes how to connect a device to IoT Platform by using HTTP.

You can connect a device to IoT Platform by using HTTP. For more information, see Establish connections over HTTP. This topic uses a sample code developed based on the device SDK for Java to connect a device with IoT Platform. Before you can establish the connectioin, you must specify the required parameters, such as request parameters and certificate information of the device.

Note This feature is available only in the China (Shanghai) region.

Configure the pom.xml file

Add the following dependency to the pom.xml file to import the Alibaba fastjson package.

> Document Version:20200922 46 Best Practices · Device access 物联网平台

com.alibaba

fastjson 1.2.61

Sample code

The following code shows how to connect a device to IoT Platform and enable data communication.

/* * Copyright © 2019 Alibaba. All rights reserved.

*/ package com.aliyun.iot.demo;

import java.io.BufferedOutputStream;

import java.io.BufferedReader; import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.URL; import java.nio.charset.StandardCharsets;

import java.util.Set; import java.util.SortedMap;

import java.util.TreeMap;

import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec;

import javax.net.ssl.HttpsURLConnection;

import com.alibaba.fastjson.JSONObject;

/**

* Connect a device to IoT Platform by using HTTP. * For more information about the HTTP protocol, see HTTP standard.

* For more information about the data format, see Establish connections over HTTP. */

public class IotHttpClient {

// The ID of the region. Only the China (Shanghai) region is available.

private static String regionId = "cn-shanghai";

47 > Document Version:20200922 物联网平台 Best Practices · Device access

// Specify an encryption algorithm. Set the HMAC_ALGORITHM parameter to hmacsha1 or hmacmd5. The value that you set must be the same as that of the signmethod parameter.

private static final String HMAC_ALGORITHM = "hmacsha1";

// The validity period of a token is seven days. After a token expires, you must obtain a new token.

private String token = null;

/** * Initialize an HTTP client.

* * @param productKey The key of the product.

* @param deviceName The name of the device. * @param deviceSecret The key of the device.

*/

public void conenct(String productKey, String deviceName, String deviceSecret) { try {

// The endpoint for authentication. URL url = new URL("https://iot-as-http." + regionId + ".aliyuncs.com/auth");

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

conn.setRequestMethod("POST"); conn.setRequestProperty("Content-type", "application/json");

conn.setDoOutput(true);

conn.setDoInput(true);

// Obtain the output stream of the URLConnection object. PrintWriter out = new PrintWriter(conn.getOutputStream());

// Send request parameters. out.print(authBody(productKey, deviceName, deviceSecret));

// Print out the contents of the cache. out.flush();

// Obtain the input stream of the URLConnection object. BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));

// Obtain responses from the endpoint. String result = "";

String line = ""; while ((line = in.readLine()) ! = null) {

result += line; }

System.out.println("----- auth result -----");

> Document Version:20200922 48 Best Practices · Device access 物联网平台

System.out.println("----- auth result -----");

System.out.println(result);

// Close input and output streams. in.close();

out.close(); conn.disconnect();

// Obtain a token.

JSONObject json = JSONObject.parseObject(result);

if (json.getIntValue("code") == 0) { token = json.getJSONObject("info").getString("token");

} } catch (Exception e) {

e.printStackTrace(); }

}

/**

* Send messages. *

@param topic The topic to which messages are sent. * @param payload The contents of messages.

*/ public void publish(String topic, byte[] payload) {

try { // Specify the endpoint of a topic to which messages are sent.

URL url = new URL("https://iot-as-http." + regionId + ".aliyuncs.com/topic" + topic);

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

conn.setRequestMethod("POST"); conn.setRequestProperty("Content-type", "application/octet-stream");

conn.setRequestProperty("password", token); conn.setDoOutput(true);

conn.setDoInput(true);

// Obtain the output stream of the URLConnection object.

BufferedOutputStream out = new BufferedOutputStream(conn.getOutputStream()); out.write(payload);

out.flush();

49 > Document Version:20200922 物联网平台 Best Practices · Device access

// Obtain the input stream of the URLConnection object. BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));

// Obtain responses from the endpoint. String result = "";

String line = "";

while ((line = in.readLine()) ! = null) { result += line;

} System.out.println("----- publish result -----");

System.out.println(result);

// Close input and output streams. in.close();

out.close();

conn.disconnect(); } catch (Exception e) {

e.printStackTrace(); }

}

/** * Generate the required parameters for authentication.

*

* @param params The required parameters for authentication. * @return A message that includes an authentication request.

*/ private String authBody(String productKey, String deviceName, String deviceSecret) {

// Create a authentication request.

JSONObject body = new JSONObject(); body.put("productKey", productKey);

body.put("deviceName", deviceName);

body.put("clientId", productKey + "." + deviceName); body.put("timestamp", String.valueOf(System.currentTimeMillis()));

body.put("signmethod", HMAC_ALGORITHM); body.put("version", "default");

body.put("sign", sign(body, deviceSecret));

System.out.println("----- auth body -----"); System.out.println(body.toJSONString());

> Document Version:20200922 50 Best Practices · Device access 物联网平台

return body.toJSONString(); }

/**

* Generate a signature for the device *

* @param params The required parameters that you can use to generate a signature * @param deviceSecret The key of a device

* @return The signature in the hexadecimal format.

*/ private String sign(JSONObject params, String deviceSecret) {

// Sort request parameters in alphbetical order.

Set keys = getSortedKeys(params);

// Remove the sign, signmethod, and version parameters. keys.remove("sign");

keys.remove("signmethod");

keys.remove("version");

// Obtain the plaintext of the signature StringBuffer content = new StringBuffer();

for (String key : keys) { content.append(key);

content.append(params.getString(key)); }

// Generate a signature String sign = encrypt(content.toString(), deviceSecret);

System.out.println("sign content=" + content); System.out.println("sign result=" + sign);

return sign;

}

/**

* Convert a JSON object to a set of key-value pairs. *

* @param json The JSON object to be converted. * @return A set of key-value pairs that are converted from the JSON object.

51 > Document Version:20200922 物联网平台 Best Practices · Device access

*/ private Set getSortedKeys(JSONObject json) {

SortedMap map = new TreeMap(); for (String key : json.keySet()) {

String vlaue = json.getString(key);

map.put(key, vlaue); }

return map.keySet(); }

/**

* Specify an encryption method in the HMAC_ALGORITHM parameter. *

* @param content Plaintext.

* @param secret An encryption key. * @return Ciphertext.

*/ private String encrypt(String content, String secret) {

try { byte[] text = content.getBytes(StandardCharsets.UTF_8);

byte[] key = secret.getBytes(StandardCharsets.UTF_8); SecretKeySpec secretKey = new SecretKeySpec(key, HMAC_ALGORITHM);

Mac mac = Mac.getInstance(secretKey.getAlgorithm());

mac.init(secretKey); return byte2hex(mac.doFinal(text));

} catch (Exception e) { e.printStackTrace();

return null; }

}

/**

* Convert a binary array to a hexadecimal string. *

* @param b The binary array. * @return A hexadecimal string.

*/ private String byte2hex(byte[] b) {

StringBuffer sb = new StringBuffer(); for (int n = 0; b ! = null && n < b.length; n++) {

String stmp = Integer.toHexString(b[n] & 0XFF);

> Document Version:20200922 52 Best Practices · Device access 物联网平台

String stmp = Integer.toHexString(b[n] & 0XFF);

if (ss.length == 1) { sb.append('0');

} sb.append(stmp);

} return sb.toString().toUpperCase();

}

public static void main(String[] args) {

String productKey = "The productKey of your device"; String deviceName = "The deviceName of your device";

String deviceSecret = "The deviceSecret of your device"; IotHttpClient client = new IotHttpClient();

client.conenct(productKey, deviceName, deviceSecret); // The topic to which messages are sent. In the IoT Platform console, you can create a custom topi

c and grant the publish permission to devices. String updateTopic = "/" + productKey + "/" + deviceName + "/user/update";

client.publish(updateTopic, "hello http".getBytes(StandardCharsets.UTF_8));

client.publish(updateTopic, new byte[] { 0x01, 0x02, 0x03 }); }

}

1.4. Dynamic registration based on unique- certificate-per-product authentication by using MQTT

This topic describes how to use Message Queuing Telemetry Transport (MQTT) to implement dynamic registration for a directly connected device.

IoT Platform supports multiple authentication methods for devices. For more information, see Authenticate a device. The Unique-certificate-per-product authentication method allows you to implement dynamic registration for a device, and obtain certificate information about the device from IoT Platform. The certificate information includes the ProductKey, DeviceName, and DeviceSecret parameters. Then, use MQTT to connect the device to IoT Platform.

IoT Platform allows you to implement dynamic registration by using MQTT. For more information about dynamic registration, see Dynamically register a directly connected device based on unique- certificate-per-product authentication. This topic use sample code that is written in Java as an example.

Prerequisites

53 > Document Version:20200922 物联网平台 Best Practices · Device access

In the IoT Platform console, create a product and add a device to the product. On the Product Details page, turn on the Dynamic Registration switch.

Configure the pom.xml file

Add the following dependencies to the pom.xml file to import SDKs.

org.eclipse.paho org.eclipse.paho.client.mqttv3 1.2.1

com.alibaba

fastjson 1.2.61

Sample code

Note The sample code implements dynamic registration for a device rather than connecting the device to IoT Platform. For more information about how to connect a device to IoT Platform, see Using Paho MQTT Java client. In the IoT Platform console, make sure that you have enabled Dynamic Registration for the product to which the device belongs. If a device is not activated, you can repeat dynamic registration for the device. Each time the deviceSecret that you obtain is different. Make sure that the device is dynamically registered once and the deviceSecret that you obtain is stored on the device. Activated devices do not support dynamic registration.

/*

* Copyright © 2019 Alibaba. All rights reserved. */ package com.aliyun.iot.demo;

import java.nio.charset.StandardCharsets; import java.util.Random; import java.util.Set;

import java.util.SortedMap; import java.util.TreeMap;

> Document Version:20200922 54 Best Practices · Device access 物联网平台

import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;

import org.eclipse.paho.client.mqttv3.MqttCallback; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException;

import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import com.alibaba.fastjson.JSONObject;

/** * Implement dynamic registration for a device.

*/ public class DynamicRegisterByMqtt {

// The ID of the region where your product resides. private static String regionId = "cn-shanghai";

// Specify an encyrption algorithm. Valid values: hmacmd5, hmacsha1, and hmacsha256.The value th

at you specify must be the same as that for the signmethod parameter. private static final String HMAC_ALGORITHM = "hmacsha1";

// The topic that receives device certificates from IoT Platform. Use the topic without any changes.

You do not need to create or subscribe to the topic. private static final String REGISTER_TOPIC = "/ext/register";

/** * Implement dynamic registration. * * @param productKey The key of a product.

* @param productSecret The secret of the product. * @param deviceName The name of a device. * @throws Exception

*/ public void register(String productKey, String productSecret, String deviceName) throws Exception {

// The endpoint of the authentication service. Only Transport Layer Security (TLS) is available.

String broker = "ssl://" + productKey + ".iot-as-mqtt." + regionId + ".aliyuncs.com:1883";

55 > Document Version:20200922 物联网平台 Best Practices · Device access

String broker = "ssl://" + productKey + ".iot-as-mqtt." + regionId + ".aliyuncs.com:1883";

// The client ID. We recommend that you use the MAC address or SN of the device. The client ID ca n be a maximum of 64 characters in length.

String clientId = productKey + "." + deviceName;

// Obtain a random value.

Random r = new Random(); int random = r.nextInt(1000000);

// The value of the securemode parameter is 2 and cannot be changed. The value 2 indicates that

TLS is applied. The signmethod parameter specifies an encryption algorithm. String clientOpts = "|securemode=2,authType=register,signmethod=" + HMAC_ALGORITHM + ",rand om=" + random + "|";

// The ID of an MQTT client. String mqttClientId = clientId + clientOpts;

// The usename that the MQTT client uses to connect to the endpoint. String mqttUsername = deviceName + "&" + productKey;

// The signature that the MQTT client uses to connect to the endpoint.

JSONObject params = new JSONObject(); params.put("productKey", productKey); params.put("deviceName", deviceName);

params.put("random", random); String mqttPassword = sign(params, productSecret);

// Use an MQTT CONNECT packet for dynamic registration.

connectMqtt(targetServer, mqttClientId, mqttUsername, mqttPassword); }

/** * Use an MQTT CONNECT packet to send a message about dynamic registration. * * @param serverURL The endpoint for dynamic registration.

* @param clientId The client ID. * @param username The username that the MQTT client uses. * @param password The password that the MQTT client uses. */

@SuppressWarnings("resource")

> Document Version:20200922 56 Best Practices · Device access 物联网平台

@SuppressWarnings("resource") private void connect(String serverURL, String clientId, String username, String password) { try {

MemoryPersistence persistence = new MemoryPersistence(); MqttClient sampleClient = new MqttClient(serverURL, clientId, persistence); MqttConnectOptions connOpts = new MqttConnectOptions(); connOpts.setMqttVersion(4);// MQTT 3.1.1.

connOpts.setUserName(username);// The username. connOpts.setPassword(password.toCharArray());// The password. connOpts.setAutomaticReconnect(false); // Disable the automatic reconnection feature based

on MQTT rules that are set for dynamic registration. System.out.println("----- register params -----"); System.out.print("server=" + serverURL + ",clientId=" + clientId); System.out.println(",username=" + username + ",password=" + password);

sampleClient.setCallback(new MqttCallback() { @Override public void messageArrived(String topic, MqttMessage message) throws Exception { // Print out only responses for dynamic registration.

if (REGISTER_TOPIC.equals(topic)) { String payload = new String(message.getPayload(), StandardCharsets.UTF_8); System.out.println("----- register result -----");

System.out.println(payload); sampleClient.disconnect(); } }

@Override public void deliveryComplete(IMqttDeliveryToken token) {

}

@Override public void connectionLost(Throwable cause) {

} }); sampleClient.connect(connOpts); } catch (MqttException e) {

System.out.print("register failed: clientId=" + clientId); System.out.println(",username=" + username + ",password=" + password); System.out.println("reason " + e.getReasonCode());

System.out.println("msg " + e.getMessage()); System.out.println("loc " + e.getLocalizedMessage()); System.out.println("cause " + e.getCause());

57 > Document Version:20200922 物联网平台 Best Practices · Device access

System.out.println("cause " + e.getCause()); System.out.println("excep " + e);

e.printStackTrace(); } }

/** * Generate a signature for dynamic registration. *

* @param params The required parameters that you use to generate a signature. * @param productSecret The secret of a product. * @return A string that includes a signature in the hex format.

*/ private String sign(JSONObject params, String productSecret) {

// Sort request parameters in the alphabetical order.

Set keys = getSortedKeys(params);

// Remove the sign and signMethod parameters. keys.remove("sign");

keys.remove("signMethod");

// Obtain the plaintext of the signature.

StringBuffer buffer = new StringBuffer(); for (String key : keyList) { content.append(key); content.append(params.getString(key));

}

// Generate a signature.

String sign = encrypt(content.toString(), productSecret); System.out.println("sign content=" + content); System.out.println("sign result=" + sign);

return sign; }

/**

* Convert a JSON object to a set of key-value pairs. * * @param json A JSON object to convert.

> Document Version:20200922 58 Best Practices · Device access 物联网平台

* @return A set of key-value pairs that are converted from the JSON object. */ private Set getSortedKeys(JSONObject json) { SortedMap map = new TreeMap();

for (String key : json.keySet()) { String vlaue = json.getString(key); map.put(key, vlaue);

} return map.keySet(); }

/** * Specify an encryption algorithm in the HMAC_ALGORITHM parameter. * * @param content Plaintext.

* @param secret An encryption key. * @return Ciphertext. */

private String encrypt(String content, String secret) { try { byte[] text = content.getBytes(StandardCharsets.UTF_8); byte[] key = secret.getBytes(StandardCharsets.UTF_8);

SecretKeySpec secretKey = new SecretKeySpec(key, HMAC_ALGORITHM); Mac mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey);

return byte2hex(mac.doFinal(text)); } catch (Exception e) { e.printStackTrace(); return null;

} }

/**

* Convert a binary array to a hexadecimal string. * * @param b A binary array.

* @return A hexadecimal string. */ private String byte2hex(byte[] b) { StringBuffer sb = new StringBuffer();

for (int n = 0; b ! = null && n < b.length; n++) {

59 > Document Version:20200922 物联网平台 Best Practices · Device access

for (int n = 0; b ! = null && n < b.length; n++) { String stmp = Integer.toHexString(b[n] & 0XFF); if (stmp.length() == 1) {

sb.append('0'); } sb.append(stmp); }

return sb.toString().toUpperCase(); }

public static void main(String[] args) throws Exception {

String productKey = "The productKey for your device"; String productSecret = "The productSecret for your device";

String deviceName = "The deviceName for your device";

// Implement dynamic registration. DynamicRegisterByMqtt client = new DynamicRegisterByMqtt();

client.register(productKey, productSecret, deviceName);

// After dynamic registration is complete, store the deviceSecret on the device.

} }

1.5. Dynamic registration based on unique- certificate-per-product authentication by using HTTPS

This topic describes how to use HTTPS to implement dynamic registration for a directly connected device.

IoT Platform supports multiple authentication methods for devices. For more information, see Authenticate a device. The Unique-certificate-per-product authentication method allows you to implement dynamic registration for a device, and obtain certificate information about the device from IoT Platform. The certificate information includes the ProductKey, DeviceName, and DeviceSecret parameters. Then, use MQTT to connect the device to IoT Platform. IoT Platform allows you to implement dynamic registration for a device by using HTTPS. For more information dynamic registration, see Dynamically register a directly connected device based on unique-certificate-per-product authentication.

This topic use sample code written in Java to implement dynamic registration by using HTTPS.

Prerequisites

> Document Version:20200922 60 Best Practices · Device access 物联网平台

In the IoT Platform console, create a product and add a device to the product. On the Product Details page, turn on the Dynamic Registration switch.

Configure the pom.xml file

Add the following dependency to the pom.xml file to import the Alibaba fastjson package.

com.alibaba

fastjson 1.2.61

Sample code

Note The sample code implements dynamic registration for a device rather than connecting the device to IoT Platform. For more information about how to connect a device to IoT Platform, see Using Paho MQTT Java client. In the IoT Platform console, make sure that you have enabled Dynamic Registration for the product to which the device belongs. If a device is not activated, you can repeat dynamic registration for the device. Each time the deviceSecret that you obtain is different. Make sure that the device is dynamically registered once and the deviceSecret that you obtain is stored on the device. Activated devices do not support dynamic registration.

/*

* Copyright © 2019 Alibaba. All rights reserved. */ package com.aliyun.iot.demo;

import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter;

import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.Random; import java.util.Set;

import java.util.SortedMap; import java.util.TreeMap;

import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec;

61 > Document Version:20200922 物联网平台 Best Practices · Device access

import javax.crypto.spec.SecretKeySpec; import javax.net.ssl.HttpsURLConnection;

import com.alibaba.fastjson.JSONObject;

/** * Implement dynamic registration for a device.

*/ public class DynamicRegisterByHttps {

// The ID of the region. private static String regionId = "cn-shanghai";

// Specify an encryption algorithm. Valid values: hmacmd5, hmacsha1, and hmacsha256. The value th

at you specify must be the same as that for the signmethod parameter. private static final String HMAC_ALGORITHM = "hmacsha1";

/** * Dynamic registration * * @param productKey The key of a product.

* @param productSecret The secret of the product. * @param deviceName The name of a device. * @throws Exception */

public void register(String productKey, String productSecret, String deviceName) throws Exception {

// The endpoint of the authentication service.

URL url = new URL("https://iot-auth." + regionId + ".aliyuncs.com/auth/register/device");

HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST");

conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded"); conn.setDoOutput(true); conn.setDoInput(true);

// Obtain the output stream of the URLConnection object. PrintWriter out = new PrintWriter(conn.getOutputStream()); // Send request parameters.

out.print(registerdBody(productKey, productSecret, deviceName)); // Print out the contents of the cache. out.flush();

> Document Version:20200922 62 Best Practices · Device access 物联网平台

out.flush();

// Obtain the input stream of the URLConnection object. BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); // Obtain responses from the endpoint.

String result = ""; String line = ""; while ((line = br.readLine()) ! = null) { result += line;

} System.out.println("----- register result -----"); System.out.println(result);

// Close input and output streams. in.close(); out.close();

conn.disconnect(); }

/**

* Generate a request for dynamic registration. * * @param productKey The key of a product.

* @param productSecret The secret of the product. * @param deviceName The name of a device. * @return The contents of responses for dynamic registration. */

private String registerdBody(String productKey, String productSecret, String deviceName) {

// Obtain a random value.

Random r = new Random(); int random = r.nextInt(1000000);

// The required parameters for dynamic registration.

JSONObject object = new JSONObject(); params.put("productKey", productKey); params.put("deviceName", deviceName); params.put("random", random);

params.put("signMethod", HMAC_ALGORITHM); params.put("sign", sign(params, productSecret));

63 > Document Version:20200922 物联网平台 Best Practices · Device access

// Concatenate the contents. StringBuffer payload = new StringBuffer(); for (String key : params.keySet()) { payload.append(key);

payload.append("="); payload.append(params.getString(key)); payload.append("&");

} payload.deleteCharAt(payload.length() - 1);

System.out.println("----- register payload -----");

System.out.println(payload);

return d.toString(); }

/** * Generate a signature for dynamic registration.

* * @param params The required parameters that you use to generate a signature. * @param productSecret The secret of a product. * @return The signature in the hexadecimal format.

*/ private String sign(JSONObject params, String productSecret) {

// Sort request parameters in the alphabetical order. Set keys = getSortedKeys(params);

// Remove the sign and signMethod parameters

keys.remove("sign"); keys.remove("signMethod");

// Obtain the plaintext of the signature.

StringBuffer content = new StringBuffer(); for (String key : keys) { content.append(key);

content.append(params.getString(key)); }

// Generate a signature.

String sign = encrypt(content.toString(), productSecret);

> Document Version:20200922 64 Best Practices · Device access 物联网平台

String sign = encrypt(content.toString(), productSecret); System.out.println("sign content=" + content); System.out.println("sign result=" + sign);

return sign; }

/** * Convert a JSON object to a set of key-value pairs. * * @param json A JSON object to convert.

* @return A set of key-value pairs that are converted from a JSON object. */ private Set getSortedKeys(JSONObject json) {

SortedMap map = new TreeMap(); for (String key : json.keySet()) { String vlaue = json.getString(key); map.put(key, vlaue);

} return map.keySet(); }

/** * Specify an encryption algorithm in the HMAC_ALGORITHM parameter. *

* @param content Plaintext. * @param secret An encryption key. * @return Ciphertext. */

private String encrypt(String content, String secret) { try { byte[] text = content.getBytes(StandardCharsets.UTF_8);

byte[] key = secret.getBytes(StandardCharsets.UTF_8); SecretKeySpec secretKey = new SecretKeySpec(key, HMAC_ALGORITHM); Mac mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey);

return byte2hex(mac.doFinal(text)); } catch (Exception e) { e.printStackTrace();

return null; }

65 > Document Version:20200922 物联网平台 Best Practices · Device access

}

/** * Convert a binary array to a hexadecimal string. * * @param b A binary array.

* @return A hexadecimal string. */ private String byte2hex(byte[] b) {

StringBuffer sb = new StringBuffer(); for (int n = 0; b ! = null && n < b.length; n++) { String stmp = Integer.toHexString(b[n] & 0XFF); if (ss.length == 1) {

sb.append('0'); } sb.append(stmp);

} return sb.toString().toUpperCase(); }

public static void main(String[] args) throws Exception {

String productKey = "The productKey for your device"; String productSecret = "The productSecret for your device";

String deviceName = "The deviceName for your device";

// Implement dynamic registration.

DynamicRegisterByHttps client = new DynamicRegisterByHttps(); client.register(productKey, productSecret, deviceName);

// After the dynamic registration is completed, store the deviceSecret on the device.

} }

1.6. Access IoT Platform by using MQTT.fx

This article uses MQTT.fx as an example to describe the method for using a third-party MQTT client to connect to IoT Platform. MQTT.fx is a MQTT client that is written in Java language and based on Eclipse Paho. It supports subscribing to messages and publishing messages through topics.

> Document Version:20200922 66 Best Practices · Device access 物联网平台

Prerequisites

You have created products and devices in the IoT Platform console, and have got the ProductKey, DeviceName, and DeviceSecret of the devices. When you set the connection parameters for MQTT.fx, you will use the values of the ProductKey, DeviceName, and DeviceSecret. See Create a product, Create a device, and Create multiple devices at a timefor help when creating products and devices.

Procedure

1. Download and install the MQTT.fx software.

Download the MQTT.fx software for Windows from MQTT.fx website.

2. Open MQTT.fx, and click the settings icon.

3. Set the connection parameters.

Currently, two types of connection modes are supported: TCP and TLS. These two modes only differ in settings of Client ID and SSL/TLS.

The procedure is as follows:

i. Enter basic information. See the following table for parameter descriptions. You can keep the default parameters for General, or set the values according to your needs.

67 > Document Version:20200922 物联网平台 Best Practices · Device access

Parameter Description

Profile Name Enter a custom profile name.

Profile Type Select MQTT Broker.

To view the endpoint of the instance that you purchased, perform the following steps: Log on to the IoT Platform console. In the left-side navigation pane, click Instances. On the page that appears, click View in the Actions column of the instance. On the Instance Details page, you can view the endpoint.

The endpoint for public instances is ${YourProductKey}.iot-as-mq

Broker Address tt. ${YourRegionId}.aliyuncs.com .

${YourProductKey}: Replace this variable with the ProductKey of the product to which the device belongs. You can obtain the ProductKey on the Device Details page of the IoT Platform console.

${YourRegionId}: Replace this variable with your region ID. For information about region IDs, see Regions and zones.

Broker Port Set to 1883.

> Document Version:20200922 68 Best Practices · Device access 物联网平台

Parameter Description

Enter a value in the format of ${clientId}|securemode=3,signmethod= hmacsha1|. Example: 12345|securemode=3,signmethod=hmacsha1| . The parameters are described as follows: ${clientId} is a custom client ID. It can be any value within 64 characters. We recommend that you use the MAC address or SN code of the device as the value of clientId. securemode is the security mode of the connection. If you use the TCP mode, set it as securemode=3; if you use the TLS mode, set it Client ID as securemode=2. signmethod is the signature method that you want to use. IoT Platform supports hmacmd5 and hmacsha1.

Note Do not click Generate after you enter the Client ID information.

ii. Click User Credentials, and enter your User Name and Password.

Parameter Description

It must be the device name directly followed by the character "&" User Name and the product key. Format: ${YourDeviceName}&${YourProductKey }. For example, device&fOAt5H5TOWF.

69 > Document Version:20200922 物联网平台 Best Practices · Device access

Parameter Description

You must enter an encrypted value of the input parameters.

IoT Platform provides a Password Generator for you to generate one easily.

Parameters in the password generator:

productKey: The unique identifier of the product to which the device belongs. You can view this information on the device details page in the console. deviceName: The name of the device. You can view this information on the device details page in the console.

deviceSecret: The device secret. You can view this information on the device details page in the console. timestamp: (Optional) Timestamp of the current system time.

clientId: The custom client ID, which must be the same as the value of ${clientId} in Client ID. method: The signature algorithm, which must be the same as the value of signmethod in Client ID. Password You can also encrypt a password by yourself.

Generate a password manually:

a. Sort and join the parameters.

Sort and join the parameters clientId, deviceName, productKey, and timestamp in a lexicographical order. (If you have not set a timestamp, do not include timestamp in the string.) Joint string example: clientId12345deviceNamedevice productKeyfOAt5H5TOWF

b. Encrypt.

Use the deviceSecret of the device as the secret key to encrypt the joint string by the signature algorithm defined in Client ID.

Suppose the deviceSecret of the device is abc123, the encryption format is hmacsha1(abc123,clientId12345deviceN amedeviceproductKeyfOAt5H5TOWF) .

> Document Version:20200922 70 Best Practices · Device access 物联网平台

iii. If you use TLS connection mode, you are required to set information for SSL/TLS. SSL/TLS settings are not required when the connection mode is TCP.

Check the box for Enable SSL/TLS, and select TLSv1 as the protocol.

iv. Enter all the required information, and then click OK. 4. Click Connect to connect to IoT Platform.

Message communication test

Test whether MQTT.fx and IoT Platform are successfully connected.

1. In MQTT.fx, click Subscribe. 2. Enter a topic of the device, and then click Subscribe.

71 > Document Version:20200922 物联网平台 Best Practices · Device access

After you have successfully subscribed to a topic, it is displayed in the topic list.

3. In the IoT Platform console, in the Topic List of the Device Details page, click the Publish button of the topic that you have subscribed to. 4. Enter message content, and click OK.

> Document Version:20200922 72 Best Practices · Device access 物联网平台

5. Go back to MQTT.fx to check if the message has been received.

View logs

In MQTT.fx, click Log to view the operation logs and error logs.

73 > Document Version:20200922 物联网平台 Best Practices · Device access

1.7. Connect Android Things to IoT Platform

This article uses an indoor air test project as an example to explain how to connect Google Android Things to IoT Platform.

Hardware

Hardware list for the project

The following table lists the hardware required by the indoor air test project.

Hardware Picture Remarks

Android Things 1.0

NXP Pico i.MX7D Note You can also use Development board Raspberry Pi instead.

> Document Version:20200922 74 Best Practices · Device access 物联网平台

Hardware Picture Remarks

DHT12 Supports I2C data Temperature and communication humidity sensor method.

ZE08-CH2O Supports UART data Formaldehyde communication detection sensor method.

Diagram of the hardware connection

75 > Document Version:20200922 物联网平台 Best Practices · Device access

Connect the SCL (clock line) and SDA (data line) pins of the temperature and humidity sensor (DHT12) with the I2C SCL and SDA pins of the development board. Connect the TXD (transmit data) pin of the formaldehyde detection sensor (ZE08-CH2O) with the RXD (receive data) pin of the development board, and connect the RXD pin of ZE08-CH2O with the TXD pin of the development board.

Create a product and device in the Alibaba Cloud IoT Platform console

1. Log on to the IoT Platform console. 2. Create a product in IoT Platform.

On the Products page, click Create Product. For more information, see Create a product.

3. Define features for the newly created product. i. After the product is successfully created, click Create TSL. ii. On the Define Feature tab page of Product Details, click Edit Draft > Self-defined Feature > Add Self-defined Feature.

> Document Version:20200922 76 Best Practices · Device access 物联网平台

iii. Define the following features.

Property name Identifier Data type Value range Description

Detected by Temperature temperature float -50~100 DHT12.

Detected by Humidity humidity float 0~100 DHT12.

Formaldehyde Detected by ch2o double 0~3 concentration ZE08.

iv. Click Update to publish this TSL. 4. Create a device

On the Devices page, select the name of the newly created product, click Add Device, and then create a device. For more information, see Create a device.

Develop the Android Things client

1. Use Android Studio to create an Android Things project, and add the permission for Internet.

2. Add eclipse.paho.mqtt to Gradle file.

implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.0'

3. Set that data of DHT12 is read through I2C.

77 > Document Version:20200922 物联网平台 Best Practices · Device access

private void readDataFromI2C() {

try {

byte[] data = new byte[5]; i2cDevice.readRegBuffer(0x00, data, data.length);

// check data

if ((data[0] + data[1] + data[2] + data[3]) % 256 ! = data[4]) { humidity = temperature = 0; return;

} // humidity data humidity = Double.valueOf(String.valueOf(data[0]) + "." + String.valueOf(data[1])); Log.d(TAG, "humidity: " + humidity);

// temperature data if (data[3] < 128) { temperature = Double.valueOf(String.valueOf(data[2]) + "." + String.valueOf(data[3]));

} else { temperature = Double.valueOf("-" + String.valueOf(data[2]) + "." + String.valueOf(data[3] - 128)); }

Log.d(TAG, "temperature: " + temperature);

} catch (IOException e) {

Log.e(TAG, "readDataFromI2C error " + e.getMessage(), e); }

}

4. Set that data of Ze08-CH2O is read through UART.

> Document Version:20200922 78 Best Practices · Device access 物联网平台

try { // data buffer byte[] buffer = new byte[9];

while (uartDevice.read(buffer, buffer.length) > 0) {

if (checkSum(buffer)) {

ppbCh2o = buffer[4] * 256 + buffer[5]; ch2o = ppbCh2o / 66.64 * 0.08; } else {

ch2o = ppbCh2o = 0; } Log.d(TAG, "ch2o: " + ch2o); }

} catch (IOException e) { Log.e(TAG, "Ze08CH2O read data error " + e.getMessage(), e); }

5. Connect Alibaba Cloud IoT Platform and the client, and report data.

/* Payload format

{ "id": 123243, "params": { "temperature": 25.6,

"humidity": 60.3, "ch2o": 0.048 },

"method": "thing.event.property.post" } */ MqttMessage message = new MqttMessage(payload.getBytes("utf-8"));

message.setQos(1);

String pubTopYourPc = "/sys/${YourProductKey}/${YourDeviceName}/thing/event/property/post"

;

mqttClient.publish(pubTopic, message);

79 > Document Version:20200922 物联网平台 Best Practices · Device access

View real-time data of the device

After the device is enabled, you can view the real-time data of the device from the Status column on the Device Details page in IoT Platform console. 1.8. Connect an RTOS device to IoT Platform by using a TCP communication module 1.8.1. Overview

This topic describes how to use a device SDK for C-based application to connect a microcontroller (MCU) device on which a real-time operating system (RTOS) runs to IoT Platform. Most electrical devices use one or more MCUs on which an RTOS runs. These electrical devices include industrial automation devices, data collection devices, real-time control devices, and home appliances. To connect these electrical devices to IoT Platform, use device SDK for C that is provided by IoT Platform.

Implementation

Connect an MCU to a communication module and use AT commands for communication between the MCU and the communication module. Use device SDK for C to connect the communication module to IoT Platform and enable communication between each other.

Prepare software and hardware

You must prepare the following items.

A NUCLEO-F103RB demo board that is equipped with an STM32F103 MCU from ST. An SIM800C mini V2.0 demo board that is equipped with a SIM800C communication module from SIMcom. The IAR Embedded Workbench for ARM development environment.

Procedure

Create a product and add a device

Build a development environment for devices

Develop for a device 1.8.2. Create a product and add a device

> Document Version:20200922 80 Best Practices · Device access 物联网平台

This topic describes how to create a product, add a device to the product, and obtain certificate information about the device in the IoT Platform console. The certificate information includes the ProductKey, DeviceName, and DeviceSecret parameters. Certificate information about a device must be added to a device SDK-based project. If a device attempts to communicate with IoT Platform, IoT Platform uses the certificate information about the device to authenticate the device.

Procedure

1. Log on to the IoT Platform console. 2. Create a product. i. In the left-side navigation pane, choose Devices > Products. ii. On the Products page, click Create Product, specify the required parameters, and click Save.

Parameter Description

Product Name The name of the product.

[DO NOT [DO NOT TRANSLATE] TRANSLATE]

Node Type Select Directly Connected Device.

Network Connection Select Wi-Fi. Method

Data Type Select ICA Standard Data Format (Alink JSON).

Authentication Select Device Secret. Mode

3. Add a device to the product. i. In the left-side navigation pane, choose Devices > Devices. ii. On the Devices page, click Add Device to add a device to the product. 1.8.3. Build a development environment for devices

This topic describes how to connect a microcontroller (MCU) to a demo board that includes a communication module. It also describes how to build a development environment, create a project, import a device SDK, and configure the project.

Context

The following figure shows the demo boards.

NUCLEO-F103RB

81 > Document Version:20200922 物联网平台 Best Practices · Device access

The following figure shows pins for the demo board.

SIM800C mini v2.0

The following figure shows pins for the demo board.

> Document Version:20200922 82 Best Practices · Device access 物联网平台

Pin Description

PWR Power switch. Automatic power-on is enabled by default.

STA Status.

GND Ground.

RXD Receive data.

TXD Transmit data.

EN Enable.

VIN 5 V to 18 V input.

Connect demo boards

Connect the RXD pin of each demo board to the TXD pin of each demo board. This allows you to establish a connection and run AT commands. The following figure shows how to connect the demo boards.

83 > Document Version:20200922 物联网平台 Best Practices · Device access

Build a development environment

This topic uses the STM32CubeMX tool as an example. For more information, see STM32Cube Ecosystem.

1. Open the STM32CubeMX tool and click New Project.

> Document Version:20200922 84 Best Practices · Device access 物联网平台

2. On the Board Seletor tab, search for NUCLEO-F103RB and click STM32F103RBTx.

3. In the upper-right corner, click Start Project. 4. In the left-side navigation pane, click Connectivity, and select USART1 as the port for communication between an MCU and a communication module. Proceed as follows. Set Mode to Asynchronous. In the Configuration section, set the following parameters. On the GPIO Settings tab, select PA9 and PA10 in the Pin field. On the NVIC Settings tab, set USART1 global interrupt to Enabled.

85 > Document Version:20200922 物联网平台 Best Practices · Device access

5. In the left-side navigation pane, click Middleware, select FREERTOS, set USE_COUNTING_SEMAPHORES to Enabled, and set TOTAL_HEAP_SIZE. Each thread can share the heap.

6. On the Project Manager tab, complete the settings in the Project section.

> Document Version:20200922 86 Best Practices · Device access 物联网平台

7. In the upper-right corner of the page, click GENERATE CODE to generate code for the project. 1.8.4. Develop for a device

Use Link SDK for C to connect a communication module to IoT Platform.

Configure a device SDK

1. Download Link SDK 3.0.1 for C. 2. Extract code from the SDK package. This topic uses Linux as an example. i. Run the make menuconfig command. ii. Select ATM Configurations and click Select.

87 > Document Version:20200922 物联网平台 Best Practices · Device access

iii. Select AT HAL Configurations and click Select.

iv. Set the following parameters:

> Document Version:20200922 88 Best Practices · Device access 物联网平台

FEATURE_PLATFORM_HAS_STDINT=y FEATURE_PLATFORM_HAS_OS=y

FEATURE_INFRA_STRING=y FEATURE_INFRA_NET=y FEATURE_INFRA_LIST=y FEATURE_INFRA_LOG=y

FEATURE_INFRA_LOG_ALL_MUTED=y FEATURE_INFRA_LOG_MUTE_FLW=y FEATURE_INFRA_LOG_MUTE_DBG=y FEATURE_INFRA_LOG_MUTE_INF=y

FEATURE_INFRA_LOG_MUTE_WRN=y FEATURE_INFRA_LOG_MUTE_ERR=y FEATURE_INFRA_LOG_MUTE_CRT=y

FEATURE_INFRA_TIMER=y FEATURE_INFRA_SHA256=y FEATURE_INFRA_REPORT=y FEATURE_INFRA_COMPAT=y

FEATURE_DEV_SIGN=y FEATURE_MQTT_COMM_ENABLED = y FEATURE_MQTT_DEFAULT_IMPL=y

FEATURE_MQTT_DIRECT = y FEATURE_DEVICE_MODEL_CLASSIC=y FEATURE_ATM_ENABLED=y FEATURE_AT_TCP_ENABLED=y

FEATURE_AT_PARSER_ENABLED=y FEATURE_AT_TCP_HAL_SIM800=y

89 > Document Version:20200922 物联网平台 Best Practices · Device access

v. After the configuration is complete, run the ./extract.sh script to extract code.

The code is saved in the output/eng directory.

The following table lists subdirectories that reside in the output/eng directory.

Directory Description

atm Includes code that you can use to send and receive AT commands.

dev_sign Includes code that you can use to authenticate devices.

infra Includes code that you can use to implement internal functions.

Includes code that you can use to implement the Message Queuing mqtt Telemetry Transport (MQTT) protocol.

Includes code that you can use to implement hardware abstraction wrappers layer (HAL) functions.

vi. In the wrappers directory, create the wrappers.c file. Implement the following HAL functions in the file.

> Document Version:20200922 90 Best Practices · Device access 物联网平台

int32_t HAL_AT_Uart_Deinit(uart_dev_t *uart)

int32_t HAL_AT_Uart_Init(uart_dev_t *uart) int32_t HAL_AT_Uart_Recv(uart_dev_t *uart, void *data, uint32_t expect_size, uint32_t *recv_si ze, uint32_t timeout)

int32_t HAL_AT_Uart_Send(uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout)

int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]) int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN])

int HAL_GetFirmwareVersion(char *version) int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN])

void *HAL_Malloc(uint32_t size);

void HAL_Free(void *ptr);

void *HAL_MutexCreate(void)

void ls_osa_mutex_destroy(void *mutex) void HAL_MutexLock(void *mutex) void HAL_MutexUnlock(void *mutex)

void *HAL_SemaphoreCreate(void) void HAL_SemaphoreDestroy(void *sem) void HAL_SemaphorePost(void *sem)

int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms) int HAL_ThreadCreate(void **thread_handle, void *(*work_routine)(void *), void *arg,

hal_os_thread_param_t *hal_os_thread_param, int *stack_used)

void HAL_SleepMs(uint32_t ms)

void ls_osa_print(const char *fmt, ...) int HAL_Snprintf(char *str, const int len, const char *fmt, ...) uint64_t HAL_UptimeMs(void)

Download a sample wrappers.c file.

The following figure shows how to specify the certificate information about the serial device in the file.

91 > Document Version:20200922 物联网平台 Best Practices · Device access

Note If you are not using the NUCLEO-F103RB demo board, set FEATURE_AT_TCP_ HAL_SIM800=n . You also need to implement the following HAL functions in the wrapp ers.c file.

int HAL_AT_CONN_Close(int fd, int32_t remote_port) int HAL_AT_CONN_Deinit(void)

int HAL_AT_CONN_DomainToIp(char *domain, char ip[16]) int HAL_AT_CONN_Init(void) int HAL_AT_CONN_Send(int fd, uint8_t *data, uint32_t len, char remote_ip[16], int32_t remo te_port, int32_t timeout)

int HAL_AT_CONN_Start(at_conn_t *conn)

int32_t HAL_AT_Uart_Deinit(uart_dev_t *uart) int32_t HAL_AT_Uart_Init(uart_dev_t *uart)

int32_t HAL_AT_Uart_Recv(uart_dev_t *uart, void *data, uint32_t expect_size, uint32_t *rec v_size, uint32_t timeout) int32_t HAL_AT_Uart_Send(uart_dev_t *uart, const void *data, uint32_t size, uint32_t time

out)

int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]) int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN])

int HAL_GetFirmwareVersion(char *version) int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN])

void *HAL_Malloc(uint32_t size); void HAL_Free(void *ptr);

void *HAL_MutexCreate(void)

void ls_osa_mutex_destroy(void *mutex) void HAL_MutexLock(void *mutex) void HAL_MutexUnlock(void *mutex)

> Document Version:20200922 92 Best Practices · Device access 物联网平台

void HAL_MutexUnlock(void *mutex)

void *HAL_SemaphoreCreate(void) void HAL_SemaphoreDestroy(void *sem) void HAL_SemaphorePost(void *sem)

int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms) int HAL_ThreadCreate(void **thread_handle, void *(*work_routine)(void *), void *arg,

hal_os_thread_param_t *hal_os_thread_param, int *stack_used)

void HAL_SleepMs(uint32_t ms) void ls_osa_print(const char *fmt, ...) int HAL_Snprintf(char *str, const int len, const char *fmt, ...) uint64_t HAL_UptimeMs(void)

3. Add the file to the IAR project.

4. Run the project to perform a test.After the project is completed, the following figure shows device logs.

93 > Document Version:20200922 物联网平台 Best Practices · Device access

In the IoT Platform console, choose Maintenance > Device Log. The Device Log page also shows logs that are generated each time the device reports data to IoT Platform. 1.9. Connect a bare-metal device to IoT Platform by using TCP 1.9.1. Overview

This topic describes how to use device SDK for C to connect a bare-metal microcontroller device to IoT Platform by using Message Queuing Telemetry Transport (MQTT).

IoT Internet of Things Bare-metal device Microcontroller (MCU)

Implementation

Connect an MCU to a communication module and use AT commands for communication between the MCU and the communication module. Use device SDK for C to connect the communication module to IoT Platform and enable communication between each other.

Prepare software and hardware

You must prepare the following items. A NUCLEO-F103RB demo board that is equipped with an STM32F103 MCU from ST. An SIM800C mini V2.0 demo board that is equipped with a SIM800C communication module from SIMcom. The IAR Embedded Workbench for ARM development environment.

> Document Version:20200922 94 Best Practices · Device access 物联网平台

Procedure

Create a product and add a device

Build a development environment for devices

Provision a device 1.9.2. Create a product and add a device

This topic describes how to create a product, add a device to the product, and obtain certificate information about the device in the IoT Platform console. The certificate information includes the ProductKey, DeviceName, and DeviceSecret parameters. Certificate information about a device must be added to a device SDK-based project. If a device attempts to communicate with IoT Platform, IoT Platform uses the certificate information about the device to authenticate the device.

Procedure

1. Log on to the IoT Platform console. 2. Create a product. i. In the left-side navigation pane, choose Devices > Products. ii. On the Products page, click Create Product, specify the required parameters, and click Save.

Parameter Description

Product Name The name of the product.

[DO NOT [DO NOT TRANSLATE] TRANSLATE]

Node Type Select Directly Connected Device.

Network Connection Select Wi-Fi. Method

Data Type Select ICA Standard Data Format (Alink JSON).

Authentication Select Device Secret. Mode

3. Add a device to the product. i. In the left-side navigation pane, choose Devices > Devices. ii. On the Devices page, click Add Device to add a device to the product. 1.9.3. Build a development environment for devices

This topic describes how to connect a microcontroller (MCU) to a demo board that includes a communication module. It also describes how to build a development environment, create a project, import a device SDK, and configure the project.

95 > Document Version:20200922 物联网平台 Best Practices · Device access

Context

The following figure shows the demo boards.

NUCLEO-F103RB

The following figure shows pins for the demo board.

SIM800C mini v2.0

The following figure shows pins for the demo board.

> Document Version:20200922 96 Best Practices · Device access 物联网平台

Pin Description

PWR Power switch. Automatic power-on is enabled by default.

STA Status.

GND Ground.

RXD Receive data.

TXD Transmit data.

EN Enable.

VIN 5 V to 18 V input.

Connect demo boards

Connect the RXD pin of a demo board to the TXD pin of the other demo board. This allows you to establish a connection and run AT commands. The following figure shows how to connect the demo boards.

97 > Document Version:20200922 物联网平台 Best Practices · Device access

Build a development environment

This section uses the STM32CubeMX tool as an example. For more information, visit STM32Cube Ecosystem.

1. Open the STM32CubeMX tool and click New Project.

> Document Version:20200922 98 Best Practices · Device access 物联网平台

2. On the Board Selector tab, search for NUCLEO-F103RB and click STM32F103RBTx.

3. In the upper-right corner, click Start Project. 4. In the left-side navigation pane, click Connectivity, select USART1 as the port for communication between the MCU and the communication module. Set the following parameters: Set Mode to Asynchronous. In the Configuration section, set the following parameters: On the GPIO Settings tab, select PA9 and PA10 in the Pin field. On the NVIC Settings tab, set USART1 global interrupt to Enabled.

99 > Document Version:20200922 物联网平台 Best Practices · Device access

5. On the Project Manager tab, specify the required parameters in the Project section. Set Toolchain/IDE to EWARM V8. Set Heap/Stack size based on your business requirements.

6. In the upper-right corner, click GENERATE CODE to generate code for the project. 1.9.4. Provision a device

This section describes how to use the Link SDK for C to connect a communication module to IoT Platform.

Procedure

> Document Version:20200922 100 Best Practices · Device access 物联网平台

1. Download Link SDK 3.0.1 for C. 2. Extract code from the SDK package. This section uses Linux as an example. i. Run the make menuconfig command. ii. Select ATM Configurations and click Select.

iii. Select AT HAL Configurations and click Select.

101 > Document Version:20200922 物联网平台 Best Practices · Device access

iv. Set the following parameters:

FEATURE_PLATFORM_HAS_STDINT=y FEATURE_INFRA_STRING=y

FEATURE_INFRA_NET=y

FEATURE_INFRA_LIST=y FEATURE_INFRA_LOG=y

FEATURE_INFRA_LOG_ALL_MUTED=y

FEATURE_INFRA_LOG_MUTE_FLW=y FEATURE_INFRA_LOG_MUTE_DBG=y

FEATURE_INFRA_LOG_MUTE_INF=y FEATURE_INFRA_LOG_MUTE_WRN=y

FEATURE_INFRA_LOG_MUTE_ERR=y

FEATURE_INFRA_LOG_MUTE_CRT=y FEATURE_INFRA_TIMER=y

FEATURE_INFRA_SHA256=y

FEATURE_INFRA_REPORT=y FEATURE_INFRA_COMPAT=y

FEATURE_DEV_SIGN=y

FEATURE_MQTT_COMM_ENABLED = y FEATURE_MQTT_DEFAULT_IMPL=y

FEATURE_MQTT_DIRECT = y FEATURE_DEVICE_MODEL_CLASSIC=y

FEATURE_ATM_ENABLED=y

FEATURE_AT_TCP_ENABLED=y FEATURE_AT_PARSER_ENABLED=y

FEATURE_AT_TCP_HAL_SIM800=y

> Document Version:20200922 102 Best Practices · Device access 物联网平台

v. After the configuration is complete, run the ./extract.sh script to exact the code.

The code is saved in the output/eng directory.

The following table lists the subdirectories that reside in the directory.

Directory Description

atm Includes code that you can use to send and receive AT instructions.

dev_sign Includes code that you can use to authenticate devices.

infra Includes code that you can use to implement internal functions.

Includes code that you can use to implement the MQ Telemetry mqtt Transport (MQTT) protocol.

Includes code that you can use to implement hardware abstraction wrappers layer (HAL) functions.

3. In the wrappers directory, create a file named wrappers.c. Implement the following HAL functions in the file.

103 > Document Version:20200922 物联网平台 Best Practices · Device access

int32_t HAL_AT_Uart_Deinit(uart_dev_t *uart) int32_t HAL_AT_Uart_Init(uart_dev_t *uart)

int32_t HAL_AT_Uart_Recv(uart_dev_t *uart, void *data, uint32_t expect_size,

uint32_t *recv_size, uint32_t timeout) int32_t HAL_AT_Uart_Send(uart_dev_t *uart, const void *data, uint32_t size,

uint32_t timeout)

int HAL_GetFirmwareVersion(char *version)

int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]) int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN])

int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN])

void *HAL_Malloc(uint32_t size);

void HAL_Free(void *ptr);

void *HAL_MutexCreate(void)

void HAL_MutexDestroy(void *mutex) void HAL_MutexLock(void *mutex)

void HAL_MutexUnlock(void *mutex)

void HAL_Printf(const char *fmt, ...)

void HAL_SleepMs(uint32_t ms)

int HAL_Snprintf(char *str, const int len, const char *fmt, ...) uint64_t HAL_UptimeMs(void)

Download a sample wrappers.c file.

The following figure shows how to specify the certificate information about the serial device in the file.

> Document Version:20200922 104 Best Practices · Device access 物联网平台

Note If you are not using the SIM800C communication module, add the FEATURE_AT_ TCP_HAL_SIM800=n statement, and implement the following HAL functions.

int HAL_AT_CONN_Close(int fd, int32_t remote_port) int HAL_AT_CONN_Deinit(void)

int HAL_AT_CONN_DomainToIp(char *domain, char ip[16])

int HAL_AT_CONN_Init(void) int HAL_AT_CONN_Send(int fd, uint8_t *data, uint32_t len, char remote_ip[16], int32_t remote_p

ort, int32_t timeout) int HAL_AT_CONN_Start(at_conn_t *conn)

int32_t HAL_AT_Uart_Deinit(uart_dev_t *uart) int32_t HAL_AT_Uart_Init(uart_dev_t *uart)

int32_t HAL_AT_Uart_Recv(uart_dev_t *uart, void *data, uint32_t expect_size, uint32_t *recv_si

ze, uint32_t timeout) int32_t HAL_AT_Uart_Send(uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout)

int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN + 1]) int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN + 1])

int HAL_GetFirmwareVersion(char *version) int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN + 1])

void *HAL_Malloc(uint32_t size); void HAL_Free(void *ptr);

void *HAL_MutexCreate(void) void HAL_MutexDestroy(void *mutex)

void HAL_MutexLock(void *mutex)

void HAL_MutexUnlock(void *mutex)

void HAL_Printf(const char *fmt, ...)

void HAL_SleepMs(uint32_t ms) int HAL_Snprintf(char *str, const int len, const char *fmt, ...)

uint64_t HAL_UptimeMs(void)

4. Add the file to the IAR project.

105 > Document Version:20200922 物联网平台 Best Practices · Device access

5. Run the project and test data communication.After the test is successful, the device logs are displayed, as shown in the following figure.

In the IoT Platform console, choose Maintenance > Device Log to view logs generated when the device reports data to IoT Platform. 1.10. Connect a serial device to IoT Platform by using a DTU device 1.10.1. Overview

IoT Platform can communicate with serial devices. You can use data transmission unit (DTU) devices to connect serial devices to IoT Platform without changing communication protocols for these serial devices.

> Document Version:20200922 106 Best Practices · Device access 物联网平台

Scenarios

Devices for serial communication are used in a variety of scenarios, such as manufacturing, agriculture, healthcare, city, building, and industrial parks. Before you connect these devices to IoT Platform, you must enable communication between these devices and IoT Platform. However, the serial communication protocols used by these devices cannot be changed to communicate with IoT Platform. Therefore, data can be parsed only on the cloud. To connect these devices to IoT Platform, Alibaba Cloud works with hardware partners to provide a solution to communication between the serial devices and IoT Platform. This solution allows you to use DTU devices as proxies to enable communication between serial devices and IoT Platform by using simple configurations.

This topic uses a motor speed controller as an example to describe how to connect a serial device with IoT Platform by using a DTU device. This device complies with the integration standard of IoT Platform.

Implementation

To connect a serial device to IoT Platform, specify the certificate information of the serial device in a DTU device. Use the DTU device as a proxy for communication between the serial device and IoT Platform. Connect the serial device to the DTU device by using a serial port. Connect the DTU device to IoT Platform over the 2G, 3G, 4G, 5G, or Ethernet network. Use the DTU device as a proxy to enable communication between the serial device and IoT Platform.

The following figure shows how to connect a serial device to IoT Platform by using a DTU device.

Procedure

1. Configure a product and a device. 2. Configure a DTU device. 3. Test data communication. 1.10.2. Configure a product and a device

This topic describes how to create a product whose data type is custom, add a device to the product, obtain certificate information of the device, create a Thing Specification Language (TSL) model, and edit a data parsing script in the IoT Platform console.

Create a product and add a device

In the IoT Platform console, create a product, add a device to the product, and obtain certificate information of the device. The certificate information includes the ProductKey, DeviceName, and DeviceSecret parameters.

107 > Document Version:20200922 物联网平台 Best Practices · Device access

1. Log on to the IoT Platform console. 2. In the left-side navigation pane, choose Devices > Products. On the Products page, click Create Product to create a product. Product information

Parameter Description

Product Name The name of the product.

[DO NOT TRANSLATE] [DO NOT TRANSLATE]

Node Type Select Directly Connected Device.

Network Connection Select Cellular (2G/3G/4G/5G). Method

Data Type Select Custom.

Authentication Mode Select Device Secret.

3. In the left-side navigation pane, click Devices and click Add Device to add a device to the product. After the device is added, go to the Devices page. Find the target device, click View to go to the Device Details page, and view the certificate information of the device. Specify the certificate information of the device in a data transmission unit (DTU) device

Create a TSL model

TSL is a data model that digitizes a physical entity and constructs the entity in the cloud. In IoT Platform, a TSL model refers to a set of features. After you define features for a product, IoT Platform generates a TSL model for the product. This topic uses a variable frequency motor as an example. You must define the spinning speed, electrical current, speed reset properties.

1. Log on to the IoT Platform console. In the left-side navigation pane, choose Devices > Products。 2. On the Product page, find the target product and click View. 3. On the Product Details page, click the Define Feature tab, and choose Edit Draft > Add Self- defined Feature. 4. Add the following properties and click Release Online to publish the TSL model.

Feature Value Read/writ Feature Identifier Data type Unit type range e type

Spinning Property speed int32 0 to 3000 rpm Read-only speed

Electrical Property current int32 0 to 300 A Read-only current

Speed Read/writ Property setspeed int32 0 to 3000 rpm reset e

> Document Version:20200922 108 Best Practices · Device access 物联网平台

Edit a data parsing script

IoT Platform proceses data in the Alink JSON format. If serial devices communicate with IoT Platform by using DTU devices, IoT Platform cannot process pass-through data that is sent from serial devices. IoT Platform converts data by using data parsing scripts. Data parsing scripts allow you to convert upstream data into the Alink JSON format and downstream data into the custom format of your device. IoT Platform calls data parsing scripts that you submit to parse data. You must edit data parsing scripts based on upstream and downstream data. 1. Log on to the IoT Platform console, go to the Product Details page, and click the Data Parsing tab. 2. On the Data Parsing tab, enter a data parsing script in the Edit Script field.For more information about how to edit a data parsing script, visit Submit data parsing script.

This topic uses a device that sends data to IoT Platform in the hexadecimal format as an example. You must use the data parsing script to convert upstream data of the hexadecimal format to data of the Alink JSON format and downstream data of the Alink JSON format to data of the hexadecimal format. The following code shows how to edit a data parsing script.

var ALINK_ID = "12345";

var ALINK_VERSION = "1.1";

var ALINK_PROP_POST_METHOD = 'thing.event.property.post'; // var ALINK_EVENT_TEMPERR_METHOD = 'thing.event.TempError.post';

// var ALINK_EVENT_HUMIERR_METHOD = 'thing.event.HumiError.post';

var ALINK_PROP_SET_METHOD = 'thing.service.property.set'; // var ALINK_SERVICE_THSET_METHOD = 'thing.service.SetTempHumiThreshold';

/* * * * * * * Upstream data ->

* 0102 // Two bytes in total * Result ->

* {"method":"thing.event.TempError.post","id":"12345","params":{"Temperature": 2},"version":"1.1"} # Upstream data->

* 0202 // Two bytes in total * Result ->

* {"method":"thing.event.HumiError.post","id":"12345","params":{"Humidity":2}, "version":"1.1"} */

/*The following function converts upstream data that is reported from serial devices into a TSL m

odel of the Alink JSON format. */ function rawDataToProtocol(bytes) {

/*Convert upstream data into an array. Upstream data is stored in the bytes object. */ var uint8Array = new Uint8Array(bytes.length);

for (var i = 0; i < bytes.length; i++) {

uint8Array[i] = bytes[i] & 0xff; }

var params = {}; // Create an object to store properties. var jsonMap = {}; // Create an object that defines the format of an Alink message

109 > Document Version:20200922 物联网平台 Best Practices · Device access

var jsonMap = {}; // Create an object that defines the format of an Alink message

.

/* Specify header fields for an Alink message. */

jsonMap['version'] = ALINK_VERSION; // The version of the Alink protocol.

jsonMap['id'] = ALINK_ID; // The ID of the Alink message. jsonMap['method'] = ALINK_PROP_POST_METHOD; // The method that is used to report device pr

operties. /*Specify properties for the Alink message. */

params['speed'] = uint8Array[0]; // Convert the first byte that is received to the value of t

he spinning speed property. params['current'] = uint8Array[1]; // Convert the second byte that is received to the value

of the electrical current property.

jsonMap['params'] = params; //Pack the required parameters to a JSON array.

return jsonMap; // Return the results to IoT Platform.

}

// The following lists miscellaneous functions. function buffer_uint8(value)

{

var uint8Array = new Uint8Array(1); var dv = new DataView(uint8Array.buffer, 0);

dv.setUint8(0, value);

return [].slice.call(uint8Array); }

function buffer_int16(value)

{ var uint8Array = new Uint8Array(2);

var dv = new DataView(uint8Array.buffer, 0); dv.setInt16(0, value);

return [].slice.call(uint8Array);

} function buffer_int32(value)

{

var uint8Array = new Uint8Array(4); var dv = new DataView(uint8Array.buffer, 0);

dv.setInt32(0, value);

return [].slice.call(uint8Array); }

function buffer_float32(value)

> Document Version:20200922 110 Best Practices · Device access 物联网平台

{ var uint8Array = new Uint8Array(4);

var dv = new DataView(uint8Array.buffer, 0); dv.setFloat32(0, value);

return [].slice.call(uint8Array);

} /*The following function converts downstream data to hexadecimal data that can be recognized b

y the device. */

function protocolToRawData(json) {

var method = json['method'];

var id = json['id']; var version = json['version'];

var payloadArray = [];

if (method == ALINK_PROP_SET_METHOD) // If the Set Device Properties command is received f

rom IoT Platform, run the following code. {

var send_params = json['params'];

var prop_cur = send_params['setspeed']; // Specify the recevied value for the prop_cur para meter.

// Concatenate raw data based on the custom format. payloadArray = payloadArray.concat(buffer_uint8(0x55)); // The first byte that indicates the

header of a message. payloadArray = payloadArray.concat(buffer_uint8(prop_bool)); // The second byte that indica

tes the value of a property.

}

return payloadArray; // Send values to the device.

}

3. Run the script. Test data reporting. a. Select Upstreamed Device Data in the Simulation Type field. b. On the Input Simulation tab, enter test data in the text box.

The preceding script specifies the first byte as the spinning speed and the second byte as the electrical current. For example, if you specify 6410 as test data, the value 64 indicates that the spinning speed is 100 rpm and the value 10 indicates that the electrical current is 10 A.

111 > Document Version:20200922 物联网平台 Best Practices · Device access

c. Click Run.

The following figure shows the results on the Parsing Results tab.

Test data receiving. a. Select Received Device Data in the Simulation Type field. b. On the Input Simulation tab, specify test data in the text box. Specify the following parameters:

{ "method": "thing.service.property.set",

"id": "12345",

"version": "1.0", "params": {

"setspeed": 123

} }

> Document Version:20200922 112 Best Practices · Device access 物联网平台

c. Click Run. The following figure shows the results on the Parsing Results tab.

4. After you confirm that test data can be parsed by a script as expected, click Submit to submit the script to IoT Platform.

Note IoT Platform cannot call scripts that are in the draft state. Before IoT Platform can call a script, you must submit the script.

What's next

Configure a DTU device 1.10.3. Configure a DTU device

This topic describes how to use a data transmission unit (DTU) configuration tool to configure a serial port for a DTU device, obtain the device certificate information, and connect the DTU device to IoT Platform. The certificate information includes the ProductKey, DeviceName, and DeviceSecret parameters.

Context

This section uses an F2x16 DTU device as an example. You can use a PC to simulate the DTU device for data communication. Connect the DTU device to the PC by using a USB to serial adapter cable.

Note Make sure that the DTU device is connected to the Internet.

Procedure

1. Connect the DTU device to a USB port of the PC.

113 > Document Version:20200922 物联网平台 Best Practices · Device access

2. On the PC, open the DTU configuration tool. This topic uses an F2x16 configuration tool as an example. 3. Set a valid port number, set a baud rate, and open a serial port. 4. Click login configuration to bring DTU into the configuration state. 5. Click Read Configuration to obtain the current settings of the DTU device. 6. On the right side of the Configuration window, click Serial Port to configure a serial port.

Note You must select PORT in the Protocol field.

7. Click IoT Integration and specify the certificate information of the device and the name of the region where the device resides. You can obtain the information from the IoT Platform console. 8. Click Apply to apply the settings.If you fail to apply the settings, click Exit and try again later. 9. After the configuration is complete, click Exit to switch the DTS device to the normal mode. 10. Power off and then power on the DTU device. If the Online LED of the DTU device lights up, it indicates that the DTU device is connected to IoT Platform.You can also view the status of the DTU device in the IoT Platform console.

What's next

Test data communication 1.10.4. Test data communication

This topic describes how to use a data transmission unit (DTU) as a device to report data to IoT Platform and receive data from IoT Platform.

Test data reporting

1. Start a sierial port debugging tool. This topic uses sscom v4.2 as an example.

Note Before you use the debugging tool to simulate data sending and receiving, you must exit the DTU configuration tool.

> Document Version:20200922 114 Best Practices · Device access 物联网平台

2. Set the required parameters for the debugging tool, open a serial port, and then click Send.Set the spinning speed and electric current parameters based on the TSL model you created in IoT Platform. Then, send the values of the parameters to IoT Platform. Set the spinning speed to 150, electric current to 10 A. In the debugging tool, enter the following hex digits in sequence: 96 and 0A. 3. After data is sent, turn on the Real-time Refresh switch. i. Log on to the IoT Platform console. In the left-side navigation pane, choose Devices > Devices. ii. Find the target device and click View. iii. On the Device Details page, choose TSL Data > Status, and turn on the Real-time Refresh switch. Wait a few minutes until the uploaded data is displayed.

Test data receiving

On the Debug Physical Device tab, send a command to set the spinning speed, and test data receiving for the DTU device. 1. Log on to the IoT Platform console. In the left-side navigation pane, choose Maintenance > Online Debug. 2. Select the device that you want to debug and click the Debug Physical Device tab. 3. Select the spinning speed property in the Debug Feature field, select Set in the Method field, enter a value, and then click Send Command. 4. After the command is sent, view the received data in the debugging tool for the DTU device.

If data is displayed as expected in both the IoT Platform console and the device, it indicates a successful configuration. 1.11. Connect environmental sensors to IoT Platform by using HTTPS

Devices can be connected over HTTPS to IoT Platform only in the China (Shanghai) region. The HTTPS communication method is available only for scenarios where devices report data to IoT Platform. Only the POST request method is supported. A device can report a maximum of 128 KB of data at a time.

Context

This topic describes how to enable communication between a device and IoT Platform by using HTTPS and report data from the device to IoT Platform. It uses an environmental sensor as an example.

115 > Document Version:20200922 物联网平台 Best Practices · Device access

Create a product and add a device

In the IoT Platform console, create a product, add a device to the product, create a Thing Specification Language (TSL) model, and obtain certificate information about the device. The certificate information includes the ProductKey, DeviceName, and DeviceSecret parameters. 1. Log on to the IoT Platform console. 2. In the left-side navigation pane, choose Devices > Products. On the Products page, click Create Product to create a product.

Parameter Description

Product Name The name of the product.

[DO NOT TRANSLATE] [DO NOT TRANSLATE]

Node Type Select Directly Connected Device.

Network Connection Select Wi-Fi. Method

Data Type Select ICA Standard Data Format (Alink JSON).

Authentication Mode Select Device Secret.

3. After the product is created, click Create TSL. 4. On the Define Feature tab of the Product Details page, choose Edit Draft > Add Self-defined Feature to add properties.The environmental sensor will report temperature data and humidity data. Therefore, you must add the following properties.

Feature Feature Value Read/writ Identifier Data type Step type name range e type

Temperat temperatu Property int32 -10 to 50 1 Read-only ure re

Property Humidity humidity int32 1 to 100 1 Read-only

5. After the TSL model is created, click Release Online to publish the TSL model. 6. In the left-side navigation pane, click Devices and click Add Device to add a device to the product. After the device is added, obtain the values of ProductKey, DeviceName, and DeviceSecret

> Document Version:20200922 116 Best Practices · Device access 物联网平台

parameters.

Send data from a device to a topic

Use HTTPS to enable communication between a device and IoT Platform and use POST requests to report temperature data and humidity data.

1. Obtain a device token.

When a device attempts to communicate with IoT Platform, IoT will authenticate the device. After the authentication is complete, a device token is returned. The token is required when the device reports data to IoT Platform. The following table lists the parameters that you must specify to obtain a device token.

Parameter Description

method The request method. You must specify POST for the parameter.

uri Specify https://iot-as-http.cn-shanghai.aliyuncs.com/auth.

The product key. You can obtain the information from the Device Details productKey page of the IoT Platform console.

The name of the device. You can obtain the information from the Device deviceName Details page of the IoT platform console.

The client ID. The ID can be a maximum of 64 characters in length. The ID can clientId be the MAC address or SN of the device. The following sample code uses the random() function to generate a random ID.

The timestamp. The following sample code uses the now() function to obtain timestamp a timestamp.

signmethod The type of the algorithm. Valid values: hmacmd5 and hmacsha1.

The signature. Use the following function to generate a signature.

sign password = signHmacSha1(params, deviceConfig.deviceSecret)

Use the following code to obtain a device token.

var rp = require('request-promise'); const crypto = require('crypto');

const deviceConfig = { productKey: "",

deviceName: "",

deviceSecret: "" }

//Obtain a token.

117 > Document Version:20200922 物联网平台 Best Practices · Device access

rp(getAuthOptions(deviceConfig))

.then(function(parsedBody) { console.log('Auth Info :',parsedBody)

})

}).catch(function (err) { console.log('Auth err :'+JSON.stringify(err))

});

//Specify the required parameters for authentication.

function getAuthOptions(deviceConfig) {

const params = {

productKey: deviceConfig.productKey, deviceName: deviceConfig.deviceName,

timestamp: Date.now(),

clientId: Math.random().toString(36).substr(2), }

//Specify the required parameters. var password = signHmacSha1(params, deviceConfig.deviceSecret);

var options = { method: 'POST',

uri: 'https://iot-as-http.cn-shanghai.aliyuncs.com/auth', "body": {

"version": "default",

"clientId": params.clientId, "signmethod": "hmacSha1",

"sign": password,

"productKey": deviceConfig.productKey, "deviceName": deviceConfig.deviceName,

"timestamp": params.timestamp

}, json: true

};

return options;

}

//HmacSha1 sign

function signHmacSha1(params, deviceSecret) {

> Document Version:20200922 118 Best Practices · Device access 物联网平台

function signHmacSha1(params, deviceSecret) {

let keys = Object.keys(params).sort();

// Sort parameters in the alphabetical order. keys = keys.sort();

const list = []; keys.map((key) => {

list.push(`${key}${params[key]}`);

}); const contentStr = list.join('');

return crypto.createHmac('sha1', deviceSecret).update(contentStr).digest('hex');

}

After you specify the required parameters in the code, run the code to initiate device authentication. If the authentication is successful, a device token is returned.

Note A device token will expire after seven days. Make sure that you have solutions to token expiration issues.

2. Report data from the device.

After a device is authenticated, a token is returned. You can specify the token for the password parameter that is required for data reporting.

The following table lists the parameters that you must specify to report data.

Parameter Description

method The request method. You must specify POST.

The syntax is https://iot-as-http.cn-shanghai.aliyuncs.com/topic + topic . The URL consists of the HTTP endpoint of IoT Platform and the name of a topic.

uri The second topic specifies the name of a topic of the following syntax:

/sys/${deviceConfig.productKey}/${deviceConfig.deviceName}/thing/even

t/property/post

body The data to report.

password The device token.

Content-Type The content type of the data. Set the value to application/octet-stream.

119 > Document Version:20200922 物联网平台 Best Practices · Device access

The following code shows how to report data.

const topic = `/sys/${deviceConfig.productKey}/${deviceConfig.deviceName}/thing/event/propert

y/post`;

//Report data. pubData(topic, token, getPostData())

function pubData(topic, token, data) {

const options = { method: 'POST',

uri: 'https://iot-as-http.cn-shanghai.aliyuncs.com/topic' + topic,

body: data, headers: {

password: token,

'Content-Type': 'application/octet-stream' }

}

rp(options)

.then(function(parsedBody) { console.log('publish success :' + parsedBody)

})

.catch(function(err) { console.log('publish err ' + JSON.stringify(err))

});

}

// Create test data that conforms to the TSL model.

function getPostData() { var payloadJson = {

id: Date.now(), params: {

humidity: Math.floor((Math.random() * 20) + 60),

temperature: Math.floor((Math.random() * 20) + 10) },

method: "thing.event.property.post"

}

console.log("===postData\n topic=" + topic)

console.log(payloadJson)

> Document Version:20200922 120 Best Practices · Device access 物联网平台

return JSON.stringify(payloadJson); }

After you specify the required parameters in the code, run the code to report data. Then, view the results in local logs.

To find the temperature data and humidity data that are reported from the device, follow these steps: Log on to the IoT Platform console. Go to the Device Details page. View the data on the Status tab. If data is displayed as expected, it indicates that the device is connected to IoT Platform and the data is reported.

For more information about HTTPS communication, see Establish connections over HTTP. 1.12. Connect a Linux device to IoT Platform

You can run device SDK for C-based code on Linux devices and connect these devices to IoT Platform by using Message Queuing Telemetry Transport (MQTT). This topic describes how to provision and connect a device to IoT Platform. It uses sample code that is written based on device SDK for C as an example. You can run the sample code on Ubuntu x86_64.

Context

For more information about the device SDK for C, see the SDK for C documentation.

Create a product and add a device

1. Log on to the IoT Platform console. 2. In the left-side navigation pane, choose Devices > Products. On the Products page, click Create Product to create a product.

Parameter Description

Product Name The name of the product.

[DO NOT TRANSLATE] [DO NOT TRANSLATE]

Node Type Select Directly Connected Device.

Network Connection Select Wi-Fi. Method

Data Type Select ICA Standard Data Format (Alink JSON).

Authentication Mode Select Device Secret.

121 > Document Version:20200922 物联网平台 Best Practices · Device access

3. In the left-side navigation pane, click Devices. On the Devices page, click Add Device to add a device in the product. After the device is added, obtain the certificate information of the device. The certificate information includes the ProductKey, DeviceName, and DeviceSecret parameters.

Create a TSL model

IoT Platform provides the C SDK Demo package. You can obtain a sample Thing Specification Language (TSL) model that is included in a JSON file of the package. Import the JSON file and apply the TSL model to the device.

1. Edit the JSON file. i. Download the C SDK Demo package. ii. Decompress the package, and open the model_for_examples.json file in the src/dev_mo del/examples directory.

iii. Specify the value of the ProductKey that you obtain from IoT Platform for the productKey parameter in the JSON file. Then, save the file.

2. On the Products page of the IoT Platform console, find the new device and click View. 3. On the Define Feature tab of the Product Details page, choose Edit Draft > Import. 4. In the Import TSL dialog box, click the Import TSL tab, upload the JSON file that you edited in the preceding step, and click OK.

> Document Version:20200922 122 Best Practices · Device access 物联网平台

After the file is imported, all features that are defined in the JSON file are displayed on the Edit Draft page. 5. Click Release Online to publish the TSL model.

Configure the C SDK Demo package

In an Integrated Development Environment (IDE), import the C SDK Demo package as a project and replace the information in the following configuration file with the information of your device.

1. In the HAL_OS_linux.c file of the wrappers/os/ubuntu directory, specify the certificate information of your device.

2. Compile the project In the working directory of the project, run the make reconfig command, enter 3, and then run the make command.

123 > Document Version:20200922 物联网平台 Best Practices · Device access

3. Run the projectIn the working directory of the project, run the ./src/dev_model/examples/linkkit_example_solo project. The following figure shows the result.

After you run the project, view the status of the device and the TSL model that the device reports on the Product Details of the IoT Platform console.

> Document Version:20200922 124 Best Practices · Communications 物联网平台

2.Communications 2.1. Use custom topics for communication

You can define custom topic categories in IoT Platform. Then, a device can send messages to a custom topic, and your server can receive the messages using an AMQP SDK. Your server can also call the API operation Pub to send commands to the device.

Scenario

In this example, an electronic thermometer periodically exchanges data with a server. The thermometer sends the current temperature to the server, and the server sends the precision setting command to the thermometer.

Prepare the development environment

In this example, both the devices and the server use Java SDKs, so you need to prepare the Java development environment first. You can download Java tools at Java official website and install the Java development environment.

Add the following Maven dependencies to import the device SDK (Link Kit Java SDK) and IoT SDK:

125 > Document Version:20200922 物联网平台 Best Practices · Communications

com.aliyun.alink.linksdk

iot-linkkit-java

1.2.0.1 compile

< dependency> com.aliyun

aliyun-java-sdk-core 3.7.1

com.aliyun

aliyun-java-sdk-iot

6.9.0

com.aliyun.openservices iot-client-message

1.1.2

Create a product and a device

First, you need to create a product, define custom topic categories, define the TSL model, configure server-side subscription, and create a device in the IoT Platform console.

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 product is created, find the product and click View. 5. On the Topic Categories tab of the Product Details page, add custom topic categories.

For more information, see Create a topic category.

In this example, add the following two topic categories:

/${productKey}/${deviceName}/user/devmsg: used by devices to publish messages. Set Device Operation Authorizations to Publish for this topic category. /${productKey}/${deviceName}/user/cloudmsg: used by devices to receive subscribed messages. Set Device Operation Authorizations to Subscribe for this topic category.

> Document Version:20200922 126 Best Practices · Communications 物联网平台

6. On the Server-side Subscription page, set the type of messages to be pushed to the AMQP SDK to Device Upstream Notification. For more information, see Configure AMQP server-side subscription in the console 7. In the left-side navigation pane, choose Devices and add a thermometer device under the thermometer product that has been created. For more information, see Create a device.

The server receives messages from the device

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

Configure the AMQP SDK, which will be installed in the server, to receive messages from IoT Platform. Add the following dependency to install Qpid JMS 0.47.0.

org.apache.qpid

qpid-jms-client 0.47.0

commons-codec commons-codec

1.10

Connect the AMQP SDK to IoT Platform.

For information about the parameters in the following demo, see Connect an AMQP client to IoT Platform.

import java.net.URI;

import java.util.Hashtable;

import javax.crypto.Mac;

127 > Document Version:20200922 物联网平台 Best Practices · Communications

import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec;

import javax.jms.Connection; import javax.jms.ConnectionFactory;

import javax.jms.Destination;

import javax.jms.Message; import javax.jms.MessageConsumer;

import javax.jms.MessageListener;

import javax.jms.MessageProducer; import javax.jms.Session;

import javax.naming.Context;

import javax.naming.InitialContext; import org.apache.commons.codec.binary.Base64;

import org.apache.qpid.jms.JmsConnection; import org.apache.qpid.jms.JmsConnectionListener;

import org.apache.qpid.jms.message.JmsInboundMessageDispatch;

import org.slf4j.Logger; import org.slf4j.LoggerFactory;

public class AmqpJavaClientDemo {

private final static Logger logger = LoggerFactory.getLogger(AmqpJavaClientDemo.class);

public static void main(String[] args) throws Exception {

//For information about parameters, see AMQP client access instructions.

String accessKey = "$ {YourAccessKeyID }"; String accessSecret = "${YourAccessKeySecret}";

String consumerGroupId = "${YourConsumerGroupId}"; long timeStamp = System.currentTimeMillis();

//Signature method: hmacmd5, hmacsha1, or hmacsha256.

String signMethod = "hmacsha1"; //The value of the clientId parameter is displayed as the client ID on the consumer group stat

us page for server-side subscription in the console.

//We recommend that you use a unique identifier, such as the UUID, MAC address, or IP addre ss as the clientId value. This allows you to identify clients.

String clientId = "$ {YourClientId }";

//For information about how to obtain the value of UserName, see AMQP client access instru

ctions. String userName = clientId + "| authMode = aksign"

+ ",signMethod=" + signMethod

> Document Version:20200922 128 Best Practices · Communications 物联网平台

+ ",timestamp=" + timeStamp + ",authId=" + accessKey

+ ",consumerGroupId=" + consumerGroupId

+ "|"; //For information about how to obtain the value of password, see AMQP client access instruc

tions.

String signContent = "authId =" + accessKey + "& timestamp =" + timeStamp; String password = doSign(signContent,accessSecret, signMethod);

//Construct the connection URL based on the rules described in Qpid JMS documentation. String connectionUrl = "failover:(amqps://${uid}.iot-amqp.${regionId}.aliyuncs.com:5671? amq

p.idleTimeout=80000)"

+ "? failover.reconnectDelay=30";

Hashtable hashtable = new Hashtable<>();

hashtable.put("connectionfactory.SBCF",connectionUrl); hashtable.put("queue.QUEUE", "default");

hashtable.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContex

tFactory"); Context context = new InitialContext(hashtable);

ConnectionFactory cf = (ConnectionFactory)context.lookup("SBCF");

Destination queue = (Destination)context.lookup("QUEUE"); // Create Connection

Connection connection = cf.createConnection(userName, password); ((JmsConnection) connection).addConnectionListener(myJmsConnectionListener);

// Create Session

// Session. Client_acknowledgment: After you receive the message, manually call message.a cknowledge().

// Session. Auto_acknowledgment: The SDK is automatically acknowledged. (recommended)

Session session = connection. createSession (false, Session. Auto_acknowledgment ); connection.start();

// Create Receiver Link

MessageConsumer consumer = session.createConsumer(queue); consumer.setMessageListener(messageListener);

}

private static MessageListener messageListener = new MessageListener() {

@Override public void onMessage(Message message) {

try {

byte[] body = message.getBody(byte[].class); String content = new String(bytes);

129 > Document Version:20200922 物联网平台 Best Practices · Communications

String content = new String(bytes);

String topic = message.getStringProperty("topic");

String messageId = message.getStringProperty("messageId"); logger.info("receive message"

+ ", topic = " + topic + ", messageId = " + messageId

+ ", content = " + content);

//If you select Session.CLIENT_ACKNOWLEDGE when creating a session, manual acknowle dgment is required.

//message.acknowledge();

//Ensure that no time-consuming logic exists during message processing. If processing r eceived messages takes a long period of time, initiate asynchronous requests.

} catch (Exception e) {

e.printStackTrace(); }

}

};

private static JmsConnectionListener myJmsConnectionListener = new JmsConnectionListener() {

/**

* The connection is successfully established. */

@Override

public void onConnectionEstablished(URI remoteURI) { logger.info("onConnectionEstablished, remoteUri:{}", remoteURI);

}

/**

* The connection fails after the maximum number of retries. */

@Override

public void onConnectionFailure(Throwable error) { logger.error("onConnectionFailure, {}", error.getMessage());

}

/**

* The connection is interrupted.

*/ @Override

public void onConnectionInterrupted(URI remoteURI) { logger.info("onConnectionInterrupted, remoteUri:{}", remoteURI);

> Document Version:20200922 130 Best Practices · Communications 物联网平台

logger.info("onConnectionInterrupted, remoteUri:{}", remoteURI);

}

/**

* The connection is interrupted and automatically restored.

*/ @Override

public void onConnectionRestored(URI remoteURI) {

logger.info("onConnectionRestored, remoteUri:{}", remoteURI); }

@Override public void onInboundMessage(JmsInboundMessageDispatch envelope) {}

@Override

public void onSessionClosed(Session session, Throwable cause) {}

@Override

public void onConsumerClosed(MessageConsumer consumer, Throwable cause) {}

@Override

public void onProducerClosed(MessageProducer producer, Throwable cause) {}

};

/** * To obtain the string to sign in the value of password, see AMQP client access instructions.

*/

private static String doSign(String toSignString, String secret, String signMethod) throws Excep tion {

SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), signMethod);

Mac mac = Mac.getInstance(signMethod); mac.init(signingKey);

Byte [] rawHmac = mac. doFinal (toSignString. getBytes ());

return Base64.encodeBase64String(rawHmac); }

}

Configure the device SDK to send a message.

131 > Document Version:20200922 物联网平台 Best Practices · Communications

Configure device authentication information.

final String productKey = "XXXXXX";

final String deviceName = "XXXXXX"; final String deviceSecret = "XXXXXXXXX";

final String region = "XXXXXX";

Set connection initialization parameters, including MQTT connection information, device information, and initial device status.

LinkKitInitParams params = new LinkKitInitParams();

// Configure MQTT connection information. Link Kit 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"; // Configure device information.

DeviceInfo deviceInfo = new DeviceInfo();

deviceInfo.productKey = productKey; deviceInfo.deviceName = deviceName;

deviceInfo.deviceSecret = deviceSecret;

// Register the initial device status. Map propertyValues = new HashMap();

params.mqttClientConfig = config; params.deviceInfo = deviceInfo;

params.propertyValues = propertyValues;

> Document Version:20200922 132 Best Practices · Communications 物联网平台

Initialize the connection.

// Initialize the connection and set the callback that is called when the initialization is successful.

LinkKit.getInstance().init(params, new ILinkKitConnectListener() { @Override

public void onError(AError aError) {

System.out.println("Init error:" + aError); }

// Set the callback that is called when the initialization is successful. @Override

public void onInitDone(InitResult initResult) { System.out.println("Init done:" + initResult);

}

});

133 > Document Version:20200922 物联网平台 Best Practices · Communications

Send a message from the device.

After connecting to IoT Platform, the device sends a message to the specified topic. Replace the content of the onInitDone callback like 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 set the callback that is called when 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 messages to the device

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

> Document Version:20200922 134 Best Practices · Communications 物联网平台

Configure the device SDK to subscribe to a topic.

For more information about how to configure device authentication information, set connection initialization parameters, and initialize the connection, see the device SDK configuration in the previous section. The device needs to subscribe to a specific topic to receive messages sent by the server.

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

// Set the callback that is called when the initialization is successful.

@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 set the callbacks that are called when the subscription succee ds and fails, respectively.

LinkKit.getInstance().subscribe(request, new IConnectSubscribeListener() {

@Override public void onSuccess() {

System.out.println("");

}

@Override public void onFailure(AError aError) {

} });

// Set the listener for listening to subscribed messages. IConnectNotifyListener notifyListener = new IConnectNotifyListener() {

135 > Document Version:20200922 物联网平台 Best Practices · Communications

IConnectNotifyListener notifyListener = new IConnectNotifyListener() {

// Define the callback that is called when a subscribed message is 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 SDK to call the Pub operation to publish a message. Configure identity verification information.

String regionId = "The ID of the region where the device is located";

String accessKey = "The AccessKey ID of your Alibaba Cloud account";

String accessSecret = "The AccessKey Secret of your Alibaba Cloud account"; final String productKey = "The key of the product";

Set connection parameters.

// Construct a client. DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKey, accessSecret);

IAcsClient client = new DefaultAcsClient(profile);

> Document Version:20200922 136 Best Practices · Communications 物联网平台

Set the parameters for publishing 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 message content. The message content must be encoded in Base64. Otherwise, the me ssage content will be 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: demo

Click here to download and view the complete demo for this example.

For more information about server-side subscription, see:

Configure AMQP server-side subscription in the console

Connect an AMQP client to IoT Platform

Java SDK access example

Node.js SDK access example

.NET SDK access example

Python 2.7 SDK access example 2.2. Control Raspberry Pi servers from IoT Platform

Alibaba Cloud IoT Platform allows you to remotely control Raspberry Pi servers without public IP addresses. This topic describes how to control Raspberry Pi servers from IoT Platform, and provides sample development code.

Background information

137 > Document Version:20200922 物联网平台 Best Practices · Communications

Assume that you use Raspberry Pi to build a server at your company or home to run some simple tasks, such as starting a script or downloading files. However, if the Raspberry Pi server does not have a public IP address, you cannot control the server when you are not in the company or at home. If you use other NAT traversal tools to contol the server, disconnection may occur frequently. To resolve these issues, you can combine the IoT Platform RRPC (remote synchronous process call) function with JSch to control the Raspberry Pi server from IoT Platform.

Process

Use the following process to control a Raspberry Pi server from IoT Platform:

Call the IoT Platform RRPC method from your computer to send an SSH command. After receiving the SSH command, IoT Platform sends the SSH command to the Raspberry Pi server by using MQTT. The server runs the SSH command. The server encapsulates the command output into an RRPC response and reports the response to IoT Platform by using MQTT. IoT Platform returns the RRPC response to the computer.

Note The RRPC call timeout period is 5 seconds. If IoT Platform does not receive any reply from the Raspberry Pi server within 5 seconds, a timeout error will be returned. If the command you have sent takes a relatively long time to process, you can ignore the timeout error.

Download SDKs and demos

To remotely control Raspberry Pi servers, you must first develop the server SDK and device SDK. Install the IoT Platform server SDK on the computer. To develop the server, you can use the server Java SDK demo. Install the IoT Platform device SDK on the Raspberry Pi server. To develop the device, use the device Java SDK Demo. The following sections provide examples about how to develop the server SDK and device SDK.

> Document Version:20200922 138 Best Practices · Communications 物联网平台

Note In the examples, only simple Linux commands are supported in the code, such as uname, touch, and mv. Complex commands such as file editing are not supported. To implement complex commands, you must write code as needed.

Develop the device SDK

After you have downloaded and installed the device SDK and SDK demo, add project dependencies and the following Java files.

The project can be exported as a JAR package and run on the Raspberry Pi server.

1. Add dependencies to the pom.xml file.

com.aliyun.alink.linksdk iot-linkkit-java

1.1.0

compile

com.google.code.gson

gson

2.8.1 compile

com.alibaba

fastjson

1.2.40 compile

com.jcraft

jsch 0.1.55

2. Add the SSHShell.java file that is used to run SSH commands.

public class SSHShell {

139 > Document Version:20200922 物联网平台 Best Practices · Communications

private String host;

private String username;

private String password;

private int port;

private Vector stdout;

public SSHShell(final String ipAddress, final String username, final String password, final int por

t) { this.host = ipAddress;

this.username = username;

this.password = password; this.port = port;

this.stdout = new Vector(); }

public int execute(final String command) {

System.out.println("ssh command: " + command);

int returnCode = 0;

JSch jsch = new JSch();

SSHUserInfo userInfo = new SSHUserInfo();

try { Session session = jsch.getSession(username, host, port);

session.setPassword(password);

session.setUserInfo(userInfo); session.connect();

Channel channel = session.openChannel("exec"); ((ChannelExec) channel).setCommand(command);

channel.setInputStream(null); BufferedReader input = new BufferedReader(new InputStreamReader(channel.getInputStr

eam()));

channel.connect();

> Document Version:20200922 140 Best Practices · Communications 物联网平台

channel.connect();

String line = null;

while ((line = input.readLine()) ! = null) {

stdout.add(line); }

input.close();

if (channel.isClosed()) {

returnCode = channel.getExitStatus();

}

channel.disconnect(); session.disconnect();

} catch (JSchException e) {

e.printStackTrace(); } catch (Exception e) {

e.printStackTrace();

}

return returnCode;

}

public Vector getStdout() { return stdout;

}

}

3. Add the SSHUserInfo.java file that is used to verify the SSH account and password.

141 > Document Version:20200922 物联网平台 Best Practices · Communications

public class SSHUserInfo implements UserInfo {

@Override

public String getPassphrase() { return null;

}

@Override

public String getPassword() {

return null; }

@Override

public boolean promptPassphrase(final String arg0) {

return false; }

@Override public boolean promptPassword(final String arg0) {

return false;

}

@Override

public boolean promptYesNo(final String arg0) { if (arg0.contains("The authenticity of host")) {

return true; }

return false;

}

@Override

public void showMessage(final String arg0) { }

}

4. Add the Device.java file that is used to establish an MQTT connection.

public class Device {

/**

* Establish a connection

> Document Version:20200922 142 Best Practices · Communications 物联网平台

* Establish a connection *

* @param productKey The product key

* @param deviceName The device name * @param deviceSecret The device secret

* @throws InterruptedException

*/ public static void connect(String productKey, String deviceName, String deviceSecret) throws Int

erruptedException {

//Initialization parameters

LinkKitInitParams params = new LinkKitInitParams();

//Set MQTT initialization parameters

IoTMqttClientConfig config = new IoTMqttClientConfig(); config.productKey = productKey;

config.deviceName = deviceName;

config.deviceSecret = deviceSecret; params.mqttClientConfig = config;

//Set device certificate information for initialization and import the certificate information DeviceInfo deviceInfo = new DeviceInfo();

deviceInfo.productKey = productKey; deviceInfo.deviceName = deviceName;

deviceInfo.deviceSecret = deviceSecret;

params.deviceInfo = deviceInfo;

//Initialize the SDK

LinkKit.getInstance().init(params, new ILinkKitConnectListener() { public void onError(AError aError) {

System.out.println("init failed !! code=" + aError.getCode() + ",msg=" + aError.getMsg() +

",subCode=" + aError.getSubCode() + ",subMsg=" + aError.getSubMsg());

}

public void onInitDone(InitResult initResult) {

System.out.println("init success !!") ; }

});

//Perform the subsequent operations only after the initialization is complete. You can increa

143 > Document Version:20200922 物联网平台 Best Practices · Communications

se the sleep time as needed.

Thread.sleep(2000); }

/** * Publish a message

* * @param topic The topic to which the message is published

* @param payload The message payload

*/ public static void publish(String topic, String payload) {

MqttPublishRequest request = new MqttPublishRequest();

request.topic = topic; request.payloadObj = payload;

request.qos = 0;

LinkKit.getInstance().getMqttClient().publish(request, new IConnectSendListener() { @Override

public void onResponse(ARequest aRequest, AResponse aResponse) { }

@Override public void onFailure(ARequest aRequest, AError aError) {

}

}); }

/** * Subscribe to a topic

* * @param topic The topic of messages to subscribe to

*/

public static void subscribe(String topic) { MqttSubscribeRequest request = new MqttSubscribeRequest();

request.topic = topic;

request.isSubscribe = true; LinkKit.getInstance().getMqttClient().subscribe(request, new IConnectSubscribeListener() {

@Override

public void onSuccess() { }

@Override

> Document Version:20200922 144 Best Practices · Communications 物联网平台

@Override public void onFailure(AError aError) {

} });

}

/**

* Unsubscribe from a topic

* * @param topic The topic of messages to unsubscribe from

*/

public static void unsubscribe(String topic) { MqttSubscribeRequest request = new MqttSubscribeRequest();

request.topic = topic; request.isSubscribe = false;

LinkKit.getInstance().getMqttClient().unsubscribe(request, new IConnectUnscribeListener() {

@Override public void onSuccess() {

}

@Override

public void onFailure(AError aError) {

} });

}

/**

* Terminate the connection */

public static void disconnect() {

//Perform the deinitialization LinkKit.getInstance().deinit();

}

}

5. Add the SSHDevice.java file. The SSHDevice.java file includes the main method. You can call the main method to receive RRPC commands, call SSHShell to run SSH commands, and return RRPC responses. In the SSHDevice.java file, you must enter the device certificate information, including ProductKey, DeviceName, and DeviceSecret, and the SSH account and password.

public class SSHDevice {

145 > Document Version:20200922 物联网平台 Best Practices · Communications

//======Start to Enter Required Parameters======//ProductKey

private static String productKey = "";

// private static String deviceName = "";

//DeviceSecret

private static String deviceSecret = ""; //The message communication topic. You can directly use the topic without creating or defining

the topic.

private static String rrpcTopic = "/sys/" + productKey + "/" + deviceName + "/rrpc/request/+"; //The domain name or IP address that you want to access by using SSH

private static String host = "127.0.0.1"; //The SSH username

private static String username = "";

//The SSH password private static String password = "";

//The SSH port

private static int port = 22; //======End======

public static void main(String[] args) throws InterruptedException {

//Listen to downstream data

registerNotifyListener();

//Establish the connection Device.connect(productKey, deviceName, deviceSecret);

//Subscribe to a topic Device.subscribe(rrpcTopic);

}

public static void registerNotifyListener() {

LinkKit.getInstance().registerOnNotifyListener(new IConnectNotifyListener() {

@Override public boolean shouldHandle(String connectId, String topic) {

//Only process messages of the specified topic if (topic.contains("/rrpc/request/")) {

return true;

} else {

> Document Version:20200922 146 Best Practices · Communications 物联网平台

} else { return false;

}

}

@Override

public void onNotify(String connectId, String topic, AMessage aMessage) { //Receive RRPC requests and resturn RRPC responses

try { //Run the SSH command

String payload = new String((byte[]) aMessage.getData(), "UTF-8");

SSHShell sshExecutor = new SSHShell(host, username, password, port); sshExecutor.execute(payload);

//Obtain the command output StringBuffer sb = new StringBuffer();

Vector stdout = sshExecutor.getStdout();

for (String str : stdout) { sb.append(str);

sb.append("\n");

}

//Return command output to the server String response = topic.replace("/request/", "/response/");

Device.publish(response, sb.toString());

} catch (UnsupportedEncodingException e) { e.printStackTrace();

}

}

@Override

public void onConnectStateChange(String connectId, ConnectState connectState) { }

}); }

}

Develop the server SDK

After you have downloaded and installed the server SDK and SDK demo, add project dependencies and the following Java files.

147 > Document Version:20200922 物联网平台 Best Practices · Communications

1. Add dependencies to the pom.xml file.

com.aliyun

aliyun-java-sdk-iot 6.5.0

com.aliyun

aliyun-java-sdk-core 3.5.1

commons-codec commons-codec

1.8

2. Add the OpenApiClient.java file that is used to call the IoT Platform API.

> Document Version:20200922 148 Best Practices · Communications 物联网平台

public class OpenApiClient {

private static DefaultAcsClient client = null;

public static DefaultAcsClient getClient(String accessKeyID, String accessKeySecret) {

if (client ! = null) {

return client;

}

try {

IClientProfile profile = DefaultProfile.getProfile("cn-shanghai", accessKeyID, accessKeySecr et);

DefaultProfile.addEndpoint("cn-shanghai", "cn-shanghai", "Iot", "iot.cn-shanghai.aliyuncs.c

om"); client = new DefaultAcsClient(profile);

} catch (Exception e) { System.out.println("create Open API Client failed !! exception:" + e.getMessage());

}

return client;

}

}

3. Add the SSHCommandSender.java file. The SSHCommandSender.java file contains the main method that is used to send SSH commands and receive responses to SSH commands. In the SSHCommandSender.java file, you must enter your Alibaba Cloud account information including AccessKey ID and AccessKey Secret, and device certificate information including ProductKey and DeviceName, and SSH command.

public class SSHCommandSender {

//======Start to Enter Required Parameters======

//AccessKey ID of your Alibaba Cloud account

private static String accessKeyID = "";

//AccessKey Secret of your Alibaba Cloud account

private static String accessKeySecret = "";

149 > Document Version:20200922 物联网平台 Best Practices · Communications

private static String accessKeySecret = "";

//ProductKey

private static String productKey = "";

//DeviceName

private static String deviceName = "";

//======End======

public static void main(String[] args) throws ServerException, ClientException, UnsupportedEnco

dingException {

//The Linux command

String payload = "uname -a";

//Construct an RRPC request

RRpcRequest request = new RRpcRequest();

request.setProductKey(productKey);

request.setDeviceName(deviceName);

request.setRequestBase64Byte(Base64.encodeBase64String(payload.getBytes()));

request.setTimeout(5000);

//Obtain information about the client connected to the Raspberry Pi server

DefaultAcsClient client = OpenApiClient.getClient(accessKeyID, accessKeySecret);

//Initiate an RRPC request

> Document Version:20200922 150 Best Practices · Communications 物联网平台

RRpcResponse response = (RRpcResponse) client.getAcsResponse(request);

//Process an RRPC response

//"response.getSuccess()" only indicates that the RRPC request has been sent. It does not in dicate that the device has received the RRPC request and has returned a response.

//Identify whether the message has been received and a response has been returned accord ing to the RrpcCode value. For more information, see the document of RRpc API https://www.aliba

bacloud.com/help/doc-detail/69797.htm.

if (response ! = null && "SUCCESS".equals(response.getRrpcCode())) {

//Output the response

System.out.println(new String(Base64.decodeBase64(response.getPayloadBase64Byte()), " UTF-8"));

} else {

//An error occurred while outputting the response and an RRPC code is displayed.

System.out.println(response.getRrpcCode());

}

}

}

2.3. TSL model communication

Devices exchange Thing Specification Language (TSL) models with IoT Platform over the Alink protocol. During the communication, devices report properties or events to IoT Platform, and IoT Platform also delivers messages to devices to set properties or invoke services. This topic provides the Java demo to describe how to configure the code for TSL model communication.

Internet of Things IoT IoT Platform TSL model TSL Communications

Create a product and a device

151 > Document Version:20200922 物联网平台 Best Practices · Communications Create a product and a device

You must create a product and a device, and define features for the product. 1. 2. In the 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.

The following example shows the properties, services, and events of the product.

For more information, see Add a TSL feature.

5. In the left-side navigation pane, click Devices to create devices. The following example includes how to set the same property of multiple devices under the same product and invoke the same service 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

In the following example, the SDK demo contains the server SDK and the device SDK.

1. Click here to download iotx-api-demo, and decompress the package. 2. Open the Java development tool and import the decompressed iotx-api-demo folder. 3. In the java directory, add the following Maven dependencies to the pom file to import the server SDK and device SDK.

> Document Version:20200922 152 Best Practices · Communications 物联网平台

com.aliyun

aliyun-java-sdk-iot

6.5.0

com.aliyun aliyun-java-sdk-core

3.5.1

com.aliyun.alink.linksdk iot-linkkit-java

1.2.0.1

compile

4. In the directory java/src/main/resources/, configure the initialization in the config file.

user.accessKeyID = user.accessKeySecret =

iot.regionId = iot.productCode = Iot

iot.domain = iot..aliyuncs.com

iot.version = 2018-01-20

Parameter Description

The AccessKey ID of your Alibaba Cloud account.

Place the pointer on your profile icon in the console, select AccessKey to accessKeyID go to the User Management page. You can create or check your AccessKey in User Management.

The AccessKey Secret of your Alibaba Cloud account. You can check the accessKeySecret AccessKey Secret in the same way as the AccessKey ID.

The ID of the region where your IoT devices are located. For more regionId information about region ID expressions, see .

Report properties and events by using the device SDK

Configure the device SDK to connect to IoT Platform and report properties and events.

153 > Document Version:20200922 物联网平台 Best Practices · Communications

The ThingTemplate file in the directory java/src/main/com.aliyun.iot.api.common.deviceApi contains the demo that devices use to report properties and events.

Configure the connection information.

In this demo, replace the parameters productKey, deviceName, and deviceSecret with the certificate of your device, and replace the regionId parameter with the region ID.

public static void main(String[] args) {

/**

* The certificate of your 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 of this device server 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();

/** * Specifies the parameters for the MQTT 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";

> Document Version:20200922 154 Best Practices · Communications 物联网平台

config.channelHost = deviceInfo.productKey + ".iot-as-mqtt." + region + ".aliyuncs.com:1883";

/** * Specifies whether to receive offline messages.

* The cleanSession field corresponding to the MQTT connection.

*/ config.receiveOfflineMsg = false;

params.mqttClientConfig = config;

ALog.setLevel(LEVEL_DEBUG); ALog.i(TAG, "mqtt connection info=" + params);

/**

* Specifies the initialization and passes in the certificate information of the specified device.

*/ params.deviceInfo = deviceInfo;

/**Establishes 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 properties = LinkKit.getInstance().getDeviceThing().getProperties();

ALog.i(TAG, "List of device properties" + JSON.toJSONString(properties));

List getEvents = LinkKit.getInstance().getDeviceThing().getEvents();

ALog.i(TAG, "List of device events" + JSON.toJSONString(getEvents));

//Reports a property. handlePropertySet("MicSwitch", new ValueWrapper.IntValueWrapper(3));

Map values = new HashMap<>();

values.put("eventValue",new ValueWrapper.IntValueWrapper(0));

OutputParams outputParams = new OutputParams(values); //Reports an event.

handleEventSet("Offline_alarm",outputParams);

155 > Document Version:20200922 物联网平台 Best Practices · Communications

}

});

}

Note The property and event identifiers in the code must be the same as the identifiers defined in the TSL model.

Configure the SDK for the device to report properties.

/**

* The device reports 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 reportData = new HashMap<>();

reportData.put(identifier, value);

LinkKit.getInstance().getDeviceThing().thingPropertyPost(reportData, new IPublishResourceLis

tener() {

public void onSuccess(String s, Object o) { // The property is reported.

ALog.i(TAG, "Reported. onSuccess() called with: s = [" + s + "], o = [" + o + "]");

}

public void onError(String s, AError aError) {

// Failed to report the property. ALog.i(TAG, "Failed to report. onError() called with: s = [" + s + "], aError = [" + JSON.toJSONS

tring(aError) + "]");

} });

}

Configure the SDK for the device to report events.

> Document Version:20200922 156 Best Practices · Communications 物联网平台

/**

* The device reports events in the Alink JSON format.

* @param identifyID 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 IPublishResour

ceListener() {

public void onSuccess(String s, Object o) { // The event is reported.

ALog.i(TAG, "Reported. onSuccess() called with: s = [" + s + "], o = [" + o + "]");

}

public void onError(String s, AError aError) {

// Failed to report the event. ALog.i(TAG, "Failed to report. onError() called with: s = [" + s + "], aError = [" + JSON.toJSONS

tring(aError) + "]");

} });

}

The server SDK of IoT Platform issues commands to set properties and invoke services

Initialize the SDK client.

The IotClient file in the directory java/src/main/com.aliyun.iot.client contains the demo for initializing the SDK 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();

157 > Document Version:20200922 物联网平台 Best Practices · Communications

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

// Initializes 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 encapsulated in the demo.

> Document Version:20200922 158 Best Practices · Communications 物联网平台

The AbstractManager file in the directory java/src/main/com.aliyun.iot.api.common.openApi contains the demo that encapsulates the CommonRequest public class. You can use the public class to call API operations of IoT Platform.

public class AbstractManager {

private static DefaultAcsClient client; static {

client = IotClient.getClient();

} /**

* action: the operation that you want to perform.

* domain: the endpoint of the service of IoT Platform. * version: the version of the operation.

*/

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;

}

Configure the server SDK to call the API operations of IoT platform, and issue corresponding commands to set properties and invoke services.

The file ThingManagerForPopSDk in the directory java/src/main/com.aliyun.iot.api.common.op enApi contains the server SDK demo for calling API operations to set properties and invoke services.

159 > Document Version:20200922 物联网平台 Best Practices · Communications

Call the SetDeviceProperty operation to set a device property.

public static void SetDeviceProperty(String IotId, String ProductKey, String DeviceName , String Ite

ms) { 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 device property.");

LogUtil.error(JSON.toJSONString(response));

}

} catch (ClientException e) { e.printStackTrace();

LogUtil.error("Failed to set device property." + JSON.toJSONString(response));

} }

Call the SetDevicesProperty operation to set same properties of multiple devices under the same product.

> Document Version:20200922 160 Best Practices · Communications 物联网平台

/**

* Set the same properties of multiple devices under the same product. *

* @param ProductKey The ProductKey that the target devices belong to. * @param DeviceNames The list of the target devices.

* @param Items The property key:value list in JSON format. You must specify this parameter.

* * @Des Description:

*/

public static void SetDevicesProperty(String ProductKey, List DeviceNames, String Item s) {

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 properties are set.");

LogUtil.print(JSON.toJSONString(response));

} else { LogUtil.print("Failed to set the properties.");

LogUtil.error(JSON.toJSONString(response));

} } catch (ClientException e) {

e.printStackTrace(); LogUtil.error("Failed to set the properties." + JSON.toJSONString(response));

}

}

Call the InvokeThingService operation to invoke a device service.

161 > Document Version:20200922 物联网平台 Best Practices · Communications

/**

* @param Identifier The identifier of the service. You must specify this parameter. * @param Args The arguments for invoking the target service. You must specify this param

eter.

*/ public static InvokeThingServiceResponse.Data InvokeThingService(String IotId, String Product

Key, 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 invoked."); LogUtil.print(JSON.toJSONString(response));

} else {

LogUtil.print("Failed to invoke the service."); LogUtil.error(JSON.toJSONString(response));

}

return response.getData();

} catch (ClientException e) {

e.printStackTrace(); LogUtil.error("Failed to invoke the service." + JSON.toJSONString(response));

} return null;

}

> Document Version:20200922 162 Best Practices · Communications 物联网平台

Call the InvokeThingsService operation to invoke the same service of multiple devices.

/**

* @param Identifier The identifier of the service. You must specify this parameter.

* @param Args The arguments for invoking the service. You must the specify this parameter. */

public static void InvokeThingsService(String IotId, String ProductKey, List DeviceName

s, 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 services are invoked."); LogUtil.print(JSON.toJSONString(response));

} else { LogUtil.print("Failed to invoke the services.");

LogUtil.error(JSON.toJSONString(response));

}

} catch (ClientException e) {

e.printStackTrace(); LogUtil.error("Failed to invoke the services." + JSON.toJSONString(response));

}

}

Sample requests for setting properties and invoking services:

163 > Document Version:20200922 物联网平台 Best Practices · Communications

public static void main(String[] args) {

/**Connects a device to IoT Platform.*/

String deviceName = "2pxuAQB2I7wGPmqq****"; String deviceProductkey = "a1QbjI2***";

//1. Sets a property of the device. SetDeviceProperty(null, deviceProductkey, deviceName,"{\"hue\":0}");

//2. Sets the same property of multiple devices under the same product.

List deviceNames = new ArrayList<>(); deviceNames.add(deviceName);

SetDevicesProperty(deviceProductkey, deviceNames, "{\"hue\":0}");

//3. Invokes the service of the specified device. InvokeThingService(null, deviceProductkey, deviceName, "ModifyVehicleInfo", "{}");

//4. Invokes the same service of multiple devices.

List deviceNamesService = new ArrayList<>(); deviceNamesService.add(deviceName);

InvokeThingsService(null, deviceProductkey, deviceNamesService, "ModifyVehicleInfo", "{}"); }

Debug the SDKs

After you configure the device SDK and server SDK, run these SDKs.

Check results: Check local logs.

Go to the IoT Platform console, click the name of the device to go the Device Details page. Click the Status tab to check the property values that the device reported last time.

> Document Version:20200922 164 Best Practices · Communications 物联网平台

Click the Events tab to check the events that the device reported last time. Click the Invoke Service tab to check the records of invoking services.

2.4. Communication between devices 2.4.1. M2M communication

Machine-to-Machine (M2M) is a kind of end-to-end communication. This section describes how to build an M2M communication architecture in IoT Platform by using the data forwarding feature of the rules engine or the topic-based message routing service. A connection between a smart lamp and a mobile app is used as an example.

IoT Platform handles communication requests between the device and the app, allowing you to focus on implementing your business system. This frees you from worries about technical issues such as guaranteeing a high level of stable communication in high-concurrency scenarios or maintaining expensive servers to handle requests.

For more information about the implementation process, see the following topics: Use the rules engine to establish M2M communication Use topic-based message routing to establish M2M communication 2.4.2. Use the rules engine to establish M2M communication

This topic describes how to use the data forwarding feature of the rules engine in IoT Platform to build an M2M communication architecture. A connection between a smart lamp and a mobile app is used as an example.

Context

The following figure shows the procedure to control the smart lamp through the mobile app.

165 > Document Version:20200922 物联网平台 Best Practices · Communications

Procedure

1. In the IoT Platform console, create a product and device for the smart lamp and define the features of the product. For more information, see Create a product, Create multiple devices at a time, and Add a TSL feature. In this example, the ProductKey and DeviceName parameters for the smart lamp are set to al123456789 and light respectively. 2. Develop a device SDK for the smart lamp. In this example, the device and IoT Platform use MQTT to communicate with each other.

The message payload is as the following.

{

"TargetDevice": "light",

"Switch": "off", "Timestamp": 1557750407000

}

3. In the IoT Platform console, register a product and device for the mobile app. In this example, the ProductKey and DeviceName parameters for the mobile app are set to al987654321 and ControlApp respectively. When a user registers the mobile app with your server, your server sends the device information to the mobile app. This way, the mobile app can connect to IoT Platform as a device. 4. Develop the mobile app. In this example, the mobile app and IoT Platform use HTTPS to communicate with each other. 5. Configure a data forwarding rule to forward commands from the mobile app to the topic of the smart lamp. i. Log on to the IoT Platform console. In the left-side navigation pane, click Rules > Data Forwarding, and create a rule.

> Document Version:20200922 166 Best Practices · Communications 物联网平台

ii. Write an SQL statement to process message contents to be forwarded. This SQL statement retrieves the messages to be sent from the mobile app to the smart lamp from the topic of the app device.

In this example, the SQL statement retrieves the deviceName, timestamp, and switch fields of the app device.

167 > Document Version:20200922 物联网平台 Best Practices · Communications

iii. Configure the destination to which you want to forward processed data. Subscribe the smart lamp to the device topic to receive commands from the app.

Note Select Publish to Another Topic.

When specifying a device, use ${TargetDevice} to match all target smart lamp devices. In this example, ${TargetDevice} is converted to the name of the smart lamp device. The name is light .

6. The user scans the QR code to bind the app to the smart lamp. After the app sends a request to the server to bind a device, the server binds the smart lamp and returns the device name. The returned name is specified by the deviceName parameter. In this example, the smart lamp device is named light. 7. The user sends control commands through the app.

i. The app sends commands to the topic in IoT Platform. In this example, the topic is /al98 7654321/ControlApp/user/command . Only JSON format commands are supported.

ii. IoT Platform then sends the commands to the topic of the smart lamp based on the data forwarding rule you defined. In this example, the topic defined is /al123456789/light/user /set .

iii. After receiving the commands, the smart lamp device performs the corresponding operations.

Note The app can also send a request to your server to unbind the smart lamp device. After the device is unbound, the app no longer controls the smart lamp.

> Document Version:20200922 168 Best Practices · Communications 物联网平台

2.4.3. Use topic-based message routing to establish M2M communication

This topic describes how to use the topic-based message routing service of IoT Platform to build an M2M communication architecture. A connection between a smart lamp and a mobile app is used as an example.

Context

The following figure shows the procedure to control the smart lamp through the mobile app.

Procedure

1. In the IoT Platform console, create a product and device for the smart lamp and define the features of the product. For more information, see Create a product, Create multiple devices at a time, and Add a TSL feature. In this example, the ProductKey and DeviceName parameters for the smart lamp are set to al123456789 and light respectively. 2. Develop a device SDK for the smart lamp. In this example, the device and IoT Platform use MQTT to communicate with each other.

The message payload is as the following.

{

"TargetDevice": "light",

"Switch": "off", "Timestamp": 1557750407000

}

3. In the IoT Platform console, register a product and device for the mobile app. In the preceding figure, the ProductKey and DeviceName parameters for the mobile app are set to al987654321 and ControlApp respectively. When a user registers the mobile app with your server, your server sends the device information to the mobile app. This way, the mobile app can connect to IoT Platform as a device.

169 > Document Version:20200922 物联网平台 Best Practices · Communications

4. Call the CreateTopicRouteTable operation to create a message routing relationship between the app topic and the smart lamp topic.

Set the SrcTopic parameter to the topic of the app: /al987654321/ControlApp/user/update .

Set the DstTopics parameter to the topic of the smart lamp: /al123456789/light/user/set .

5. Develop the mobile app. In this example, the mobile app and IoT Platform use HTTPS to communicate with each other. 6. The user scans the QR code to bind the app to the smart lamp. After the app sends a request to the server to bind a device, the server binds the smart lamp and returns the device name. The returned name is specified by the deviceName parameter. In this example, the smart lamp device is named light. 7. The user sends control commands through the app.

i. The topic to which the app sends commands is /al987654321/ControlApp/user/update . Only JSON format commands are supported.

ii. IoT Platform routes commands to the topic of the smart lamp device based on the defined message routing relationship. The topic is /al123456789/light/user/set .

iii. After receiving the commands, the smart lamp device performs the corresponding operations.

Note You can configure the app to notify your server to delete the message routing relationship and your server calls the DeleteTopicRouteTable operation to delete the message routing relationship. After the routing relationship is deleted, the app no longer controls the smart lamp.

2.5. Create a server-side subscription of the MNS type

This topic describes how to create a server-side subscription of the MNS type. The subscription allows messages about status changes on the devices of a product to be pushed to an MNS queue. Servers receive messages about status changes on devices by monitoring MNS queues.

Prerequisites

Activate the Alibaba Cloud Message Notification Service. Install Eclipse as Java development environment.

Context

The following figure shows data flows.

> Document Version:20200922 170 Best Practices · Communications 物联网平台

Create a server-side subscription

In the IoT Platform console, follow these steps to create a server-side subscription of the MNS type and select the types of messages to which you want to subscribe.

1. Log on to the IoT Platform console. 2. In the left-side navigation pane, choose Devices > Products. On the Products page, click Create Product to create a product. 3. Choose Devices > Create Device to add a device in the product.

When you use a server MNS SDK to provision a device, you must obtain the certificate information of the device.

4. In the left-side navigation pane, choose Rules > Server-side Subscription. On the Server-side Subscription page, click Create Subscription to create a server-side subscription of the MNS type.

Note The first time you select MNS in the Subscription Type field, a message prompts you to authorize access. Click Authorize Now to go to the Resource Access Management (RAM) console. Click Confirm Authorization Policy.

Select Device Status Change Notification. In the product, messages about status changes that occur on all devices will be pushed to an MNS queue.

After you create a server-side subscription, IoT Platform automatically creates a queue in MNS. The queue is used to receive messages from IoT Platform. The format of the queue name is aliyun-iot-${yourProductKey} . When you use an MNS SDK to monitor the messages of a queue, you must specify the name of the queue.

On the Server-side Subscription page, move the pointer over the icon next to MNS to view the name of a queue.

Use MNS SDK for Java to receive messages

This section uses the MNS Java SDK Demo project as an example.

171 > Document Version:20200922 物联网平台 Best Practices · Communications

1. Visit MNS SDK for Java. On the page that appears, click Download sample to download the ali yun-sdk-mns-samples1.1.8 package, and then decompress the package. 2. Open Eclipse, click Import Project, and select the aliyun-sdk-mns-samples directory to import. 3. In the C:\Users\${YourComputerUserName} local directory, create the .aliyun-mns .properties file. Add identity information in the following format to the file. The identity information is used by MNS for authentication.

mns.accountendpoint=http://$your_accountId.mns.$your_regionId.aliyuncs.com

mns.accesskeyid=$your_accesskeyid mns.accesskeysecret=$your_accesskeysecret

Parameter Description

The endpoint of Message Service. In the MNS console, select the region accountendpoint where the queue resides and click Get Endpoint to view the information.

The AccessKey ID of your Alibaba Cloud account.

To create or view your AccessKey pair, follows these steps: Log on to accesskeyid the Alibaba Cloud console. Move the pointer over your profile picture, and click AccessKey to go to the User Management page. On the page, you can create or view your AccessKey pairs.

The AccessKey secret of your Alibaba Cloud account. Obtain the accesskeysecret AccessKey secret in the same way as the AccessKey ID.

4. Add the following code to the ComsumerDemo script in the src\main\java\com.aliyun.mns.sa mple.Queue directory. The code is used to specify the name of the queue that is automatically created by IoT Platform.

> Document Version:20200922 172 Best Practices · Communications 物联网平台

public static void main(String[] args) {

CloudAccount account = new CloudAccount(

ServiceSettings.getMNSAccessKeyId(), ServiceSettings.getMNSAccessKeySecret());

ServiceSettings.getMNSAccountEndpoint()); MNSClient client = account.getMNSClient(); // Initialize a client

// Extract messages try{

CloudQueue queue = client.getQueueRef("aliyun-iot-a1eN7La****");//Specify the name of t

he queue that is automatically created by IoT Platform for (int i = 0; i < 10; i++)

{

Message popMsg = queue.popMessage(10); //The timeout for long polling if (popMsg ! = null){

System.out.println("message handle: " + popMsg.getReceiptHandle()); System.out.println("message body: " + popMsg.getMessageBodyAsString()); //Obtain

raw messages

System.out.println("message id: " + popMsg.getMessageId()); System.out.println("message dequeue count:" + popMsg.getDequeueCount());

//<>

//Delete the messages from the queue

queue.deleteMessage(popMsg.getReceiptHandle());

System.out.println("delete message successfully.\n"); }

} }

5. Run the ComsumerDemo script.

Configure a device SDK

1. Visit Download device SDKs and select Java SDK. 2. At the bottom of the Configure a project topic, click Java SDK Demo to download the package, and then decompress the package. 3. In a Java IDE, select the JavaLinkKitDemo directory to import as a project. 4. In the device_id file, add certificate information for the device.

173 > Document Version:20200922 物联网平台 Best Practices · Communications

5. In the MqttSample script of the src\devicesdk\demo directory, add information of the device, specify the name of your device topic in the publish method.

6. Run the MqttSample project to connect the device to IoT Platform.

Verify the results

After you run the device SDK Demo project, a message indicating that the device is online is sent to the MNS queue. The MNS Java SDK Demo project receives the message from the queue and then deletes the message from the queue. The following figure shows how the MNS Java SDK Demo project receives the message and then deletes the message.

> Document Version:20200922 174 Best Practices · Communications 物联网平台

2.6. Parse pass-through data from devices

Raw data from some devices that have limited resources and low specifications cannot be converted to Thing Specification Language (TSL) models in the JSON format. Therefore, these devices cannot communicate with IoT Platform. To fix the issue, you can pass through raw data from devices to IoT Platform. IoT Platform converts raw device data to Alink JSON data by using data parsing scripts that you submit. Then, you can perform subsequent operations on the converted data.

Context

The following figure shows how data flows between devices and enterprise servers.

Connect a device to IoT Platform

This article uses a device that collects environmental data as an example.

1. Log on to the IoT Platform console.

175 > Document Version:20200922 物联网平台 Best Practices · Communications

2. In the left-side navigation pane, choose Devices > Products. On the page that appears, click Create Product to create a product. Product information

Parameter Description

Product Name The name of the product.

[DO NOT TRANSLATE] [DO NOT TRANSLATE]

Node Type Select Directly Connected Device.

Network Connection Select Wi-Fi. Method

Data Type Select Custom.

Authentication Mode Select Device Secret.

3. After the product is created, click Create TSL. 4. Choose Edit Draft > Add Self-defined Feature to add the following properties.

5. Click Release Online to publish the TSL model. 6. In the left-side navigation pane, select Devices and click Add Device to add a device to the product. After the device is added, obtain certficate information of the device. The certificate includes the ProductKey, DeviceName, and DeviceSecret parameters. 7. Provision a device and perform a testThis article uses a device SDK to provision a device as an example. For more information about how to provision a device, see the Link SDK reference.

After the device is provisioned, create a TSL model for the device, and then run a test to implement data reporting.

After you connect the device to IoT Platform, the device is in the Online state. You can view the status on the Devices page.

Choose Maintenance > Device Log > Cloud run log, search for the device, and view the logs of the Device-to-cloud Messages. Click the MessageID of a message to view the details of the message that is reported from the device.

The contents of the message are displayed in the hexadecimal notation as follows: 0xaa1fc > Document Version:20200922 176 Best Practices · Communications 物联网平台

The contents of the message are displayed in the hexadecimal notation as follows: 0xaa1fc 800003710ff0005d76b15001c013400ad04ffff0400ffff18003000ff2e .

Create a data parsing script

In the IoT Platform console, edit and submit a data parsing script, and test data parsing. 1. In the left-side navigation pane, choose Devices > Products. 2. On the Product page, find the target product and click View. 3. On the Product Details page, click the Data Parsing tab. 4. On the Data Parsing tab, write a data parsing script in the Edit Script section.

Edit the data parsing script based on the communication protocol for the device that is used by the device. The following figure shows the packet format of the communication protocol.

Byte Description Note

12 Low byte of a PM2.5 value Return value: PM2.5. Range: 0~999ug/m3. 13 High byte of a PM2.5 value

Low byte of a temperature 14 value*10 Return value: temperature. Range: -10°C~50°C. High byte of a temperature 15 value*10

16 Low byte of a humidity value Return value: humidity. Range: 0~99%. 17 High byte of a humidity value

Low byte of a percentage of 18 carbon dioxide Return value: percentage of carbon dioxide. High byte of a percentage of 19 carbon dioxide

Low byte of a percentage of 22 formaldehyde*100 Return value: percentage of formaldehyde. Range: 0~9.99. High byte of a percentage of 23 formaldehyde*100

Low byte of an illuminance 28 value Return value: illuminance. Unit: lux. High byte of an illuminance 29 value

The device can only report data. Therefore, you must implement the rawDataToProtocol data parsing function for upstream data rather than implementing the protocolToRawData function.

The following code shows how to parse data.

177 > Document Version:20200922 物联网平台 Best Practices · Communications

var PROPERTY_REPORT_METHOD = 'thing.event.property.post';

//Upstream data. The following function converts data of a custom format to a TSL model in the JS

ON format.

function rawDataToProtocol(bytes) {

var uint8Array = new Uint8Array(bytes.length);

for (var i = 0; i < bytes.length; i++) { uint8Array[i] = bytes[i] & 0xff;

}

var dataView = new DataView(uint8Array.buffer, 0);

var jsonMap = new Object();

//Specify the request method. jsonMap['method'] = ALINK_PROP_REPORT_METHOD

//Specify the protocol version. Set the version to 1.0. Do not change the value.

jsonMap['version'] = '1.0' //Specify the ID of the request.

jsonMap['id'] = new Date().getTime();

var params = {}; //The 12 and 13 values are the values of the PM2.5 property.

params['pm25'] = (dataView.getUint8(13)*256+dataView.getUint8(12));

//The 14 and 15 values are the values of the temperature property. params['temperature'] = (dataView.getUint8(15)*256+dataView.getUint8(14))/10;

//The 16 and 17 values are the values of the humidity property. params['humidity'] = (dataView.getUint8(17)*256+dataView.getUint8(16));

//The 18 and 19 values are the values of the co2 property.

params['co2'] = (dataView.getUint8(19)*256+dataView.getUint8(18)); //The 22 and 23 values are the values of the hcho property.

params['hcho'] = (dataView.getUint8(23)*256+dataView.getUint8(22))/100;

//The 28 and 29 values are the values of the lightLux property. params['lightLux'] = (dataView.getUint8(29)*256+dataView.getUint8(28));

jsonMap['params'] = params;

return jsonMap; }

//Downstream commands. The following function converts a TSL model in the JSON format to data

of a custom format.

> Document Version:20200922 178 Best Practices · Communications 物联网平台

of a custom format. function protocolToRawData(json) {

var payloadArray = [1];//The device can only report data. The device cannot receive commands

from IoT Platform. return payloadArray;

}

//Transform data carried in custom topics to json data.

function transformPayload(topic, rawData) { var jsonObj = {}

return jsonObj;

}

5. Test data parsing. i. Select Upstreamed Device Data in the Simulation Type field. ii. In the text box on the Input Simulation tab, enter test data.After the test data is applied, you can view the following device data in the hexadecimal format on the Device Log page: 0xaa1fc800003710ff0005d76b15001c013400ad04ffff0400ffff18003000ff2e .

iii. Click Run.

The following figure shows the results on the Parsing Results tab.

6. Make sure that data is parsed by the script as expected. Click Submit to submit the script to IoT Platform.

After you submit the script, IoT Platform uses the script to parse subsequent upstream data. After upstream data is parsed, the data is displayed on the Status tab of the Device Details page.

179 > Document Version:20200922 物联网平台 Best Practices · Communications

> Document Version:20200922 180 Best Practices · Device management 物联网平台

3.Device management 3.1. Set desired property values to control the light bulb status

You can set a desired property value for a device on the cloud. IoT Platform caches the value and pushes the value to the device when it is online .

Background information

A light bulb does not have storage capability. If you want to control the light bulb from IoT Platform, the light bulb must stay online always. However, the light bulb is rarely online.

To resolve this issue, IoT Platform allows you to set desired property values.

When the light bulb is connected to IoT Platform, it reads the desired property value stored in IoT Platform. The device then updates the actual property based on the desired value and reports the updated property to IoT Platform. The reported property value will be stored as the latest property value.

Create a product and a device in the IoT Platform console

1. Log on to the IoT Platform console. 2. Create a product and define features for the product. 3. Register a device. 4. Go to the Device Details page of the device, and click the Status tab.

For a newly created device, the latest value and the desired value of a property are both "null", and the desired value version is 0.

5. Record the device certificate information, including ProductKey, DeviceName, and DeviceSecret, and the region information (RegionId).

Develop on the cloud

You call the related APIs to obtain the latest property values of a device and set desired property values to control the device.

For more information, see API reference (cloud). This example uses the Java SDK (cloud).

Call QueryDeviceDesiredProperty to query the desired property values of the device.

181 > Document Version:20200922 物联网平台 Best Practices · Device management

DefaultProfile profile = DefaultProfile.getProfile(

"", //Your region ID

"", //AccessKey ID of your Alibaba Cloud account ""); //AccessKey Secret of your Alibaba Cloud account

IAcsClient client = new DefaultAcsClient(profile);

//Set parameters to call the API

QueryDeviceDesiredPropertyRequest request = new QueryDeviceDesiredPropertyRequest(); request.setProductKey(productKey);

request.setDeviceName(deviceName);

//The list of property identifiers that you want to query If you do not specify the property identifier list, the desired values of all properties except the read-only properties will be queried.

request.setIdentifiers(Arrays.asList("LightStatus"));

//Initiate the request and handle the response or exception

QueryDeviceDesiredPropertyResponse response; try {

response = client.getAcsResponse(request);

QueryDeviceDesiredPropertyResponse.Data data = response.getData();

for (QueryDeviceDesiredPropertyResponse.Data.DesiredPropertyInfo propInfo :

data.getList()) { //Return the desired value and version of each property, such as property=LightStatus desired

=1 version=5

System.out.println("property=" + propInfo.getIdentifier()); System.out.println("desired=" + propInfo.getValue());

System.out.println("version=" + propInfo.getBizVersion()); }

} catch (ServerException e) {

e.printStackTrace(); } catch (ClientException e) {

e.printStackTrace();

}

Call SetDeviceDesiredProperty to set desired property values for a device.

> Document Version:20200922 182 Best Practices · Device management 物联网平台

DefaultProfile profile = DefaultProfile.getProfile(

"", //Your region ID

"", //AccessKey ID of your Alibaba Cloud account ""); //AccessKey Secret of your Alibaba Cloud account

IAcsClient client = new DefaultAcsClient(profile);

//Set parameters to call the API

SetDeviceDesiredPropertyRequest request = new SetDeviceDesiredPropertyRequest(); request.setProductKey(productKey);

request.setDeviceName(deviceName);

//The identifiers and values of the properties that you want to set. request.setItems("{\"LightStatus\": 1}");

//You can set the version of a desired property value if other RAM users also set desired values for

the property for distinguishment. Typically, you can choose not to specify the version. request.setVersions("{}");

//Initiate the request and handle the response or exception. SetDeviceDesiredPropertyResponse response;

try { response = client.getAcsResponse(request);

SetDeviceDesiredPropertyResponse.Data data = response.getData(); //If the operation is successful, the version of the desired property value is returned, such as {"Li

ghtStatus":5}

System.out.println(data.getVersions()); } catch (ServerException e) {

e.printStackTrace();

} catch (ClientException e) { e.printStackTrace();

}

Develop on the device

When the light bulb is connected to IoT Platform, it requests the desired property values from IoT Platform. If a desired property value changes while the light bulb is on, IoT Platform pushes the change in real time to the light bulb. For more information, see Developer Guide (Devices). This example uses the Java SDK.

The last section of this topic provides a complete set of device demo code for your reference.

1. Enter the device certificate and region information.

183 > Document Version:20200922 物联网平台 Best Practices · Device management

/**

* ProductKey, DeviceName, and DeviceSecret

*/ private static String productKey = "******";

private static String deviceName = "********";

private static String deviceSecret = "**************"; /**

* MQTT connection information

*/ private static String productKey = "******";

2. Add the following methods. These methods can be used to change the actual property value of the light bulb and automatically report the changes to IoT Platform. The latest property value in IoT Platform will be replaced.

/**

* When the device handles a property change, the methods will be called in the following scenari os:

* Scenario 1 Pull mode: After the device is connected to IoT Platform, the device automatically req

uests the latest desired property value from IoT Platform. * Scenario 2 Push mode: While the device is online, it receives the desired property value that IoT

Platform pushes to the topic property.set.

* @param identifier The property identifier * @param value The desired property value

* @param needReport Indicates whether to subscribe to the topic property.post to send the pro perty value to IoT Platform

* In scenario 2, the property report capability is already integrated into the processing function a

nd the needReport parameter will be set to "false". * @return

*/

private boolean handlePropertySet(String identifier, ValueWrapper value, boolean needReport) { ALog.d(TAG, "The device handled property changes= [" + identifier + "], value = [" + value + "]");

//Identify whether the property settings are successful according to the response. In this exam

ple, a success message is returned. boolean success = true;

if (needReport) { reportProperty(identifier, value);

}

return success; }

private void reportProperty(String identifier, ValueWrapper value){

> Document Version:20200922 184 Best Practices · Device management 物联网平台

if (StringUtils.isEmptyString(identifier) || value == null) {

return;

}

ALog.d(TAG, "Reported property identity=" + identifier);

Map reportData = new HashMap<>();

reportData.put(identifier, value); LinkKit.getInstance().getDeviceThing().thingPropertyPost(reportData, new IPublishResourceLis

tener() {

public void onSuccess(String s, Object o) {

//The property is reported

ALog.d(TAG, "Report success onSuccess() called with: s = [" + s + "], o = [" + o + "]"); }

public void onError(String s, AError aError) { //The property fails to be reported

ALog.d(TAG, "Report failure onError() called with: s = [" + s + "], aError = [" + JSON.toJSONStr ing(aError) + "]");

}

}); }

3. When the light bulb is online, if a desired property value is set for the light bulb in IoT Platform, the value will be pushed to the light bulb. The light bulb then processes the message and changes the status accordingly.

If the device is offline when the desired value is set, use the connectNotifyListener method to register a function to respond to service calls and property settings. For information about the Alink protocol, see Report device properties.

After the device receives an asynchronous message from IoT Platform, the device calls the mCommonHandler method and then the handlePropertySet method to update the property value.

/**

* Register a function to respond to service calls and property settings.

* When IoT Platform calls a service from the device, the device must respond to the call and retur n a response.

*/

public void connectNotifyListener() { List serviceList = LinkKit.getInstance().getDeviceThing().getServices();

for (int i = 0; serviceList ! = null && i < serviceList.size(); i++) {

185 > Document Version:20200922 物联网平台 Best Practices · Device management

Service service = serviceList.get(i);

LinkKit.getInstance().getDeviceThing().setServiceHandler(service.getIdentifier(), mCommonH

andler); }

}

private ITResRequestHandler mCommonHandler = new ITResRequestHandler() {

public void onProcess(String serviceIdentifier, Object result, ITResResponseCallback itResRespo

nseCallback) { ALog.d(TAG, "onProcess() called with: s = [" + serviceIdentifier + "]," +

" o = [" + result + "], itResResponseCallback = [" + itResResponseCallback + "]"); ALog.d(TAG, "Received an asynchronous service call from IoT Platform " + serviceIdentifier);

try {

if (SERVICE_SET.equals(serviceIdentifier)) { Map data = (Map)((InputParams)result).g

etData();

ALog.d(TAG, "Received asynchronous downstream data " + data); //Set the property value of the device and then report the property value to IoT Platform

.

boolean isSetPropertySuccess = handlePropertySet("LightStatus", data.get("LightStatus"), false);

if (isSetPropertySuccess) { if (result instanceof InputParams) {

//Return a response to IoT Platform

itResResponseCallback.onComplete(serviceIdentifier, null, null); } else {

itResResponseCallback.onComplete(serviceIdentifier, null, null);

} } else {

AError error = new AError();

error.setCode(100); error.setMsg("setPropertyFailed.");

itResResponseCallback.onComplete(serviceIdentifier, new ErrorInfo(error), null);

} } else if (SERVICE_GET.equals(serviceIdentifier)) {

} else { //The device operation varies by service.

ALog.d(TAG, "The returned values corresponding to the service.");

OutputParams outputParams = new OutputParams(); // outputParams.put("op", new ValueWrapper.IntValueWrapper(20));

itResResponseCallback.onComplete(serviceIdentifier, null, outputParams);

> Document Version:20200922 186 Best Practices · Device management 物联网平台

itResResponseCallback.onComplete(serviceIdentifier, null, outputParams);

} } catch (Exception e) {

e.printStackTrace();

ALog.d(TAG, "The data returned from IoT Platform is incorrectly formatted"); }

}

public void onSuccess(Object o, OutputParams outputParams) {

ALog.d(TAG, "onSuccess() called with: o = [" + o + "], outputParams = [" + outputParams + "]"); ALog.d(TAG, "The service has been registered");

}

public void onFail(Object o, ErrorInfo errorInfo) {

ALog.d(TAG, "onFail() called with: o = [" + o + "], errorInfo = [" + errorInfo + "]");

ALog.d(TAG, "Service registration failed."); }

};

4. When the light bulb is offline, if a desired property value is set for the light bulb in IoT Platform, this value will be stored in IoT Platform. After the light bulb comes online again, it will request for the desired property value from IoT Platform and call the handlePropertySet method to update the property value.

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

connectNotifyListener();

//Obtain the latest desired property value getDesiredProperty(deviceInfo, Arrays.asList("LightStatus"), new IConnectSendListener() {

public void onResponse(ARequest aRequest, AResponse aResponse) {

if(aRequest instanceof MqttPublishRequest && aResponse.data ! = null) { JSONObject jsonObject = JSONObject.parseObject(aResponse.data.toString());

ALog.i(TAG, "onResponse result=" + jsonObject);

JSONObject dataObj = jsonObject.getJSONObject("data"); if (dataObj ! = null) {

if (dataObj.getJSONObject("LightStatus") == null) {

//No desired value is set

187 > Document Version:20200922 物联网平台 Best Practices · Device management

//No desired value is set } else {

Integer value = dataObj.getJSONObject("LightStatus").getInteger("value"); handlePropertySet("LightStatus", new ValueWrapper.IntValueWrapper(value), tru

e);

} }

}

} public void onFailure(ARequest aRequest, AError aError) {

ALog.d(TAG, "onFailure() called with: aRequest = [" + aRequest + "], aError = [" + aError +

"]"); }

});

} });

private void getDesiredProperty(BaseInfo info, List properties, IConnectSendListener list

ener) {

ALog.d(TAG, "getDesiredProperty() called with: info = [" + info + "], listener = [" + listener + "]"); if(info ! = null && ! StringUtils.isEmptyString(info.productKey) && ! StringUtils.isEmptyString(inf

o.deviceName)) {

MqttPublishRequest request = new MqttPublishRequest(); request.topic = DESIRED_PROPERTY_GET.replace("{productKey}", info.productKey).replace("{de

viceName}", info.deviceName);

request.replyTopic = DESIRED_PROPERTY_GET_REPLY.replace("{productKey}", info.productKey) .replace("{deviceName}", info.deviceName);

request.isRPC = true; RequestModel> model = new RequestModel<>();

model.id = String.valueOf(IDGeneraterUtils.getId());

model.method = METHOD_GET_DESIRED_PROPERTY; model.params = properties;

model.version = "1.0";

request.payloadObj = model.toString(); ALog.d(TAG, "getDesiredProperty: payloadObj=" + request.payloadObj);

ConnectSDK.getInstance().send(request, listener);

} else { ALog.w(TAG, "getDesiredProperty failed, baseInfo Empty.");

if(listener ! = null) { AError error = new AError();

error.setMsg("BaseInfoEmpty.");

> Document Version:20200922 188 Best Practices · Device management 物联网平台

listener.onFailure(null, error); }

}

}

Verify the configuration

Verify that you can change the light bulb status by setting the desired value in IoT Platform regardless of whether the light bulb is online or not. When the light bulb is online, you change the light bulb status in IoT Platform and the light bulb responds to the change in real time.

When the light bulb is offline, you change the light bulb status in IoT Platform. As a result, the desired value and the latest property value displayed in IoT Platform console are different.

After the light bulb comes online again, the light bulb requests the desired property value. The latest property value will be immediately synchronized from the desired value.

189 > Document Version:20200922 物联网平台 Best Practices · Device management

Conslusion: To change the light bulb status, you can simply modify the desired property value. You can use the desired value to control the status of the light bulb that has no storage capability.

SDK demo code

package com.aliyun.alink.devicesdk.demo;

import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.JSONObject; import com.aliyun.alink.apiclient.utils.StringUtils;

import com.aliyun.alink.dm.api.BaseInfo; import com.aliyun.alink.dm.api.DeviceInfo;

import com.aliyun.alink.dm.api.InitResult;

import com.aliyun.alink.dm.model.RequestModel; import com.aliyun.alink.dm.utils.IDGeneraterUtils;

import com.aliyun.alink.linkkit.api.ILinkKitConnectListener;

import com.aliyun.alink.linkkit.api.IoTMqttClientConfig; import com.aliyun.alink.linkkit.api.LinkKit;

import com.aliyun.alink.linkkit.api.LinkKitInitParams;

import com.aliyun.alink.linksdk.cmp.api.ConnectSDK; import com.aliyun.alink.linksdk.cmp.connect.channel.MqttPublishRequest;

import com.aliyun.alink.linksdk.cmp.core.base.ARequest; import com.aliyun.alink.linksdk.cmp.core.base.AResponse;

import com.aliyun.alink.linksdk.cmp.core.listener.IConnectSendListener;

import com.aliyun.alink.linksdk.tmp.api.InputParams; import com.aliyun.alink.linksdk.tmp.api.OutputParams;

import com.aliyun.alink.linksdk.tmp.device.payload.ValueWrapper;

import com.aliyun.alink.linksdk.tmp.devicemodel.Service; import com.aliyun.alink.linksdk.tmp.listener.IPublishResourceListener;

import com.aliyun.alink.linksdk.tmp.listener.ITResRequestHandler;

import com.aliyun.alink.linksdk.tmp.listener.ITResResponseCallback; import com.aliyun.alink.linksdk.tmp.utils.ErrorInfo;

> Document Version:20200922 190 Best Practices · Device management 物联网平台

import com.aliyun.alink.linksdk.tmp.utils.ErrorInfo;

import com.aliyun.alink.linksdk.tools.AError;

import com.aliyun.alink.linksdk.tools.ALog;

import java.util.Arrays; import java.util.HashMap;

import java.util.List;

import java.util.Map;

public class LampDemo {

private static final String TAG = "LampDemo";

private final static String SERVICE_SET = "set";

private final static String SERVICE_GET = "get";

public static String DESIRED_PROPERTY_GET = "/sys/{productKey}/{deviceName}/thing/property/desi red/get";

public static String DESIRED_PROPERTY_GET_REPLY = "/sys/{productKey}/{deviceName}/thing/proper

ty/desired/get_reply"; public static String METHOD_GET_DESIRED_PROPERTY = "thing.property.desired.get";

public static void main(String[] args) { /**

* ProductKey, DeviceName, and DeviceSecret

*/ String productKey = "****";

String deviceName = "Lamp"; String deviceSecret = "****";

/**

* MQTT connection information */

String regionId = "cn-shanghai";

LampDemo manager = new LampDemo();

DeviceInfo deviceInfo = new DeviceInfo(); deviceInfo.productKey = productKey;

deviceInfo.deviceName = deviceName;

deviceInfo.deviceSecret = deviceSecret;

manager.init(deviceInfo, regionId);

191 > Document Version:20200922 物联网平台 Best Practices · Device management

}

public void init(final DeviceInfo deviceInfo, String region) { LinkKitInitParams params = new LinkKitInitParams();

/**

* Set the MQTT initialization parameters */

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";

/**

* Indicates whether to receive offline messages * The cleanSession field corresponding to the MQTT connection

*/

config.receiveOfflineMsg = false; params.mqttClientConfig = config;

/** * Pass in the device certificate information for initialization

*/ params.deviceInfo = deviceInfo;

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

connectNotifyListener();

//Obtain the latest desired property value from IoT Platform getDesiredProperty(deviceInfo, Arrays.asList("LightStatus"), new IConnectSendListener() {

public void onResponse(ARequest aRequest, AResponse aResponse) { if(aRequest instanceof MqttPublishRequest && aResponse.data ! = null) {

JSONObject jsonObject = JSONObject.parseObject(aResponse.data.toString());

ALog.i(TAG, "onResponse result=" + jsonObject); JSONObject dataObj = jsonObject.getJSONObject("data");

if (dataObj ! = null) {

> Document Version:20200922 192 Best Practices · Device management 物联网平台

if (dataObj ! = null) {

if (dataObj.getJSONObject("LightStatus") == null) { //No desired value is set

} else {

Integer value = dataObj.getJSONObject("LightStatus").getInteger("value"); handlePropertySet("LightStatus", new ValueWrapper.IntValueWrapper(value), tru

e); }

}

} }

public void onFailure(ARequest aRequest, AError aError) {

ALog.d(TAG, "onFailure() called with: aRequest = [" + aRequest + "], aError = [" + aError + "]");

}

}); }

}); }

/** * When the device handles a property change, the methods will be called in the following scenarios:

* Scenario 1. Pull mode: After the device is connected to IoT Platform again, the device automaticall

y requests the latest desired property value from IoT Platform. * Scenario 2. Push mode: While the device is online, it receives the desired property value that IoT P

latform pushes to the property.set topic.

* @param identifier The property identifier * @param value The desired property value

* @param needReport Indicates whether to subscribe to the property.post topic to send the proper

ty value to IoT Platform * In scenario 2, the property report capability is already integrated into the processing function and

the needReport parameter will be set to "false". * @return

*/

private boolean handlePropertySet(String identifier, ValueWrapper value, boolean needReport) { ALog.d(TAG, "The device handled property changes= [" + identifier + "], value = [" + value + "]");

//Identify whether the property settings are successful according to the response. In this exampl

e, a success message is returned. boolean success = true;

if (needReport) {

reportProperty(identifier, value); }

193 > Document Version:20200922 物联网平台 Best Practices · Device management

}

return success; }

private void reportProperty(String identifier, ValueWrapper value){ if (StringUtils.isEmptyString(identifier) || value == null) {

return;

}

ALog.d(TAG, "Reported property identity=" + identifier);

Map reportData = new HashMap<>();

reportData.put(identifier, value); LinkKit.getInstance().getDeviceThing().thingPropertyPost(reportData, new IPublishResourceListe

ner() {

public void onSuccess(String s, Object o) {

//The property is reported

ALog.d(TAG, "Report success onSuccess() called with: s = [" + s + "], o = [" + o + "]"); }

public void onError(String s, AError aError) { //The property fails to be reported

ALog.d(TAG, "Report failure onError() called with: s = [" + s + "], aError = [" + JSON.toJSONStrin

g(aError) + "]"); }

}); }

/** * Register a function to respond to service calls and property settings.

* When IoT Platform calls a service from the device, the device must respond to the call and return a

response. */

public void connectNotifyListener() {

List serviceList = LinkKit.getInstance().getDeviceThing().getServices(); for (int i = 0; serviceList ! = null && i < serviceList.size(); i++) {

Service service = serviceList.get(i); LinkKit.getInstance().getDeviceThing().setServiceHandler(service.getIdentifier(), mCommonHan

dler);

}

> Document Version:20200922 194 Best Practices · Device management 物联网平台

}

private ITResRequestHandler mCommonHandler = new ITResRequestHandler() { public void onProcess(String serviceIdentifier, Object result, ITResResponseCallback itResRespons

eCallback) {

ALog.d(TAG, "onProcess() called with: s = [" + serviceIdentifier + "]," + " o = [" + result + "], itResResponseCallback = [" + itResResponseCallback + "]");

ALog.d(TAG, "Received an asynchronous service call from IoT Platform " + serviceIdentifier); try {

if (SERVICE_SET.equals(serviceIdentifier)) {

Map data = (Map)((InputParams)result).get Data();

ALog.d(TAG, "Received asynchronous downstream data " + data);

//Set the property of the device and then report the property value to IoT Platform. boolean isSetPropertySuccess =

handlePropertySet("LightStatus", data.get("LightStatus"), false);

if (isSetPropertySuccess) { if (result instanceof InputParams) {

//Return a response to IoT Platform

itResResponseCallback.onComplete(serviceIdentifier, null, null); } else {

itResResponseCallback.onComplete(serviceIdentifier, null, null); }

} else {

AError error = new AError(); error.setCode(100);

error.setMsg("setPropertyFailed.");

itResResponseCallback.onComplete(serviceIdentifier, new ErrorInfo(error), null); }

} else if (SERVICE_GET.equals(serviceIdentifier)) {

} else { //The device operation varies by service.

ALog.d(TAG, "The returned values corresponding to the service."); OutputParams outputParams = new OutputParams();

// outputParams.put("op", new ValueWrapper.IntValueWrapper(20));

itResResponseCallback.onComplete(serviceIdentifier, null, outputParams); }

} catch (Exception e) {

e.printStackTrace(); ALog.d(TAG, "The data returned from IoT Platform is incorrectly formatted");

}

195 > Document Version:20200922 物联网平台 Best Practices · Device management

}

}

public void onSuccess(Object o, OutputParams outputParams) { ALog.d(TAG, "onSuccess() called with: o = [" + o + "], outputParams = [" + outputParams + "]");

ALog.d(TAG, "The service was registered");

}

public void onFail(Object o, ErrorInfo errorInfo) {

ALog.d(TAG, "onFail() called with: o = [" + o + "], errorInfo = [" + errorInfo + "]"); ALog.d(TAG, "Service registration failed.");

}

};

private void getDesiredProperty(BaseInfo info, List properties, IConnectSendListener listen

er) { ALog.d(TAG, "getDesiredProperty() called with: info = [" + info + "], listener = [" + listener + "]");

if(info ! = null && ! StringUtils.isEmptyString(info.productKey) && ! StringUtils.isEmptyString(info.d eviceName)) {

MqttPublishRequest request = new MqttPublishRequest();

request.topic = DESIRED_PROPERTY_GET.replace("{productKey}", info.productKey).replace("{devi ceName}", info.deviceName);

request.replyTopic = DESIRED_PROPERTY_GET_REPLY.replace("{productKey}", info.productKey).r

eplace("{deviceName}", info.deviceName); request.isRPC = true;

RequestModel> model = new RequestModel<>();

model.id = String.valueOf(IDGeneraterUtils.getId()); model.method = METHOD_GET_DESIRED_PROPERTY;

model.params = properties; model.version = "1.0";

request.payloadObj = model.toString();

ALog.d(TAG, "getDesiredProperty: payloadObj=" + request.payloadObj); ConnectSDK.getInstance().send(request, listener);

} else {

ALog.w(TAG, "getDesiredProperty failed, baseInfo Empty."); if(listener ! = null) {

AError error = new AError();

error.setMsg("BaseInfoEmpty."); listener.onFailure(null, error);

}

} }

> Document Version:20200922 196 Best Practices · Device management 物联网平台

}

}

3.2. Call a synchronous service

To meet the requirements for managing devices and obtaining responses from the devices, IoT Platform provides synchronous services. This topic describes how to call a synchronous service.

Context

A server calls an IoT Platform API operation to invoke a synchronous service. IoT Platform sends a request to a device. Then, the device responds to the request within a certain period of time and returns the results to IoT Platform. Servers use synchronous services to manage devices and obtain results from devices. IoT Platform calls synchronous services by using Revert-RPC (RRPC). For more information, see Invoke device services in an asynchronous manner.

Precautions

Before you can call a synchronous service, make sure that the device that the synchronous service manages is in the online state. After IoT Platform calls a synchronous service, the maximum timeout period for IoT Platform to wait before a response is received is 8 seconds. If no response is received within 8 seconds, a timeout error occurs.

Step 1: Create a custom service

1. Log on to the IoT Platform console by using an Alibaba Cloud account. 2. In the left-side navigation pane, choose Devices > Products, find the target product, and click View next to the product. 3. On the Product Details page, click the Define Feature tab, and add a self-defined feature as shown in the following figure.

197 > Document Version:20200922 物联网平台 Best Practices · Device management

For more information about the required parameters that you need to specify for a custom service, see Add a TSL feature.

4. The following figure shows how to add input parameters and output parameters.

Input parameters

> Document Version:20200922 198 Best Practices · Device management 物联网平台

Output parameters

199 > Document Version:20200922 物联网平台 Best Practices · Device management

Step 2: Create a device SDK-based application

1. Add the following dependencies to the pom.xml file.

> Document Version:20200922 200 Best Practices · Device management 物联网平台

com.aliyun.alink.linksdk iot-linkkit-java

1.2.0.1 compile

com.google.code.gson gson

2.8.1 compile

com.alibaba fastjson 1.2.40

compile

com.google.guava guava 23.0

2. Add Java classes and specify the information of your device in the Config. * file.

/* * Copyright © 2019 Alibaba. All rights reserved. */

package com.aliyun.iot.demo.alink;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSONObject; import com.aliyun.alink.dm.api.DeviceInfo;

import com.aliyun.alink.dm.api.InitResult; import com.aliyun.alink.linkkit.api.ILinkKitConnectListener; import com.aliyun.alink.linkkit.api.IoTMqttClientConfig;

import com.aliyun.alink.linkkit.api.LinkKit;

201 > Document Version:20200922 物联网平台 Best Practices · Device management

import com.aliyun.alink.linkkit.api.LinkKit; import com.aliyun.alink.linkkit.api.LinkKitInitParams; import com.aliyun.alink.linksdk.cmp.connect.channel.MqttPublishRequest;

import com.aliyun.alink.linksdk.cmp.core.base.AMessage; import com.aliyun.alink.linksdk.cmp.core.base.ARequest; import com.aliyun.alink.linksdk.cmp.core.base.AResponse;

import com.aliyun.alink.linksdk.cmp.core.base.AMessage; import com.aliyun.alink.linksdk.cmp.core.listener.IConnectNotifyListener; import com.aliyun.alink.linksdk.cmp.core.listener.IConnectSendListener;

import com.aliyun.alink.linksdk.tools.AError; import com.google.common.util.concurrent.ThreadFactoryBuilder;

/**

* Call a synchronous service. */ public class SyncServiceProcessor {

// ======The start of the section where you can specify the required parameter s======

// Specify the information of your device in the Config. * file. // The ID of the region. private static String regionId = "cn-shanghai";

// The productKey specifies the key of a product. private static String productKey = "Config.productKey"; // The deviceName specifies the name of a device.

private static String deviceName = "Config.deviceName"; // The deviceSecret specifies the key of the device. private static String deviceSecret = "Config.deviceSecret";

// ======The end of the section where you can specify the required parameters ======

private static ExecutorService executorService = new ThreadPoolExecutor(Runtime.getRuntime(). availableProcessors(), Runtime.getRuntime().availableProcessors() * 2, 60, TimeUnit.SECONDS, new LinkedBlockingQu eue<>(100),

new ThreadFactoryBuilder().setDaemon(true).setNameFormat("http2-downlink-handle-%d").b uild(), new ThreadPoolExecutor.AbortPolicy());

/** * 1 Start the application to simulate an online device.

> Document Version:20200922 202 Best Practices · Device management 物联网平台

* 2 Initialize an InvokeSyncService object to call a synchronous service.
* * @param args

* @throws InterruptedException */ public static void main(String[] args) throws InterruptedException {

// Listen for downstream data. registerNotifyListener();

// Connect the device to IoT Platform. connect(productKey, deviceName, deviceSecret);

}

/**

* Establish a connection. * * @param productKey The key of the product. * @param deviceName The name of the device.

* @param deviceSecret The key of the device. * @throws InterruptedException */

private static void connect(String productKey, String deviceName, String deviceSecret) throws In terruptedException {

// Initialize parameters. LinkKitInitParams params = new LinkKitInitParams();

// Specify MQTT-related initialization parameters. IoTMqttClientConfig config = new IoTMqttClientConfig(); config.channelHost = productKey + ".iot-as-mqtt." + regionId + ".aliyuncs.com:1883";

config.productKey = productKey; config.deviceName = deviceName; config.deviceSecret = deviceSecret;

params.mqttClientConfig = config;

// Specify the certificate information of the device.

DeviceInfo deviceInfo = new DeviceInfo(); deviceInfo.productKey = productKey; deviceInfo.deviceName = deviceName;

deviceInfo.deviceSecret = deviceSecret;

203 > Document Version:20200922 物联网平台 Best Practices · Device management

deviceInfo.deviceSecret = deviceSecret; params.deviceInfo = deviceInfo;

// Initialize the device.

LinkKit.getInstance().init(params, new ILinkKitConnectListener() { public void onError(AError aError) { System.out.println("init failed !! code=" + aError.getCode() + ",msg=" + aError.getMsg() + ",su

bCode=" + aError.getSubCode() + ",subMsg=" + aError.getSubMsg()); }

public void onInitDone(InitResult initResult) { System.out.println("upload success!") ;

} });

// Before you proceed to the following steps, make sure the initialization is complete. You can s pecify a custom value based on your business requirement. Thread.sleep(2000);

}

/**

* Send messages. * @param topic The topic to which messages are sent. * @param payload The contents of messages.

*/ private static void publish(String topic, String payload) { MqttPublishRequest request = new MqttPublishRequest();

request.topic = topic; request.payloadObj = payload; request.qos = 0;

LinkKit.getInstance().getMqttClient().publish(request, new IConnectSendListener() { @Override public void onResponse(ARequest aRequest, AResponse aResponse) {

}

@Override

public void onFailure(ARequest aRequest, AError aError) { } });

}

> Document Version:20200922 204 Best Practices · Device management 物联网平台

}

/**

* Listen for downstream data. */ private static void registerNotifyListener() {

LinkKit.getInstance().registerOnNotifyListener(new IConnectNotifyListener() { @Override public boolean shouldHandle(String connectId, String topic) { return true;

}

@Override

public void onNotify(String connectId, String topic, AMessage aMessage) { // Accept the call from the synchronous service and response to the service. // Create a new thread to avoid callback blocks.

executorService.submit(() -> doService(topic, aMessage)); }

@Override public void onConnectStateChange(String s, ConnectState connectState) { }

}); }

/** * Process the request that is used to call the synchronous service. *

* @param topic The topic of the request. * @param aMessage The contents of the request. */

private static void doService(String topic, AMessage aMessage) {

String content = new String((byte[]) aMessage.getData()); System.out.println("Service Request Topic:" + topic);

System.out.println("Service Request:" + content);

/**

* The aMessage parameter includes a JSON text. * { * "id": "123",

205 > Document Version:20200922 物联网平台 Best Practices · Device management

* "version": "1.0", * "params": // The required parameters for the synchronous service. These parameters chan ge based on the definition of the synchronous service.

* { * "input": 50 * },

* "method": "thing.service.{tsl.service.identifier}" * } */

JSONObject request = JSONObject.parseObject(content); JSONObject params = request.getJSONObject("params"); if (! params.containsKey("input")) { // Validate the request parameters.

return; } Integer input = params.getInteger("input"); // Obtain the request parameters.

/** * The response from the synchronous service includes a JSON text. * {

* "id": "123", // The ID of the request. * "code": 200, // The value 200 indicates a successful call. * "data": {} // The response from the synchronous service. The response changes based on

the definition of the synchronous service. * } */

JSONObject response = new JSONObject(); JSONObject data = new JSONObject(); data.put("output", input + 1);

response.put("id", request.get("id")); response.put("code", 200); response.put("data", data);

// The response from the synchonous service. String respTopic = topic.replace("/request/", "/response/");

publish(respTopic, response.toString()); System.out.println("Service Response Topic:" + respTopic); System.out.println("Service Response Contents" + response.toString());

} }

> Document Version:20200922 206 Best Practices · Device management 物联网平台

Step 3: Create a service SDK-based application

1. Add the following dependencies to the pom.xml file.

com.aliyun

aliyun-java-sdk-iot 7.0.0

com.aliyun aliyun-java-sdk-core 3.5.1

com.alibaba

fastjson 1.2.40

2. Add the following Java classes and specify the information of your device in the Config. * file.

/* * Copyright © 2019 Alibaba. All rights reserved. */ package com.aliyun.iot.demo.alink;

import com.alibaba.fastjson.JSONObject; import com.aliyuncs.DefaultAcsClient;

import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.exceptions.ServerException; import com.aliyuncs.iot.model.v20180120.InvokeThingServiceRequest;

import com.aliyuncs.iot.model.v20180120.InvokeThingServiceResponse; import com.aliyuncs.profile.DefaultProfile; import com.aliyuncs.profile.IClientProfile;

/** * Call a synchronous service.

*/ public class InvokeSyncService {

======The start of the section where you can specify the required parameters======

207 > Document Version:20200922 物联网平台 Best Practices · Device management

// Specify the information of your device in the Config. * file.

// The ID of the region. private static String regionId = "cn-shanghai"; // The AccessKey ID of your Alibaba Cloud account. private static String accessKeyID = "Config.accessKey";

// The AccesseKey secret of your Alibaba Cloud account. private static String accessKeySecret = "Config.accessKeySecret"; // productKey. The key of a product.

private static String productKey = "Config.productKey"; // deviceName. The name of a device. private static String deviceName = "Config.deviceName";

======The end of the section where you need to specify the required parameters======

/** * 1. Initialize the SyncServiceProcessor class to simulate an online device.
* 2. Start the application to call a synchronous service.

* * @param args * @throws ServerException

* @throws ClientException */ public static void main(String[] args) throws ServerException, ClientException {

// Obtain exceptions from a client. DefaultAcsClient client = null;

try { IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyID, accessKeySecret); DefaultProfile.addEndpoint(regionId, regionId, "Iot", "iot." + regionId + ".aliyuncs.com"); client = new DefaultAcsClient(profile);

} catch (Exception e) { System.out.println("create Open API Client failed !! exception:" + e.getMessage()); }

// Specify the required parameters. InvokeThingServiceRequest request = new InvokeThingServiceRequest();

request.setProductKey(productKey); // The productKey specifies the key of the product. request.setDeviceName(deviceName); // The deviceName specifies the name of the device. request.setIdentifier("MySyncService"); // The identifier of the synchronous service that you w

ant to call. The identifier changes based on the definition of the synchronous service. JSONObject json = new JSONObject(); // Create a request parameter. The request parameter inc

> Document Version:20200922 208 Best Practices · Device management 物联网平台

JSONObject json = new JSONObject(); // Create a request parameter. The request parameter inc ludes a JSON string.

json.put("input", 50); // You can specify a custom value based on the definition of the synchron ous service. request.setArgs(json.toString());

// Obtain a response from the synchronous service. InvokeThingServiceResponse response = client.getAcsResponse(request);

if (response == null) { System.out.println("Failed to call the synchronous service"); return;

} System.out.println("requestId:" + response.getRequestId()); System.out.println("code:" + response.getCode()); System.out.println("success:" + response.getSuccess());

System.out.println("error message:" + response.getErrorMessage()); if (response ! = null && response.getSuccess()) { // The synchronous service is called successfu lly. The return value true indicates that a request is sent to the synchronous service rather than t

hat the synchronous service is run successfully. System.out.println("The synchronous service is called"); System.out.println("Message ID:" + response.getData().getMessageId());

System.out.println("Results" + response.getData().getResult()); // If the synchronous service i s called successfully, results are returned. } else {

System.out.println("Failed to call the synchronous service"); } }

}

3.3. Connect a sub-device to IoT Platform

209 > Document Version:20200922 物联网平台 Best Practices · Data forwarding

4.Data forwarding 4.1. Integrate with a weather service

Context

The user specifies a city name, city code, or the latitude and longitude of a city. IoT Platform uses the rules engine to pass the request to Function Compute for further processing. Function Compute then queries the weather service and retrieves the weather data for the specified city. The query results are eventually sent to the specified topic.

In this example, one topic performs weather queries, and the other receives query results. This example uses Function Compute to access third-party services in Alibaba Cloud API Marketplace.

Procedure

1. Define the function.

Business logic:

Performs weather queries based on city information. An API is used to query weather information. The query results are sent to the specified topic of the device using the service API provided by IoT Platform.

Create a new project and import the following JAR files:

> Document Version:20200922 210 Best Practices · Data forwarding 物联网平台

com.aliyun.fc.runtime

fc-java-core 1.0.0

com.aliyun aliyun-java-sdk-core 3.2.10

com.aliyun

aliyun-java-sdk-iot 4.0.0

com.alibaba fastjson

1.2.25

org.apache.httpcomponents httpclient 4.2.1

org.apache.httpcomponents

httpcore 4.2.1

commons-lang commons-lang 2.6

Code logic:

public class FcToApiDemo implements PojoRequestHandler { private static String host = "http://jisutqybmf.market.alicloudapi.com"; private static String path = "/weather/query"; private static String method = "GET";

private static String appcode = "Your appCode";

211 > Document Version:20200922 物联网平台 Best Practices · Data forwarding

private static String appcode = "Your appCode"; private static String accessKey = "Your Alibaba Cloud Access Key ID"; private static String accessSecret = "Your Alibaba Cloud Access Key Secret";

static DefaultAcsClient client; static { IClientProfile profile = DefaultProfile.getProfile("cn-shanghai", accessKey, accessSecret);

try { DefaultProfile.addEndpoint("cn-shanghai", "cn-shanghai", "Iot", "iot.cn-shanghai.aliyuncs.com"); } catch (ClientException e) {

e.printStackTrace(); } client = new DefaultAcsClient(profile); // Initialize a client object.

} public String handleRequest(CityModel input, Context context) { Map headers = new HashMap();

// The format of the header is as follows (include a space in the middle): Authorization:APPCO DE // 83359fd73fe94948385f570e3c139105

headers.put("Authorization", "APPCODE " + appcode); Map querys = new HashMap(); querys.put("city", input.getCity());

querys.put("citycode", input.getCityCode()); querys.put("cityid", input.getCityid()); querys.put("ip", input.getIp()); querys.put("location", input.getLocation());

try { /** * Note: Download HttpUtils from the following address:

* https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliy un/api/gateway/demo/util/HttpUtils.java *

* * For more information about the dependencies, see: * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml

*/ HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys); // Send the query results to the specified topic.

Boolean result = pub(EntityUtils.toString(response.getEntity())); return result.toString(); } catch (Exception e) {

e.printStackTrace();

> Document Version:20200922 212 Best Practices · Data forwarding 物联网平台

} return "error";

} public static Boolean pub(String msg) { try { PubRequest request = new PubRequest();

request.setProductKey("The productKey of your product"); request.setTopicFullName("The topic for receiving weather query results"); request.setMessageContent(Base64.encodeBase64String(msg.getBytes()));

request.setQos(1); PubResponse response = client.getAcsResponse(request); return response.getSuccess();

} catch (ServerException e) { e.printStackTrace(); } catch (ClientException e) {

e.printStackTrace(); } return false;

} }

The custom model is as shown in the following picture.

The function implements the PojoRequestHandler interface that is provided by Function Compute. Function Compute also provides the StreamRequestHandler interface. Select an interface based on your needs.

2. Configure the function i. Log on to the Function Compute console.

213 > Document Version:20200922 物联网平台 Best Practices · Data forwarding

ii. Click Create Function, select No Trigger, and configure the basic information, as shown in the following picture.

iii. Click Next, Create. iv. After the configuration is complete, test the function to see whether the function runs properly. The function runs properly if the code logic is correct.

3. Log on to the IoT Platform console, create a product and a device, and define topics. i. Log on to the IoT Platform console. ii. Select Products, and click Create Product to create an IoT Platform product. In this example, the product is named weatherProduct. iii. Select Devices, select weatherProduct, and then click Add Device to specify the device name. iv. Select Products, and click View next to weather Product. v. Select Topic Categories > Custom Topics > Define Topic Category, and define the topics for performing weather queries and receiving query results, as shown in Define topics.

Define topics

vi. Select Rules > Data Forwarding, and click Create Rule to create a new JSON rule.

> Document Version:20200922 214 Best Practices · Data forwarding 物联网平台

vii. Click Write SQL and write the SQL, as shown in Rules engine.

Rules engine

viii. Click Add Operation and configure the rule to forward data to the function. ix. On the Data Forwarding page, click Start corresponding to the rule to start the rule. 4. Test the functionality of weather query. Log on to your emulated device and subscribe to the specified topic.

215 > Document Version:20200922 物联网平台 Best Practices · Data forwarding

Send a message from the console.

You can also use cityid, cityCode, location, or IP information to query weather information.

The device receives the message.

> Document Version:20200922 216 Best Practices · Data forwarding 物联网平台

4.2. Upload temperature and humidity data to DingTalk chatbots

Context

Scenario:

Upload the data that is collected by the temperature and humidity sensor to DingTalk chatbots.

Business logic:

Connect the temperature and humidity sensor to IoT Platform through MQTT. Configure the rules engine to send the temperature and humidity data to the pushData2DingTalk function in Function Compute. The function processes the data and posts the results to the Webhook address of the specified DingTalk chatbot. The DingTalk group can then receive the temperature and humidity data sent by this DingTalk chatbot.

The data flow diagram is shown in Data flow diagram.

Data flow diagram

217 > Document Version:20200922 物联网平台 Best Practices · Data forwarding

Procedure

1. Configure the DingTalk chatbot. i. Log on to the desktop version of DingTalk.

ii. In the upper-right corner of the DingTalk group page, click ... , and then select ChatBot.

iii. Click Add Robot, select Custom, then click Add. iv. Enter a name for the robot, click Next, and then click Finish. 2. Create a function. i. Activate Alibaba Cloud Function Compute service first.

Function Compute is an event-driven, fully managed computing service. Currently supported languages include Java, Node.js and Python. For more information, see How to use Function Compute.

ii. Write the function script code. In this example, Node.js is used. The function obtains the device location, device number, temperature, humidity, and the time of recording from IoT Platform, and splices the data according to the specified DingTalk message format. Data will be sent to the Webhook address of the specified DingTalk chatbot using HTTPS Post methods. iii. Log on to the Function Compute console and create a service named IoT_Service. iv. Click Create Function, and select the Empty Function template. v. Select No Trigger and specify the basic configurations as shown in the following picture.

Basic configurations

The function pushData2DingTalk is declared as follows:

const https = require('https');

> Document Version:20200922 218 Best Practices · Data forwarding 物联网平台

const https = require('https'); const accessToken = 'Specify the webhook accessToken of the DingTalk robot'; module.exports.handler = function(event, context, callback) {

var eventJson = JSON.parse(event.toString()); //DingTalk message format const postData = JSON.stringify({

"msgtype": "markdown", "markdown": { "title": "Temperature and humidity sensor",

"text": "#### Temperature and humidity details\n" + "> Device location: " + eventJson.tag + "\n\n" + "> Device number: " + eventJson.isn+ "\n\n" +

"> Temperature: " + eventJson.temperature + "℃\n\n" + "> Humidity: " + eventJson.humidity + "%\n\n" + "> ###### " + eventJson.time + " published by [Alibaba Cloud IoT Platform](https://www.aliy

un.com/product/iot) \n" }, "at": { "isAtAll": false

} }); const options = {

hostname: 'oapi.dingtalk.com', port: 443, path: '/robot/send? access_token=' + accessToken,

method: 'POST', headers: { 'Content-Type': 'application/json',

'Content-Length': Buffer.byteLength(postData) } };

const req = https.request(options, (res) => { res.setEncoding('utf8'); res.on('data', (chunk) => {});

res.on('end', () => { callback(null, 'success'); });

}); // When an exception returns req.on('error', (e) => {

callback(e); });

219 > Document Version:20200922 物联网平台 Best Practices · Data forwarding

}); // Write the data req.write(postData);

req.end(); };

3. Configure IoT Platform. i. In the IoT Platform console, select Products and then create a product for the temperature and humidity sensor.

ii. On the Topic Categories tab page of the product details page, create a topic category / productKey/${deviceName}/user/data whose Device Operation Authorizations is Publish.

iii. On the Define Feature tab page, define two properties: temperature and humidity. iv. Select Devices and then register a device. v. Click View next to the device name. On the Tag Information section, click Edit to add two device tags.

Tag Key Tag Value Description

Room 007S, 3rd Floor, tag Device location Building 2, Cloud Town

deviceISN T20180102XnbKjmoAnUb Device number

vi. Select Rules > Data Forwarding to create and enable a rule. A complete rule contains three parts: basic information, data processing SQL, and data forwarding. You can specify multiple forwarding actions for a rule.

> Document Version:20200922 220 Best Practices · Data forwarding 物联网平台

a. Configure the data processing script.

The rules engine supports SQL statements.

The device name (deviceName) and attributes (tag and deviceISN) are required.

This SQL is to obtain the temperature and humidity values from the payload of the messages that are sent from the temperature and humidity sensor.

The SQL statements are as follows:

SELECT deviceName() as deviceName, attribute('tag') as tag,

attribute('deviceISN') as isn, temperature, humidity,

timestamp('yyyy-MM-dd HH:mm:ss') as time FROM "/Specify the productKey/+/user/data"

221 > Document Version:20200922 物联网平台 Best Practices · Data forwarding

b. Configure the data forwarding action.

The complete rule is as follows:

vii. On the rules page, click Enable to enable the rule. 4. Temperature and humidity sensor.

To facilitate testing, a Node.js program is used to simulate the temperature and humidity sensor and send the temperature and humidity data. The aliyun-iot-mqtt library is used in this example. The complete code is as follows:

const mqtt = require('aliyun-iot-mqtt'); const client = mqtt.getAliyunIotMqttClient({

productKey: "Specify the productKey", deviceName: "Specify the deviceName", deviceSecret: "Specify the deviceSecret"

}); const topic = 'Specify the topic with forwarding actions'; const data = {

temperature: 18, humidity: 63, };

client.publish(topic, JSON.stringify(data));

5. DingTalk robot receives messages.

> Document Version:20200922 222 Best Practices · Data forwarding 物联网平台

i. The program sends the temperature and humidity data.

$ npm install $ node demo.js

ii. DingTalk robot receives the data, and sends a message to the DintTalk group.

223 > Document Version:20200922