赞
踩
本文介绍如何使用esp8266+MQTT协议,从硬件的角度如何上云,并将数据采集-发送到阿里云后台。
完整项目介绍:https://blog.csdn.net/feit2417/article/details/86671932
码云(获取源码):https://gitee.com/hinzer/temp_hum_system
阿里Link 设备端SDK iotkit-embedded-2.3.0
我们使用基于TCP的MQTT协议来连接阿里云Link平台,需要遵循Alink协议规范,对阿里C-SDK进行移植到ESP8266
下面来介绍一下移植过程。
1.使用ESP8266-sdk目录下examples/mqtt_demo,以此为模板。放置在根目录下。
2.修改项目目录下的·gen_misc.sh·和·Makefile·文件,
- export SDK_PATH=$/mnt/hgfs/sharefolder-esp8266/ESP8266_RTOS_SDK-2.0.0 //SDK根目录
- export BIN_PATH=$/mnt/hgfs/sharefolder-esp8266/ESP8266_RTOS_SDK-2.0.0/bin //输出bin文件目录
- parent_dir:=$(abspath $(shell pwd)/$(lastword $(MAKEFILE_LIST)))
- parent_dir:=$(shell dirname $(parent_dir))
- parent_dir:=$(shell dirname $(parent_dir))
-
- SDK_PATH= $(parent_dir)
- BIN_PATH=$(SDK_PATH)/bin
3.编译项目,没有问题
使用MQTT-TCP连接Link平台,需要mqttClientId、mqttUsername、mqttPassword这三个参数认证。但是这些参数并不是直接提供给我们的,需要使用加密机制来对三元组数据生成。
1.找到Link-SDK中的utils\digest目录,复制.c和.h文件到工程目录下
2.清除不必要的头文件包含,去除log_err函数(如果有的话)
3.每个.h文件中,包涵
- #include "esp_common.h"
- #include "iot_export_errno.h"
4.编译,直到无错误
OK,基本移植完成了。
实现设备连接到云平台
参考官方文档:https://help.aliyun.com/document_detail/73742.html?spm=a2c4g.11186623.6.644.44a53f86Ed7mht
1.在`user_config.h`中修改wifi信息,和MQTT代理服务器地址
- #define SSID "espressif" /* Wi-Fi SSID */
- #define PASSWORD "1234567890" /* Wi-Fi Password */
-
- #define MQTT_BROKER "a1u8k40ci7d.iot-as-mqtt.cn-shanghai.aliyuncs.com" /* 代理服务地址,参考官方文档*/
- #define MQTT_PORT 1883 /* MQTT Port*/
2.`MQTTEcho.c`中修改配置
- //设备信息
- char *clientId = "你的设备id";
- char *timestamp = "789";
- char *deviceName = "你的设备名";
- char *productKey = "产品key值";
- char *devicesecret = "设备secret值";
-
- //mqtt连接信息
- char mqttClientId[100];
- char mqttUsername[100];
- char mqttPassword[100];
- char hmac_source[512];
3.获取mqttClientId、mqttUsername、mqttPassword这三个参数认证
- void GetmqttClientId(void)
- {//获取mqttClientId
- sprintf(mqttClientId,"%s|securemode=3,signmethod=hmacsha1,timestamp=%s|",clientId,timestamp);
- printf("%s\r\n",mqttClientId);
- }
- void GetmqttUsername(void)
- {//获取mqttUsername
- sprintf(mqttUsername,"%s&%s",deviceName,productKey);
- printf("%s\r\n",mqttUsername);
- }
- void GetmqttPassword(void)
- {//获取mqttPassword
- sprintf(hmac_source,
- "clientId%s" "deviceName%s" "productKey%s" "timestamp%s",
- clientId,deviceName,productKey,timestamp);
- utils_hmac_sha1(hmac_source,strlen(hmac_source),
- mqttPassword,devicesecret,strlen(devicesecret));
- printf("%s\r\n",mqttPassword);
- }
4.在线程`mqtt_client_thread`中,进行参数获取,并进行认证
- GetmqttClientId();
- GetmqttUsername();
- GetmqttPassword();
- //GetMqttTopicPropertyPost();
- //GetMqttTopicPropertyPostReply();
- connectData.clientID.cstring = mqttClientId;
- connectData.username.cstring = mqttUsername;
- connectData.password.cstring = mqttPassword;
- connectData.MQTTVersion = 4; //mqtt v3.1
-
- if ((rc = MQTTConnect(&client, &connectData)) != 0) {
- printf("Return code from MQTT connect is %d\n", rc);
- } else {
- printf("MQTT Connected\n");
- }
-
- vTaskDelete(NULL);
- return;
ps:需要修改sendbuf和readbuf的缓冲大小为300
5.再修改工程目录下Makefile文件。
- #CONFIGURATION_DEFINES = -DICACHE_FLASH -DMQTT_TASK
- CONFIGURATION_DEFINES = -DICACHE_FLASH
6.编译程序,直至成功
现在设备可以连接到阿里云了
设备通过MQTT协议,发布订阅的方式与平台进行交互。Alink协议采用json格式,需要cJSON库对采集到的数据进行封装。数据采集部分使用dht11完成温度、湿度的采集,这里使用现成的函数库。
1.从ESP8266 SDK 目录中`driver_lib/`,添加库文件到工程目录
2.修改Makefile
- SUBDIRS= \
- user \
- driver
-
- COMPONENTS_eagle.app.v6 = \
- user/libuser.a \
- driver/libdriver.a
3.修改工程
封装信息
- //封装发布主题(上报数据)和订阅主题(订阅发布响应)
- #define TOPIC_PROPERTY_POST "/sys/%s/%s/thing/event/property/post"
- #define TOPIC_PROPERTY_POST_REPLY "/sys/%s/%s/thing/event/property/post_reply"
-
- //对数据的jison格式进行封装
- #define DATAPAYLOAD "{\r\n\"id\" : \"1123\",\r\n\"version\":\"1.0\",\r\n\"params\" : {\r\n\"tempture\": %d,\r\n\"humidity\": %d,\r\n},\r\n\"method\":\"thing.event.property.post\"\r\n}"
mqtt_client线程中进行每10s一次主题上报
- static void mqtt_client_thread(void* pvParameters)
- {
- printf("mqtt client thread starts\n");
- MQTTClient client;
- Network network;
- unsigned char sendbuf[300], readbuf[300] = {0};
- int rc = 0, count = 0;
- MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;
-
- pvParameters = 0;
- NetworkInit(&network);
- MQTTClientInit(&client, &network, 30000, sendbuf, sizeof(sendbuf), readbuf, sizeof(readbuf));
-
- char* address = MQTT_BROKER;
- printf("address = %s\r\n",address);
-
- if ((rc = NetworkConnect(&network, address, MQTT_PORT)) != 0) {
- printf("Return code from network connect is %d\n", rc);
- }
-
- #if defined(MQTT_TASK)
-
- if ((rc = MQTTStartTask(&client)) != pdPASS) {
- printf("Return code from start tasks is %d\n", rc);
- } else {
- printf("Use MQTTStartTask\n");
- }
-
-
- #endif
- GetmqttClientId();
- GetmqttUsername();
- GetmqttPassword();
- GetMqttTopicPropertyPost();
- GetMqttTopicPropertyPostReply();
- connectData.clientID.cstring = mqttClientId;
- connectData.username.cstring = mqttUsername;
- connectData.password.cstring = mqttPassword;
- connectData.MQTTVersion = 4; //mqtt v3.1
-
- printf("connectData.struct_id = %s\r\n",connectData.struct_id);
- printf("connectData.struct_version = %d\r\n",connectData.struct_version);
- printf("connectData.MQTTVersion = %d\r\n",connectData.MQTTVersion);
- printf("connectData.clientID = %s\r\n",connectData.clientID.cstring);
- printf("connectData.keepAliveInterval = %d\r\n",connectData.keepAliveInterval);
- printf("connectData.cleansession = %d\r\n",connectData.cleansession);
- printf("connectData.willFlag = %d\r\n",connectData.willFlag);
- printf("connectData.username = %s\r\n",connectData.username.cstring);
- printf("connectData.password = %s\r\n",connectData.password.cstring);
-
- if ((rc = MQTTConnect(&client, &connectData)) != 0) {
- printf("Return code from MQTT connect is %d\n", rc);
- } else {
- printf("MQTT Connected\n");
- }
-
-
- //订阅主题响应...
- if ((rc = MQTTSubscribe(&client, MqttTopicPropertyPostReply, 2, messageArrived)) != 0) {
- printf("Return code from MQTT subscribe is %d\n", rc);
- } else {
- printf("MQTT subscribe to topic %s\n",MqttTopicPropertyPostReply);
- }
-
- while (++count) {
- GetJsonData(); //获取jison对象
- MQTTMessage message;
-
- message.qos = QOS0;
- message.retained = 0;
- message.payload = JsonDataPayLoad;
- printf("JSON is %s\r\n",message.payload);
- message.payloadlen = strlen(JsonDataPayLoad);
-
- //发布数据主题
- if ((rc = MQTTPublish(&client, MqttTopicPropertyPost, &message)) != 0) {
- printf("Return code from MQTT publish is %d\n", rc);
- } else {
- printf("MQTT publish topic %s, message is %s\n",MqttTopicPropertyPost,message.payload);
- }
- //等待应答主题
- MQTTYield(&client,200);
- //定时10s发送
- vTaskDelay(10000 / portTICK_RATE_MS); //send every 10 seconds
-
- }
-
- printf("mqtt_client_thread going to be deleted\n");
- vTaskDelete(NULL);
- return;
- }
编译后的bin文件烧写到设备,运行
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。