├── CHANGELOG.md ├── LICENSE ├── README.md ├── aliyun_mqtt.cpp ├── aliyun_mqtt.h ├── examples ├── esp8266 │ └── esp8266.cpp └── uno │ └── uno.ino └── library.json /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # AliyunMqttArduino: Change Log 2 | 3 | ## v0.2.0 (Feb. 14th, 2019) 4 | 5 | * Add two new APIs to support calculate HMAC256 externally for resource limited device like Arduino UNO. 6 | * Update README. 7 | * Add UNO example. 8 | 9 | ## v0.1.1 (Jan. 2019) 10 | 11 | * Include examples code in library release. 12 | * Add changelog file. 13 | 14 | ## v0.1.0 15 | 16 | * Initial release to PIO registry and validated with Node MCU v3. 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to 5 | deal in the Software without restriction, including without limitation the 6 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 | sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 | IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arduino - 阿里云物联网平台MQTT连接库 2 | 3 | ## 简介 4 | 5 | 为简化使用Arduino Framwork的开发者连接阿里云物联网平台时的工作,本项目封装了开源的 6 | [PubSubClient库](https://github.com/knolleary/pubsubclient)和 7 | [Arduino Cryptography Library](https://github.com/rweather/arduinolibs)代码库, 8 | 帮助开发者完成连接阿里云物联网平台需要的参数设置以及准备工作。开发者只要提供从阿里云物联网平台上获得的 9 | 三元组(Product Key, Device Name, Device Key)就可以迅速使用支持Arduino Framework的开发板完 10 | 成MQTT连云和数据上报。 11 | 12 | 关于本库实现的说明: 13 | 14 | 1. 本代码库使用HMAC256算法完成连接时的签名验证。 15 | 2. 本代码库并不进一步封装`PubSubClient`库本身的接口,使用者可以仍然以熟悉的方式使用`PubSubClient`库接口, 16 | 这个库仅仅帮助开发者完成连接阿里云MQTT Broker的繁琐部分。 17 | 3. 默认使用阿里云华东2区作为连接region,使用其他region的用户调用时可以显式指定region名。 18 | 19 | 目前已验证平台和硬件包括: 20 | 21 | * Atmel AVR: Arduino UNO. 22 | * Espressif 8266: Node MCU v3. 23 | 24 | 其他经验证的平台和开发板信息可以逐步更新到上面列表中。 25 | 26 | ## 使用方法 27 | 28 | ### 资源较多的设备 29 | 30 | 在Node MCU上可以直接使用本库提供的API完成所有连接参数以及HMAC256签名的动态计算,仅仅使用下面的API即可。 31 | 32 | ```C 33 | /** 34 | * Connect to Alibaba Cloud MQTT server. In connection process, it will try several times for 35 | * possible network failure. For authentication issue, it will return false at once. 36 | * 37 | * @param mqttClient: Caller provide a valid PubSubClient object (initialized with network client). 38 | 39 | * @param productKey: Product Key, get from Alibaba Cloud Link Platform. 40 | 41 | * @param deviceName: Device Name, get from Alibaba Cloud Link Platform. 42 | 43 | * @param deviceSecret: Device Secret, get from Alibaba Cloud Link Platform. 44 | * 45 | * @param region: Optional region, use "cn-shanghai" as default. It can be "us-west-1", 46 | * "ap-southeast-1" etc. Refer to Alibaba Cloud Link Platform. 47 | * 48 | * 49 | * @return true if connect succeed, otherwise false. 50 | */ 51 | bool connectAliyunMQTT( 52 | PubSubClient &mqttClient, 53 | const char *productKey, 54 | const char *deviceName, 55 | const char *deviceSecret, 56 | const char *region = "cn-shanghai"); 57 | ``` 58 | 59 | ### 资源较少的设备 60 | 61 | 如Arduino UNO,只有2K的SRAM,对于此类设备,需要将计算HMAC256签名的过程放在程序外部,并对应用程序内存使用做适当的优化,才能运行程序。 62 | 63 | 资源受限平台上,本库提供了以下两个APIs,其中初始化准备阶段如Arduino `setup`函数中调用第一个函数准备MQTT的连接参数。另外借助[外部签名 64 | 计算工具](http://tool.oschina.net/encrypt?type=2)完成HMAC256 MQTT签名的计算,之后使用该签名进行MQTT连接过程。 65 | 66 | ```C 67 | /** 68 | * Two new added APIs are designed for devices with limited resource like Arduino UNO. 69 | * Since it is hard to calculate HMAC256 on such devices, the calculation can be done externally. 70 | * 71 | * These two APIs should be used together with external HMAC256 calculation tools, e.g. 72 | * http://tool.oschina.net/encrypt?type=2 73 | * They can be used together to replace connectAliyunMQTT on resource-limited devices. 74 | */ 75 | 76 | /** 77 | * This API should be called in setup() phase to init all MQTT parameters. Since HMAC256 78 | * calculation is executed extenrally, a fixed timestamp string should be provided, such 79 | * as "23668" etc. The same timestamp string is also used to calculate HMAC256 result. 80 | * 81 | * Other params are similar to them in connectAliyunMQTT. 82 | */ 83 | extern "C" void mqttPrepare( 84 | const char *timestamp, 85 | const char *productKey, 86 | const char *deviceName, 87 | const char *deviceSecret, 88 | const char *region = "cn-shanghai"); 89 | 90 | /** 91 | * Use tools here to calculate HMAC256: http://tool.oschina.net/encrypt?type=2 92 | * The calculated result should be defined as constants and passed when call this function. 93 | */ 94 | extern "C" bool connectAliyunMQTTWithPassword(PubSubClient &mqttClient, const char *password); 95 | ``` 96 | 97 | ### 包含头文件 98 | 99 | 使用者只需要将`aliyun_mqtt.h`包含到自己的文件中使用即可,无需进一步包含`PubSubClient.h` 头文件。 100 | 已支持开发板中的使用示例可参考example目录中对应的例子。 101 | 102 | ### 增加库依赖和编译选项配置 103 | 104 | 由于Aliyun IoT平台MQTT borker连接时需要的参数与`PubSubClient`库默认参数不同,因此需要将以下两个宏定义加入你对应工程的预编译选项中: 105 | 106 | * KeepAlive: 应当在60s到300秒之间,否则会被服务器拒绝连接。 107 | * 默认MQTT包最大值:PubSubClient库默认为128字节,需要调整为256字节及以上值。 108 | 109 | 例如对于Platform IO的工程,可以在应用的`platform.ini`文件中加入类似下面的库依赖和编译选项配置: 110 | 111 | ```ini 112 | lib_deps = 113 | https://code.aliyun.com/hacklab/aliyun-mqtt-arduino.git 114 | 115 | # Customize PubSub MQTT configs for Aliyun MQTT broker 116 | build_flags = 117 | -D MQTT_MAX_PACKET_SIZE=256 118 | -D MQTT_KEEPALIVE=60 119 | ``` 120 | -------------------------------------------------------------------------------- /aliyun_mqtt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Aliyun_mqtt.h - Library for connect to Aliyun MQTT server. 3 | */ 4 | 5 | #include "aliyun_mqtt.h" 6 | 7 | #include 8 | 9 | #define MQTT_PORT 1883 10 | #define SHA256HMAC_SIZE 32 11 | 12 | // Verify tool: http://tool.oschina.net/encrypt?type=2 13 | static String hmac256(const String &signcontent, const String &ds) 14 | { 15 | byte hashCode[SHA256HMAC_SIZE]; 16 | SHA256 sha256; 17 | 18 | const char *key = ds.c_str(); 19 | size_t keySize = ds.length(); 20 | 21 | sha256.resetHMAC(key, keySize); 22 | sha256.update((const byte *)signcontent.c_str(), signcontent.length()); 23 | sha256.finalizeHMAC(key, keySize, hashCode, sizeof(hashCode)); 24 | 25 | String sign = ""; 26 | for (byte i = 0; i < SHA256HMAC_SIZE; ++i) 27 | { 28 | sign += "0123456789ABCDEF"[hashCode[i] >> 4]; 29 | sign += "0123456789ABCDEF"[hashCode[i] & 0xf]; 30 | } 31 | 32 | return sign; 33 | } 34 | 35 | static String mqttBroker; 36 | static String mqttClientID; 37 | static String mqttUserName; 38 | static String mqttPassword; 39 | 40 | // call this function once 41 | void mqttPrepare(const char *timestamp, 42 | const char *productKey, 43 | const char *deviceName, 44 | const char *deviceSecret, 45 | const char *region) 46 | { 47 | mqttBroker = productKey; 48 | mqttBroker += ".iot-as-mqtt."; 49 | mqttBroker += String(region); 50 | mqttBroker += ".aliyuncs.com"; 51 | // Serial.println(mqttBroker); 52 | 53 | mqttUserName = deviceName; 54 | mqttUserName += '&'; 55 | mqttUserName += productKey; 56 | // Serial.println(mqttUserName); 57 | 58 | mqttClientID = deviceName; // device name used as client ID 59 | mqttClientID += "|securemode=3,signmethod=hmacsha256,timestamp="; 60 | mqttClientID += timestamp; 61 | mqttClientID += '|'; 62 | // Serial.println(mqttClientID); 63 | } 64 | 65 | bool connectAliyunMQTTWithPassword(PubSubClient &mqttClient, const char *password) 66 | { 67 | mqttClient.setServer(mqttBroker.c_str(), MQTT_PORT); 68 | 69 | byte mqttConnectTryCnt = 5; 70 | while (!mqttClient.connected() && mqttConnectTryCnt > 0) 71 | { 72 | // Serial.println("Connecting to MQTT Server ..."); 73 | if (mqttClient.connect(mqttClientID.c_str(), mqttUserName.c_str(), password)) 74 | { 75 | 76 | // Serial.println("MQTT Connected!"); 77 | return true; 78 | } 79 | else 80 | { 81 | byte errCode = mqttClient.state(); 82 | // Serial.print("MQTT connect failed, error code:"); 83 | // Serial.println(errCode); 84 | if (errCode == MQTT_CONNECT_BAD_PROTOCOL || errCode == MQTT_CONNECT_BAD_CLIENT_ID || errCode == MQTT_CONNECT_BAD_CREDENTIALS || errCode == MQTT_CONNECT_UNAUTHORIZED) 85 | { 86 | // Serial.println("No need to try again."); 87 | break; // No need to try again for these situation 88 | } 89 | delay(5000); 90 | } 91 | mqttConnectTryCnt -= 1; 92 | } 93 | 94 | return false; 95 | } 96 | 97 | bool connectAliyunMQTT( 98 | PubSubClient &mqttClient, 99 | const char *productKey, 100 | const char *deviceName, 101 | const char *deviceSecret, 102 | const char *region) 103 | { 104 | String timestamp = String(millis()); 105 | mqttPrepare(timestamp.c_str(), productKey, deviceName, deviceSecret, region); 106 | 107 | // Generate MQTT Password, use deviceName as clientID 108 | String signcontent = "clientId"; 109 | signcontent += deviceName; 110 | signcontent += "deviceName"; 111 | signcontent += deviceName; 112 | signcontent += "productKey"; 113 | signcontent += productKey; 114 | signcontent += "timestamp"; 115 | signcontent += timestamp; 116 | 117 | String mqttPassword = hmac256(signcontent, deviceSecret); 118 | 119 | // Serial.print("HMAC256 data: "); 120 | // Serial.println(signcontent); 121 | // Serial.print("HMAC256 key: "); 122 | // Serial.println(deviceSecret); 123 | // Serial.println(mqttPassword); 124 | 125 | return connectAliyunMQTTWithPassword(mqttClient, mqttPassword.c_str()); 126 | } 127 | -------------------------------------------------------------------------------- /aliyun_mqtt.h: -------------------------------------------------------------------------------- 1 | /* 2 | Aliyun_mqtt.h - Library for connect to Aliyun MQTT server with authentication by 3 | product key, device name and device secret. 4 | 5 | https://www.alibabacloud.com/help/product/30520.htm 6 | */ 7 | 8 | #ifndef _ALIYUN_MATT_H 9 | #define _ALIYUN_MATT_H 10 | 11 | #include 12 | #include 13 | 14 | /** 15 | * Connect to Alibaba Cloud MQTT server. In connection process, it will try several times for 16 | * possible network failure. For authentication issue, it will return false at once. 17 | * 18 | * @param mqttClient: Caller provide a valid PubSubClient object (initialized with network client). 19 | 20 | * @param productKey: Product Key, get from Alibaba Cloud Link Platform. 21 | 22 | * @param deviceName: Device Name, get from Alibaba Cloud Link Platform. 23 | 24 | * @param deviceSecret: Device Secret, get from Alibaba Cloud Link Platform. 25 | * 26 | * @param region: Optional region, use "cn-shanghai" as default. It can be "us-west-1", 27 | * "ap-southeast-1" etc. Refer to Alibaba Cloud Link Platform. 28 | * 29 | * 30 | * @return true if connect succeed, otherwise false. 31 | */ 32 | extern "C" bool connectAliyunMQTT( 33 | PubSubClient &mqttClient, 34 | const char *productKey, 35 | const char *deviceName, 36 | const char *deviceSecret, 37 | const char *region = "cn-shanghai"); 38 | 39 | /** 40 | * Two new added APIs are designed for devices with limited resource like Arduino UNO. 41 | * Since it is hard to calculate HMAC256 on such devices, the calculation can be done externally. 42 | * 43 | * These two APIs should be used together with external HMAC256 calculation tools, e.g. 44 | * http://tool.oschina.net/encrypt?type=2 45 | * They can be used together to replace connectAliyunMQTT on resource-limited devices. 46 | */ 47 | 48 | /** 49 | * This API should be called in setup() phase to init all MQTT parameters. Since HMAC256 50 | * calculation is executed extenrally, a fixed timestamp string should be provided, such 51 | * as "23668" etc. The same timestamp string is also used to calculate HMAC256 result. 52 | * 53 | * Other params are similar to them in connectAliyunMQTT. 54 | */ 55 | extern "C" void mqttPrepare( 56 | const char *timestamp, 57 | const char *productKey, 58 | const char *deviceName, 59 | const char *deviceSecret, 60 | const char *region = "cn-shanghai"); 61 | 62 | /** 63 | * Use tools here to calculate HMAC256: http://tool.oschina.net/encrypt?type=2 64 | * The calculated result should be defined as constants and passed when call this function. 65 | */ 66 | extern "C" bool connectAliyunMQTTWithPassword(PubSubClient &mqttClient, const char *password); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /examples/esp8266/esp8266.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "aliyun_mqtt.h" 6 | 7 | // GPIO 13, D7 on the Node MCU v3 8 | #define SENSOR_PIN 13 9 | 10 | #define WIFI_SSID "" 11 | #define WIFI_PASSWD "" 12 | 13 | #define PRODUCT_KEY "" 14 | #define DEVICE_NAME "" 15 | #define DEVICE_SECRET "" 16 | 17 | #define ALINK_BODY_FORMAT "{\"id\":\"123\",\"version\":\"1.0\",\"method\":\"%s\",\"params\":%s}" 18 | #define ALINK_TOPIC_PROP_POST "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post" 19 | #define ALINK_TOPIC_PROP_POSTRSP "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post_reply" 20 | #define ALINK_TOPIC_PROP_SET "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/service/property/set" 21 | #define ALINK_METHOD_PROP_POST "thing.event.property.post" 22 | 23 | unsigned long lastMs = 0; 24 | 25 | WiFiClient espClient; 26 | PubSubClient mqttClient(espClient); 27 | 28 | void initWifi(const char *ssid, const char *password) 29 | { 30 | WiFi.mode(WIFI_STA); 31 | WiFi.begin(ssid, password); 32 | while (WiFi.status() != WL_CONNECTED) 33 | { 34 | Serial.println("WiFi does not connect, try again ..."); 35 | delay(3000); 36 | } 37 | 38 | Serial.println("Wifi is connected."); 39 | Serial.println("IP address: "); 40 | Serial.println(WiFi.localIP()); 41 | } 42 | 43 | void callback(char *topic, byte *payload, unsigned int length) 44 | { 45 | Serial.print("Message arrived ["); 46 | Serial.print(topic); 47 | Serial.print("] "); 48 | payload[length] = '\0'; 49 | Serial.println((char *)payload); 50 | 51 | if (strstr(topic, ALINK_TOPIC_PROP_SET)) 52 | { 53 | StaticJsonBuffer<100> jsonBuffer; 54 | JsonObject &root = jsonBuffer.parseObject(payload); 55 | if (!root.success()) 56 | { 57 | Serial.println("parseObject() failed"); 58 | return; 59 | } 60 | } 61 | } 62 | 63 | void mqttCheckConnect() 64 | { 65 | while (!connectAliyunMQTT(mqttClient, PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET)) 66 | { 67 | } 68 | 69 | Serial.println("MQTT connect succeed!"); 70 | // client.subscribe(ALINK_TOPIC_PROP_POSTRSP); 71 | mqttClient.subscribe(ALINK_TOPIC_PROP_SET); 72 | Serial.println("subscribe done"); 73 | } 74 | 75 | void mqttIntervalPost() 76 | { 77 | char param[32]; 78 | char jsonBuf[128]; 79 | 80 | sprintf(param, "{\"MotionAlarmState\":%d}", digitalRead(13)); 81 | sprintf(jsonBuf, ALINK_BODY_FORMAT, ALINK_METHOD_PROP_POST, param); 82 | Serial.println(jsonBuf); 83 | mqttClient.publish(ALINK_TOPIC_PROP_POST, jsonBuf); 84 | } 85 | 86 | void setup() 87 | { 88 | 89 | pinMode(SENSOR_PIN, INPUT); 90 | /* initialize serial for debugging */ 91 | Serial.begin(115200); 92 | 93 | Serial.println("Demo Start"); 94 | 95 | initWifi(WIFI_SSID, WIFI_PASSWD); 96 | 97 | mqttClient.setCallback(callback); 98 | } 99 | 100 | // the loop function runs over and over again forever 101 | void loop() 102 | { 103 | if (millis() - lastMs >= 5000) 104 | { 105 | lastMs = millis(); 106 | mqttCheckConnect(); 107 | 108 | /* Post */ 109 | mqttIntervalPost(); 110 | } 111 | 112 | mqttClient.loop(); 113 | 114 | unsigned int WAIT_MS = 60000; 115 | if (digitalRead(SENSOR_PIN) == HIGH) 116 | { 117 | Serial.println("Motion detected!"); 118 | } 119 | else 120 | { 121 | Serial.println("Motion absent!"); 122 | } 123 | delay(WAIT_MS); // ms 124 | Serial.println(millis() / WAIT_MS); 125 | } 126 | -------------------------------------------------------------------------------- /examples/uno/uno.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Arduino Temperature with DHT sensors to Aliyun MQTT Server 3 | * Refer to https://thingsboard.io/docs/samples/arduino/temperature/ 4 | */ 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | //DHT sensor pin and type setting 15 | #define DHTPIN A0 16 | #define DHTTYPE DHT11 17 | 18 | // Initialize DHT sensor. 19 | DHT dht(DHTPIN, DHTTYPE); 20 | 21 | #define WIFI_SSID "" 22 | #define WIFI_PASSWORD "" 23 | 24 | // Initialize the Ethernet client object 25 | const int WIFI_RX = 2; 26 | const int WIFI_TX = 3; 27 | SoftwareSerial softSerial(WIFI_RX, WIFI_TX); // RX, TX 28 | 29 | void connectWiFi() 30 | { 31 | int status = WiFi.status(); 32 | // attempt to connect to WiFi network 33 | while (status != WL_CONNECTED) 34 | { 35 | Serial.print(F("Attempting to connect to Wifi: ")); 36 | Serial.println(WIFI_SSID); 37 | // Connect to WPA/WPA2 network 38 | status = WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 39 | delay(500); 40 | } 41 | } 42 | 43 | void initWiFi() 44 | { 45 | // initialize serial for ESP module 46 | softSerial.begin(9600); 47 | // initialize ESP module 48 | WiFi.init(&softSerial); 49 | // check for the presence of the shield 50 | if (WiFi.status() == WL_NO_SHIELD) 51 | { 52 | Serial.println(F("WiFi shield not present, stop")); 53 | // don't continue 54 | while (true); 55 | } 56 | 57 | connectWiFi(); 58 | Serial.print(F("Connected to AP: ")); 59 | Serial.println(WiFi.localIP()); 60 | } 61 | 62 | #define TIMESTAMP "23668" // can be changed to a random positive value string 63 | 64 | // Use external HMAC256 calculation for MQTT_PASSWORD: http://tool.oschina.net/encrypt?type=2 65 | // Content: clientId[DEVICE_NAME]deviceName[DEVICE_NAME]productKey[PRODUCT_KEY]timestamp[TIMESTAMP] 66 | // Key: [DEVICE_SECRET] 67 | 68 | #define PRODUCT_KEY "" 69 | #define DEVICE_NAME "" 70 | #define DEVICE_SECRET "" 71 | #define MQTT_PASSWORD "" 72 | 73 | // https://help.aliyun.com/document_detail/89301.html 74 | #define ALINK_TOPIC_PROP_POST "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post" 75 | 76 | unsigned long lastSend; 77 | 78 | WiFiEspClient espClient; 79 | PubSubClient mqttClient(espClient); 80 | 81 | void checkMqttConnection() 82 | { 83 | connectWiFi(); 84 | 85 | // Loop until we're reconnected 86 | while (!mqttClient.connected()) 87 | { 88 | Serial.println(F("Connecting to Aliyun IoT ...")); 89 | // Attempt to connect (clientId, username, password) 90 | if (connectAliyunMQTTWithPassword(mqttClient, MQTT_PASSWORD)) 91 | { 92 | Serial.println("[MQTT Connected]"); 93 | } 94 | else 95 | { 96 | Serial.print(F("[MQTT Connect FAILED] [rc = ")); 97 | Serial.print(mqttClient.state()); 98 | Serial.println(F(": retrying in 5 seconds]")); 99 | // Wait 5 seconds before retrying 100 | delay(5000); 101 | } 102 | } 103 | } 104 | 105 | void getAndSendTemperatureAndHumidityData() 106 | { 107 | // Reading temperature or humidity takes about 250 milliseconds! 108 | int h = dht.readHumidity(); 109 | // Read temperature as Celsius (the default) 110 | int t = dht.readTemperature(); 111 | // Check if any reads failed and exit early (to try again). 112 | if (isnan(h) || isnan(t)) 113 | { 114 | Serial.println(F("Failed to read sensor data!")); 115 | return; 116 | } 117 | 118 | Serial.print(F("Humidity: ")); 119 | Serial.print(h); 120 | Serial.print(F("% Temperature: ")); 121 | Serial.print(t); 122 | Serial.println(F("°C")); 123 | 124 | String temperature = String(t); 125 | String humidity = String(h); 126 | 127 | // Prepare a JSON payload string 128 | String payload = "{"; 129 | payload += "\"temperature\":"; 130 | payload += temperature; 131 | payload += ","; 132 | payload += "\"humidity\":"; 133 | payload += humidity; 134 | payload += "}"; 135 | 136 | // Send payload as Alink data 137 | String jsonData = F("{\"id\":\"123\",\"version\":\"1.0\",\"method\":\"thing.event.property.post\",\"params\":"); 138 | jsonData += payload; 139 | jsonData += F("}"); 140 | 141 | char alinkData[128]; 142 | jsonData.toCharArray(alinkData, 128); 143 | mqttClient.publish(ALINK_TOPIC_PROP_POST, alinkData); 144 | Serial.println(alinkData); 145 | } 146 | 147 | void setup() 148 | { 149 | Serial.begin(115200); 150 | initWiFi(); 151 | dht.begin(); 152 | mqttPrepare(TIMESTAMP, PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET); 153 | lastSend = 0; 154 | } 155 | 156 | void loop() 157 | { 158 | checkMqttConnection(); 159 | 160 | if (millis() - lastSend >= 10000) 161 | { // Update and send only after 1 seconds 162 | getAndSendTemperatureAndHumidityData(); 163 | lastSend = millis(); 164 | } 165 | mqttClient.loop(); 166 | } 167 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "AliyunMqttArduino", 3 | "version": "0.2.0", 4 | "keywords": "aliyun, mqtt, pubsub, iot", 5 | "description": "A simple Aliyun MQTT connection library for Arduino", 6 | "license": "MIT", 7 | "homepage": "https://github.com/legenddcr/aliyun-mqtt-arduino", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/legenddcr/aliyun-mqtt-arduino.git" 11 | }, 12 | "authors": { 13 | "name": "Chengrui Deng", 14 | "email": "legenddcr@gmail.com" 15 | }, 16 | "dependencies": [ 17 | { 18 | "name": "Crypto", 19 | "version": "^0.2.0" 20 | }, 21 | { 22 | "name": "PubSubClient", 23 | "version": "^2.7" 24 | } 25 | ], 26 | "frameworks": "arduino", 27 | "platforms": [ 28 | "atmelavr", 29 | "espressif8266" 30 | ] 31 | } 32 | --------------------------------------------------------------------------------