first commit

This commit is contained in:
james.liu 2020-08-25 16:19:31 +08:00
commit ccbff56627
26 changed files with 1022 additions and 0 deletions

20
LICENSE.txt Normal file
View File

@ -0,0 +1,20 @@
Copyright (c) 2008-2015 Nicholas O'Leary
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

137
REDME.md Normal file
View File

@ -0,0 +1,137 @@
#arduino esp32接入物联网通信云平台
------------
###本实践使用arduino平台esp32 wrover-b开发板连接上物联网通信云平台UIoT Core实现mqtt消息的发布与订阅
##一、环境准备
###1.下载并安装arduino IDE,[点击选择下载方式](https://www.arduino.cn/thread-5838-1-1.html)
###2.完成安装之后打开IDE安装ESP32包步骤如下
点击文件->首选项,弹出对话框
![1](./photo/1.png)
按如图所示点击1处方框将 https://dl.espressif.com/dl/package_esp32_index.json 填入,点击好,保存
![2](./photo/2.png)
点击工具->开发板->开发板管理器,弹出对话框
![3](./photo/3.png)
等待下载完成之后,安装
![4](./photo/4.png)
下载完成之后点击搜索框搜索esp32点击安装安装完成之后显示INSTALLED
![5](./photo/5.png)
esp32开发板安装完成
###3.安装依赖库
点击 工具->管理库,弹出对话框
![6](./photo/6.png)
安装PubSubClient库在搜索框中粘贴```PubSubClient```,找到该名称**对应的库**,并安装
![7](./photo/7.png)
安装ArduinoJson库在搜索框中粘贴```Arduino_JSON```,找到该名称**对应的库**,并安装
![8](./photo/8.png)
安装UCloudIoTSDK库,在搜索框中粘贴```UCloudIoTSDK```,找到该名称**对应的库**,并安装
![9](./photo/9.png)
###4.开发板设置
用USB--连接上开发板,将开发板信息设置为如图所示(该设置仅仅针对该款ESP32,其它请自行查阅资料确认如何设置)
![10](./photo/10.png)
##二、程序编写
###1.首先包含sdk头文件以及连接wifi所需头文件。
###2.设置wifi ssid以及password。
###3.设置连接物联网通信平台需要的信息,该部分信息必须在物联网通信平台[创建产品以及设备](https://docs.ucloud.cn/uiot-core/console_guide/product_device/create_products)之后获得。```product_sn``` 和```device_sn```必填。[静态连接](https://docs.ucloud.cn/uiot-core/device_develop_guide/authenticate_devices/unique-certificate-per-device_authentication)时,将```product_secret```置为NULL并填写```device_secret```。[动态注册](https://docs.ucloud.cn/uiot-core/device_develop_guide/authenticate_devices/unique-certificate-per-product_authentication)时将```device_secret```置为NULL并填写```product_secret```。
###4.定义mqtt测试topic。
###5.设置用户消息回调函数该回调函数在mqtt收到消息之后调用。
###6.wifi连接过程
###7.根据四元组信息以及回调函数构造UCloudMQTT对象
###8.setup里面进行wifi连接以及mqtt连接订阅测试topic
###9.loop里面进行消息接收以及每两秒发布一条测试topic的消息
![11](./photo/11.png)
![12](./photo/12.png)
##三、烧录以及现象
###1.烧录
点击图中→方向,点击之后开始编译,编译通过后自动下载到开发板
![13](./photo/13.png)
###2.现象
使用串口工具连接esp32串口看到如图所示有wifi连接成功mqtt连接成功。以及订阅发布成功的log。
![14](./photo/14.png)
##四、注意事项
###1.编译出现有些文件找不到,请确认是否将必要的库安装成功
###2.烧录不了确认arduino IDE能够读取到端口信息如果开发板端口连接到其他串口工具将会造成烧录失败
##五、拓展
###该例程只演示了使用静态连接连上物联网通信云平台此外SDK还有动态注册以及TLS加密连接功能。想要使用动态注册只需要将四元组信息的```device_sn```置为NULL,并且正确填写四元组的其他三个信息。如果想要使用TLS加密连接找到库文件将库文件中的```ucloud_iot_sdk_esp32.h```打开,将```ENABLE_TLS```宏打开即可
![15](./photo/15.png)
##六、API参考
###1.构造对象接口
要使用该库进行mqtt连接到物联网通信云平台时需要首先构建UCloudMQTT对象使用到以下接口
UCloudMQTT(
char *product_sn,
char *device_sn,
char *product_secret,
char *device_secret,
MQTTHandlerFun callback
);
参数:```product_sn```,指向存有产品序列号字符串的指针
参数:```device_sn``` ,指向存有设备序列号字符串的指针
参数:```product_secret```,指向存有产品秘钥字符串的指针
参数:```device_secret``` ,指向存有设备秘钥字符串的指针
参数:```callback```,用户消息回调函数指针
使用示例:
```UCloudMQTT ucloudMQTT(product_sn,device_sn,product_secret,device_secret,msg_callback);```
###2.MQTT连接接口
int mqtt_connect(void);
返回值: 0-连接成功 1-连接失败
使用示例:```mqtt_connect();```
###3.延时等待接收MQTT消息接口
void mqttYield(int time_ms);
参数:```time_ms```延时等待的时间ms为单位。
使用示例:```mqttYield(2000);```
###4.查询MQTT状态接口
boolean mqtt_status(void);
返回值: true-处于连接状态 false-断开状态
使用示例:```mqtt_status();```
###5.MQTT发布接口
boolean publish(
const char* topic,
const char* payload
);
参数:```topic```消息TOPIC
参数:```payload```,消息内容
返回值true-发布成功 false-发布失败
使用示例:```publish(MSG_TOPIC,"123456");```
###6.MQTT订阅接口
boolean subscribe(const char* topic);
参数:```topic```订阅的TOPIC
返回值true-订阅成功 false-订阅失败
使用示例:```subscribe(MSG_TOPIC);```
-------------
#结束

78
examples/ESP32/esp32.ino Normal file
View File

@ -0,0 +1,78 @@
#include "ucloud_iot_sdk_esp32.h"
#include <WiFi.h>
/******用户实现************/
#define wifi_ssid "LJZ"
#define wifi_password "12345678"
#define product_sn "o2lp4qngf6ytdq1n"
#define device_sn "hhg4fq0iiw23lwp7"
#define product_secret NULL//"i1jybkmxm1ez9l4y"
#define device_secret "da5qd9isg6j8eany"
/*************************/
#define MQTT_TEST_TOPIC "/%s/%s/test/mqtt_connect"
#define MQTT_TEST_MESSAGE "This is a test message!"
char mqtt_test_topic[80];
/*******用户消息回调函数************/
void msg_callback(char* topic, uint8_t* payload, unsigned int length)
{
Serial.println("calling user callback ");
Serial.print("Message received: ");
Serial.println(topic);
Serial.print("payload: ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
int wifi_connect(char *ssid,char *password)
{
Serial.print("attempting to connect ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status()!= WL_CONNECTED)
{
Serial.print(".");
// wait 1 second for re-trying
delay(1000);
}
Serial.print("connected with ");
Serial.println(ssid);
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
UCloudMQTT ucloudMQTT(product_sn,device_sn,product_secret,device_secret,msg_callback);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
//连接wifi
wifi_connect(wifi_ssid,wifi_password);
//连接mqtt
while(!ucloudMQTT.mqtt_status()) {
ucloudMQTT.mqtt_connect();
}
Serial.println("connected to ucloud iot core platform!");
//订阅topic
sprintf(mqtt_test_topic,MQTT_TEST_TOPIC,product_sn,device_sn);
if(ucloudMQTT.subscribe(mqtt_test_topic)==false)
Serial.println("subscribe topic failed !");
else
Serial.println("subscribe topic success !");
}
void loop() {
// put your main code here, to run repeatedly:
ucloudMQTT.mqttYield(2000);
if(ucloudMQTT.publish(mqtt_test_topic,MQTT_TEST_MESSAGE)==false)
Serial.println("publish topic failed !");
else
Serial.println("publish topic success !");
}

View File

@ -0,0 +1,73 @@
#include "ucloud_iot_sdk_esp8266.h"
#include "ESP8266WiFi.h"
/******用户实现************/
#define wifi_ssid "LJZ"
#define wifi_password "12345678"
#define product_sn "o2lp4qngf6ytdq1n"
#define device_sn "4dg7a36jyla1qz1j"
#define product_secret NULL//"i1jybkmxm1ez9l4y"
#define device_secret "s2zrz9eaaj5ibpho"
/*************************/
#define MQTT_TEST_TOPIC "/%s/%s/test/mqtt_connect"
char mqtt_test_topic[80];
/*******用户消息回调函数************/
void msg_callback(char* topic, uint8_t* payload, unsigned int length)
{
Serial.println("calling user callback ");
Serial.print("Message received: ");
Serial.println(topic);
Serial.print("payload: ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
}
int wifi_connect(char *ssid,char *password)
{
Serial.print("attempting to connect ");
Serial.println(ssid);
//WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status()!= WL_CONNECTED)
{
Serial.print(".");
// wait 1 second for re-trying
delay(1000);
}
Serial.print("connected with ");
Serial.println(ssid);
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
UCloudMQTT ucloudMQTT(product_sn,device_sn,product_secret,device_secret,msg_callback);
void setup() {
// put your setup code here, to run once:
Serial.begin(76800);
Serial.println();
//连接wifi
wifi_connect(wifi_ssid,wifi_password);
//连接mqtt
while(!ucloudMQTT.mqtt_status()) {
ucloudMQTT.mqtt_connect();
}
Serial.println("connected to ucloud iot core platform!");
//订阅topic
sprintf(mqtt_test_topic,MQTT_TEST_TOPIC,product_sn,device_sn);
if(ucloudMQTT.subscribe(mqtt_test_topic)==false)
Serial.println("subscribe topic failed !");
else
Serial.println("subscribe topic success !");
}
void loop() {
// put your main code here, to run repeatedly:
ucloudMQTT.mqttYield(2000);
if(ucloudMQTT.publish(mqtt_test_topic,"123456789")==false)
Serial.println("publish topic failed !");
else
Serial.println("publish topic success !");
}

17
keywords.txt Normal file
View File

@ -0,0 +1,17 @@
# Syntax Coloring Map For UCloud IoT Platform
# Datatypes (KEYWORD1)
UCloudIoTSDK KEYWORD1
# Methods and Functions (KEYWORD2)
mqtt_connect KEYWORD2
mqttYield KEYWORD2
mqtt_status KEYWORD2
publish KEYWORD2
subscribe KEYWORD2
# Constants (LITERAL1)

21
library.json Normal file
View File

@ -0,0 +1,21 @@
{
"name": "UCloudIoTSDK",
"keywords": "ethernet, ucloud, mqtt, m2m, iot",
"description": "UCloudIoTSDK is designed & developed by UCloud IoT team , this library is used to connect with UCloud iot platform.",
"repository": {
"type": "git",
"url": "https://github.com/ucloud/ucloud-iot-sdk-arduino"
},
"version": "0.0.1",
"examples": "examples/*/*.ino",
"frameworks": "arduino",
"platforms": ["espressif8266", "espressif32"],
"dependencies": [
{
"name": "PubSubClient",
},
{
"name": "Arduino_JSON"
}
]
}

9
library.properties Normal file
View File

@ -0,0 +1,9 @@
name=UCloudIoTSDK
version=0.0.1
author=James Liu <james.liu@ucloud.cn>
maintainer=James Liu <james.liu@ucloud.cn>
sentence=An Arduino library for connecting ucloud iot platform made by UCloud IoT team.
paragraph=UCloudIoTSDK is designed & developed by UCloud IoT team , this library is used to connect with UCloud iot platform.
category=Communication
url=https://github.com/ucloud/ucloud-iot-sdk-arduino
architectures=*

BIN
photo/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
photo/10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
photo/11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
photo/12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
photo/13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
photo/14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
photo/15.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
photo/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
photo/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
photo/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
photo/5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
photo/6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
photo/7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
photo/8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
photo/9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,265 @@
#include "ucloud_iot_sdk_esp32.h"
#define PASSWRD_TOPIC "/$system/%s/%s/password"
#define PASSWORD_REPLY_TOPIC "/$system/%s/%s/password_reply"
#define CLIENT_ID "%s.%s"
#define USER_NAME "%s|%s|%d"
WiFiClientSecure espSecureClient;
WiFiClient espClient;
static PubSubClient client;
static const char* mqtt_server = "mqtt-cn-sh2.iot.ucloud.cn";
char password_string[30] = "{\"RequestID\":\"1\"}";
char passwrd_topic[100];
char passwrd_reply_topic[100];
Uiot_Info_st uiot_info_st;
const char* mqtt_ca_crt= \
{
"-----BEGIN CERTIFICATE-----\n" \
"MIIDsjCCApoCCQCudOie27G3QDANBgkqhkiG9w0BAQsFADCBmjELMAkGA1UEBhMC\n"
"Q04xETAPBgNVBAgMCFNoYW5naGFpMREwDwYDVQQHDAhTaGFuZ2hhaTEPMA0GA1UE\n"
"CgwGVUNsb3VkMRgwFgYDVQQLDA9VQ2xvdWQgSW9ULUNvcmUxFjAUBgNVBAMMDXd3\n"
"dy51Y2xvdWQuY24xIjAgBgkqhkiG9w0BCQEWE3Vpb3QtY29yZUB1Y2xvdWQuY24w\n"
"HhcNMTkwNzI5MTIyMDQxWhcNMzkwNzI0MTIyMDQxWjCBmjELMAkGA1UEBhMCQ04x\n"
"ETAPBgNVBAgMCFNoYW5naGFpMREwDwYDVQQHDAhTaGFuZ2hhaTEPMA0GA1UECgwG\n"
"VUNsb3VkMRgwFgYDVQQLDA9VQ2xvdWQgSW9ULUNvcmUxFjAUBgNVBAMMDXd3dy51\n"
"Y2xvdWQuY24xIjAgBgkqhkiG9w0BCQEWE3Vpb3QtY29yZUB1Y2xvdWQuY24wggEi\n"
"MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0g9bzkQBipln/nRsUKeQcwAkU\n"
"ZUk/VMWrg5AzBislYW9hujCGZHWXUknVHPSQM2Pk30tPeIdmupSkOJllYtFplI6U\n"
"6kqHpVsyPn925H5zz4uP5Ty0hkkNK+rIR/YjbEjGn8loTqWk++/o6qST5QOrZLUR\n"
"vxaWvshpce0QUcYU9xMfUPzLa6/ZfmaNHgn1aWExYMJAWDyBCyw4OxeSMUyH+ydh\n"
"egW7VHNQuVHOYdnXiC+VYImNJ8+QAyCIZ88lP0nqVPSKTt1XXmGW6vXrWSl+/XhO\n"
"GaHNMzlwb1kqlFx/ZagTQoQ0hpmqSUKtqPgKSqGPxY9go1Rda1m2rYc8k3gJAgMB\n"
"AAEwDQYJKoZIhvcNAQELBQADggEBAHU0KKqEbR7uoY1tlE+MDsfx/2zXNk9gYw44\n"
"O+xGVdbvTC298Ko4uUEwc1C+l9FaMmN/2qUPSXWsSrAYDGMS63rzaxqNuADTgmo9\n"
"QY0ITtTf0lZTkUahVSqAxzMFaaPzSfFeP9/EaUu14T5RPQbUZMVOAEPKDNmfK4rD\n"
"06R6dnO12be4Qlha14o67+ojaNtyZ7/ESePXA/RjO9YMkeQAoa4BdnsJCZgCFmXf\n"
"iKvGM+50+L/qSbH5F//byLGTO1t3TWCCdBE5/Mc/QLYEXDmZM6LMHyEAw4VuinIa\n"
"I8m1P/ceVO0RjNNBG0pDH9PH4OA7ikY81c63PBCQaYMKaiksCzs=\n"
"-----END CERTIFICATE-----\n"
};
//消息回调函数,收到数据之后对数据进行处理
void dynamic_msg_callback(char* topic, uint8_t* payload, unsigned int length)
{
Serial.print("Message received: ");
Serial.println(topic);
Serial.print("payload: ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
if((0 == strncmp(topic, passwrd_reply_topic, strlen(topic))) && ( uiot_info_st.auth_mode== DYNAMIC_AUTH))
{
JSONVar myObject = JSON.parse((const char *)payload);
if (myObject.hasOwnProperty("Password"))
{
strncpy(uiot_info_st.deviceSecret, myObject["Password"], strlen(myObject["Password"]));
}
if (JSON.typeof(myObject) == "Password")
Serial.print("Password received: ");
Serial.println(uiot_info_st.deviceSecret);
client.disconnect();
uiot_info_st.auth_mode = STATIC_AUTH;
}
}
//构造函数,内部对传入的四元组进行检查以及初始化四元组,传入用户回调函数
UCloudMQTT::UCloudMQTT(char *product_sn,char *device_sn,char *product_secret,char *device_secret,MQTTHandlerFun callback)
{
if(product_sn==NULL||device_sn==NULL)
Serial.println("MQTT CONSTRUCT FAILED!");
if(device_secret!=NULL)
{
uiot_info_st.auth_mode=STATIC_AUTH;
memcpy(uiot_info_st.deviceSecret,device_secret,20);
this->passWord=uiot_info_st.deviceSecret;
}
else if(product_secret!=NULL)
{
uiot_info_st.auth_mode=DYNAMIC_AUTH;
memcpy(uiot_info_st.productSecret,product_secret,20);
this->passWord=uiot_info_st.productSecret;
}
else
{
Serial.println("there is no any secret!");
//~UCloudMQTT();
}
if(callback==NULL)
{
uiot_info_st.user_callback=dynamic_msg_callback;
}
else
{
uiot_info_st.user_callback=callback;
}
#ifdef ENABLE_TLS
uiot_info_st.is_tls=IS_TLS;
#else
uiot_info_st.is_tls=NO_TLS;
#endif
memcpy(uiot_info_st.productSn,product_sn,20);
memcpy(uiot_info_st.deviceSn,device_sn,20);
}
//mqtt连接分为动态注册时的预认证和静态连接
int UCloudMQTT::mqtt_connect(void)
{
int retry_time=10;
while (!client.connected()&&retry_time)
{
if(uiot_info_st.is_tls==IS_TLS)
{
espSecureClient.setCACert(mqtt_ca_crt);
client.setClient(espSecureClient);
client.setServer(mqtt_server, 8883);
Serial.println("support TLS connection!");
}
else
{
client.setClient(espClient);
client.setServer(mqtt_server, 1883);
}
client.setKeepAlive(500);
Serial.print("MQTT connecting ...");
/* connect now */
if(uiot_info_st.auth_mode == DYNAMIC_AUTH)
{
client.setCallback(dynamic_msg_callback);
gen_mqtt_connect_info(DYNAMIC_AUTH);
Serial.print("MQTT dynamic register ...");
//如果是动态注册,等待预认证完成,auth_mode会在回调函数中改变
while (uiot_info_st.auth_mode==DYNAMIC_AUTH&&retry_time)
{
client.connect(this->clientId,this->userName,this->passWord);
if(mqtt_status()==true)
{
Serial.println("connected");
/* subscribe topic to get device secret */
client.subscribe(passwrd_reply_topic);
client.publish(passwrd_topic, password_string);
long start_tick = millis();
long timeout_flg=0;
while(uiot_info_st.auth_mode == DYNAMIC_AUTH&&timeout_flg==0)
{
mqttYield(1000);
if(millis()-start_tick>=10000)
timeout_flg=1;
}
if(timeout_flg)
{
Serial.println("mqtt dynamic register failed! get device password timeout!");
return FAILED_RET;
}
}
else
{
Serial.print("failed, status code =");
Serial.print(client.state());
Serial.println(" try again in 3 seconds");
/* Wait 3 seconds before retrying */
delay(3000);
retry_time--;
}
}
if(!retry_time)
{
Serial.println("mqtt dynamic register failed! retry too many times");
return FAILED_RET;
}
}
else
{
client.setCallback(uiot_info_st.user_callback);
gen_mqtt_connect_info(STATIC_AUTH);
Serial.print("MQTT static connect...");
if (client.connect(this->clientId,this->userName,this->passWord))
{
Serial.println("connected");
return 0;
}
else
{
Serial.print("failed, status code =");
Serial.print(client.state());
Serial.println(" try again in 3 seconds");
/* Wait 3 seconds before retrying */
delay(3000);
retry_time--;
}
}
}
if(!retry_time)
{
Serial.println("mqtt connect failed! retry too many times");
return FAILED_RET;
}
return SUCCESS_RET;
}
//根据四元组生成mqtt连接三要素clientID,userName以及passward
void UCloudMQTT::gen_mqtt_connect_info(int auth_mode)
{
sprintf(this->clientId,CLIENT_ID,uiot_info_st.productSn,uiot_info_st.deviceSn);
if(auth_mode==DYNAMIC_AUTH)
{
sprintf(this->userName,USER_NAME,uiot_info_st.productSn,uiot_info_st.deviceSn,2);
sprintf(passwrd_topic,PASSWRD_TOPIC,uiot_info_st.productSn,uiot_info_st.deviceSn);
sprintf(passwrd_reply_topic,PASSWORD_REPLY_TOPIC,uiot_info_st.productSn,uiot_info_st.deviceSn);
}
else
{
sprintf(this->userName,USER_NAME,uiot_info_st.productSn,uiot_info_st.deviceSn,1);
this->passWord = uiot_info_st.deviceSecret;
}
}
//返回mqtt连接的状态
boolean UCloudMQTT::mqtt_status()
{
return client.connected();
}
//mqtt延时等待消息
void UCloudMQTT::mqttYield(int time_ms)
{
long start_tick = millis();
while(millis()-start_tick<time_ms)
{
//断开则重连
if(!client.connected())
mqtt_connect();
//读取消息等
client.loop();
}
}
//发布消息
boolean UCloudMQTT::publish(const char* topic, const char* payload)
{
return client.publish(topic,payload);
}
//订阅消息
boolean UCloudMQTT::subscribe(const char* topic)
{
return client.subscribe(topic,0);
}
//析构函数
UCloudMQTT::~UCloudMQTT(void)
{
}

View File

@ -0,0 +1,55 @@
#ifndef ___UCLOUDIOTSDK_H___
#define ___UCLOUDIOTSDK_H___
#include <Arduino.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#include <Arduino_JSON.h>
#include <WiFiClientSecure.h>
#include <ssl_client.h>
//#define ENABLE_TLS
#define DYNAMIC_AUTH 1
#define STATIC_AUTH 0
#define IS_TLS 1
#define NO_TLS 0
#define FAILED_RET 1
#define SUCCESS_RET 0
typedef void (*MQTTHandlerFun)(char* topic, uint8_t* payload, unsigned int length);
typedef struct {
char productSn[20];
char deviceSn[20];
char productSecret[20];
char deviceSecret[20];
int auth_mode;
int is_tls;
MQTTHandlerFun user_callback;
}Uiot_Info_st;
class UCloudMQTT
{
public:
UCloudMQTT(char *product_sn,char *device_sn,char *product_secret,char *device_secret,MQTTHandlerFun callback);
~UCloudMQTT(void);
int mqtt_connect(void);
void mqttYield(int time_ms);
boolean mqtt_status(void);
boolean publish(const char* topic, const char* payload);
boolean subscribe(const char* topic);
private:
char clientId[40];
char userName[40];
char *passWord;
void gen_mqtt_connect_info(int auth_mode);
};
void dynamic_msg_callback(char* topic, uint8_t* payload, unsigned int length);
#endif /* ___UCLOUDIOTSDK_H___ */

View File

@ -0,0 +1,287 @@
#include "ucloud_iot_sdk_esp8266.h"
#define PASSWRD_TOPIC "/$system/%s/%s/password"
#define PASSWORD_REPLY_TOPIC "/$system/%s/%s/password_reply"
#define CLIENT_ID "%s.%s"
#define USER_NAME "%s|%s|%d"
const char* mqtt_ca_crt= \
{
"-----BEGIN CERTIFICATE-----\n" \
"MIIDsjCCApoCCQCudOie27G3QDANBgkqhkiG9w0BAQsFADCBmjELMAkGA1UEBhMC\n"
"Q04xETAPBgNVBAgMCFNoYW5naGFpMREwDwYDVQQHDAhTaGFuZ2hhaTEPMA0GA1UE\n"
"CgwGVUNsb3VkMRgwFgYDVQQLDA9VQ2xvdWQgSW9ULUNvcmUxFjAUBgNVBAMMDXd3\n"
"dy51Y2xvdWQuY24xIjAgBgkqhkiG9w0BCQEWE3Vpb3QtY29yZUB1Y2xvdWQuY24w\n"
"HhcNMTkwNzI5MTIyMDQxWhcNMzkwNzI0MTIyMDQxWjCBmjELMAkGA1UEBhMCQ04x\n"
"ETAPBgNVBAgMCFNoYW5naGFpMREwDwYDVQQHDAhTaGFuZ2hhaTEPMA0GA1UECgwG\n"
"VUNsb3VkMRgwFgYDVQQLDA9VQ2xvdWQgSW9ULUNvcmUxFjAUBgNVBAMMDXd3dy51\n"
"Y2xvdWQuY24xIjAgBgkqhkiG9w0BCQEWE3Vpb3QtY29yZUB1Y2xvdWQuY24wggEi\n"
"MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0g9bzkQBipln/nRsUKeQcwAkU\n"
"ZUk/VMWrg5AzBislYW9hujCGZHWXUknVHPSQM2Pk30tPeIdmupSkOJllYtFplI6U\n"
"6kqHpVsyPn925H5zz4uP5Ty0hkkNK+rIR/YjbEjGn8loTqWk++/o6qST5QOrZLUR\n"
"vxaWvshpce0QUcYU9xMfUPzLa6/ZfmaNHgn1aWExYMJAWDyBCyw4OxeSMUyH+ydh\n"
"egW7VHNQuVHOYdnXiC+VYImNJ8+QAyCIZ88lP0nqVPSKTt1XXmGW6vXrWSl+/XhO\n"
"GaHNMzlwb1kqlFx/ZagTQoQ0hpmqSUKtqPgKSqGPxY9go1Rda1m2rYc8k3gJAgMB\n"
"AAEwDQYJKoZIhvcNAQELBQADggEBAHU0KKqEbR7uoY1tlE+MDsfx/2zXNk9gYw44\n"
"O+xGVdbvTC298Ko4uUEwc1C+l9FaMmN/2qUPSXWsSrAYDGMS63rzaxqNuADTgmo9\n"
"QY0ITtTf0lZTkUahVSqAxzMFaaPzSfFeP9/EaUu14T5RPQbUZMVOAEPKDNmfK4rD\n"
"06R6dnO12be4Qlha14o67+ojaNtyZ7/ESePXA/RjO9YMkeQAoa4BdnsJCZgCFmXf\n"
"iKvGM+50+L/qSbH5F//byLGTO1t3TWCCdBE5/Mc/QLYEXDmZM6LMHyEAw4VuinIa\n"
"I8m1P/ceVO0RjNNBG0pDH9PH4OA7ikY81c63PBCQaYMKaiksCzs=\n"
"-----END CERTIFICATE-----\n"
};
WiFiClient espClient;
BearSSL::WiFiClientSecure espSecureClient;
BearSSL::X509List mqttcert(mqtt_ca_crt);
static PubSubClient client;
static const char* mqtt_server = "mqtt-cn-sh2.iot.ucloud.cn";
char password_string[30] = "{\"RequestID\":\"1\"}";
char passwrd_topic[100];
char passwrd_reply_topic[100];
Uiot_Info_st uiot_info_st;
//消息回调函数,收到数据之后对数据进行处理
void dynamic_msg_callback(char* topic, uint8_t* payload, unsigned int length)
{
Serial.print("Message received: ");
Serial.println(topic);
Serial.print("payload: ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
if((0 == strncmp(topic, passwrd_reply_topic, strlen(topic))) && ( uiot_info_st.auth_mode== DYNAMIC_AUTH))
{
JSONVar myObject = JSON.parse((const char *)payload);
if (myObject.hasOwnProperty("Password"))
{
strncpy(uiot_info_st.deviceSecret, myObject["Password"], strlen(myObject["Password"]));
}
if (JSON.typeof(myObject) == "Password")
Serial.print("Password received: ");
Serial.println(uiot_info_st.deviceSecret);
client.disconnect();
uiot_info_st.auth_mode = STATIC_AUTH;
}
}
//构造函数,内部对传入的四元组进行检查以及初始化四元组,传入用户回调函数
UCloudMQTT::UCloudMQTT(char *product_sn,char *device_sn,char *product_secret,char *device_secret,MQTTHandlerFun callback)
{
if(product_sn==NULL||device_sn==NULL)
Serial.println("MQTT CONSTRUCT FAILED!");
if(device_secret!=NULL)
{
uiot_info_st.auth_mode=STATIC_AUTH;
memcpy(uiot_info_st.deviceSecret,device_secret,20);
this->passWord=uiot_info_st.deviceSecret;
}
else if(product_secret!=NULL)
{
uiot_info_st.auth_mode=DYNAMIC_AUTH;
memcpy(uiot_info_st.productSecret,product_secret,20);
this->passWord=uiot_info_st.productSecret;
}
else
{
Serial.println("there is no any secret!");
}
if(callback==NULL)
{
uiot_info_st.user_callback=dynamic_msg_callback;
}
else
{
uiot_info_st.user_callback=callback;
}
#ifdef ENABLE_TLS
uiot_info_st.is_tls=IS_TLS;
#else
uiot_info_st.is_tls=NO_TLS;
#endif
memcpy(uiot_info_st.productSn,product_sn,20);
memcpy(uiot_info_st.deviceSn,device_sn,20);
}
//mqtt连接分为动态注册时的预认证和静态连接
int UCloudMQTT::mqtt_connect(void)
{
int retry_time=10;
while (!client.connected()&&retry_time)
{
if(uiot_info_st.is_tls==IS_TLS)
{
espSecureClient.setTrustAnchors(&mqttcert);
setClock();
// if no check the CA Certification
espSecureClient.setInsecure();
client.setClient(espSecureClient);
client.setServer(mqtt_server, 8883);
Serial.println("support TLS connection!");
}
else
{
client.setClient(espClient);
client.setServer(mqtt_server, 1883);
}
client.setKeepAlive(500);
Serial.print("MQTT connecting ...");
/* connect now */
if(uiot_info_st.auth_mode == DYNAMIC_AUTH)
{
client.setCallback(dynamic_msg_callback);
gen_mqtt_connect_info(DYNAMIC_AUTH);
Serial.print("MQTT dynamic register ...");
//如果是动态注册,等待预认证完成,auth_mode会在回调函数中改变
while (uiot_info_st.auth_mode==DYNAMIC_AUTH&&retry_time)
{
client.connect(this->clientId,this->userName,this->passWord);
if(mqtt_status()==true)
{
Serial.println("connected");
/* subscribe topic to get device secret */
client.subscribe(passwrd_reply_topic);
client.publish(passwrd_topic, password_string);
long start_tick = millis();
long timeout_flg=0;
while(uiot_info_st.auth_mode == DYNAMIC_AUTH&&timeout_flg==0)
{
mqttYield(1000);
if(millis()-start_tick>=10000)
timeout_flg=1;
}
if(timeout_flg)
{
Serial.println("mqtt dynamic register failed! get device password timeout!");
return FAILED_RET;
}
}
else
{
Serial.print("failed, status code =");
Serial.print(client.state());
Serial.println(" try again in 3 seconds");
/* Wait 3 seconds before retrying */
delay(3000);
retry_time--;
}
}
if(!retry_time)
{
Serial.println("mqtt dynamic register failed! retry too many times");
return FAILED_RET;
}
}
else
{
client.setCallback(uiot_info_st.user_callback);
gen_mqtt_connect_info(STATIC_AUTH);
Serial.print("MQTT static connect...");
if (client.connect(this->clientId,this->userName,this->passWord))
{
Serial.println("connected");
return 0;
}
else
{
Serial.print("failed, status code =");
Serial.print(client.state());
Serial.println(" try again in 3 seconds");
/* Wait 3 seconds before retrying */
delay(3000);
retry_time--;
}
}
}
if(!retry_time)
{
Serial.println("mqtt connect failed! retry too many times");
return FAILED_RET;
}
return SUCCESS_RET;
}
//根据四元组生成mqtt连接三要素clientID,userName以及passward
void UCloudMQTT::gen_mqtt_connect_info(int auth_mode)
{
sprintf(this->clientId,CLIENT_ID,uiot_info_st.productSn,uiot_info_st.deviceSn);
if(auth_mode==DYNAMIC_AUTH)
{
sprintf(this->userName,USER_NAME,uiot_info_st.productSn,uiot_info_st.deviceSn,2);
sprintf(passwrd_topic,PASSWRD_TOPIC,uiot_info_st.productSn,uiot_info_st.deviceSn);
sprintf(passwrd_reply_topic,PASSWORD_REPLY_TOPIC,uiot_info_st.productSn,uiot_info_st.deviceSn);
}
else
{
sprintf(this->userName,USER_NAME,uiot_info_st.productSn,uiot_info_st.deviceSn,1);
this->passWord = uiot_info_st.deviceSecret;
}
}
// Set time via NTP, as required for x.509 validation
void UCloudMQTT::setClock()
{
configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");
Serial.print("Waiting for NTP time sync: ");
time_t now = time(nullptr);
while (now < 8 * 3600 * 2)
{
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println("");
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
Serial.print("Current time: ");
Serial.print(asctime(&timeinfo));
}
//返回mqtt连接的状态
boolean UCloudMQTT::mqtt_status()
{
return client.connected();
}
//mqtt延时等待消息
void UCloudMQTT::mqttYield(int time_ms)
{
long start_tick = millis();
while(millis()-start_tick<time_ms)
{
//断开则重连
if(!client.connected())
mqtt_connect();
//读取消息等
client.loop();
}
}
//发布消息
boolean UCloudMQTT::publish(const char* topic, const char* payload)
{
return client.publish(topic,payload);
}
//订阅消息
boolean UCloudMQTT::subscribe(const char* topic)
{
return client.subscribe(topic,0);
}
//析构函数
UCloudMQTT::~UCloudMQTT(void)
{
}

View File

@ -0,0 +1,60 @@
#ifndef ___UCLOUDIOTSDK_H___
#define ___UCLOUDIOTSDK_H___
#include <Arduino.h>
#include <WiFiClient.h>
#include <WiFiClientSecure.h>
#include <time.h>
#include <Arduino_JSON.h>
#include <PubSubClient.h>
//#define ENABLE_TLS
#define DYNAMIC_AUTH 1
#define STATIC_AUTH 0
#define IS_TLS 1
#define NO_TLS 0
#define FAILED_RET 1
#define SUCCESS_RET 0
typedef void (*MQTTHandlerFun)(char* topic, uint8_t* payload, unsigned int length);
typedef struct {
char productSn[20];
char deviceSn[20];
char productSecret[20];
char deviceSecret[20];
int auth_mode;
int is_tls;
MQTTHandlerFun user_callback;
}Uiot_Info_st;
class UCloudMQTT
{
public:
UCloudMQTT(char *product_sn,char *device_sn,char *product_secret,char *device_secret,MQTTHandlerFun callback);
~UCloudMQTT(void);
int mqtt_connect(void);
void mqttYield(int time_ms);
boolean mqtt_status(void);
boolean publish(const char* topic, const char* payload);
boolean subscribe(const char* topic);
private:
char clientId[40];
char userName[40];
char *passWord;
void gen_mqtt_connect_info(int auth_mode);
void setClock();
};
void dynamic_msg_callback(char* topic, uint8_t* payload, unsigned int length);
#endif /* ___UCLOUDIOTSDK_H___ */