> 技术文档 > (代码易懂实现)新stm32+esp8266/01s+dht11+mqtt onenet上报温湿度和远程控制——STM32代码实现篇_stm32 (hal库) 新版onenet

(代码易懂实现)新stm32+esp8266/01s+dht11+mqtt onenet上报温湿度和远程控制——STM32代码实现篇_stm32 (hal库) 新版onenet

(代码易懂实现)新stm32+esp8266/01s+dht11+mqtt onenet上报温湿度和远程控制——STM32代码实现篇_stm32 (hal库) 新版onenet

 

(代码完美实现)stm32 + 新版 onenet + mqtt物联网(保姆级教程)
地址:↓↓👇👇👇👇👇👇👇👇👇👇👇👇👇

(代码完美实现)stm32 + 新版 onenet + mqtt物联网(保姆级教程) https://blog.csdn.net/Wang2869902214/article/details/142501323

注                👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆

STM32代码实现

注:代码和文章内容创作不易,使用或分享代码时请标注来源

读者们也可以加入STM32链接OneNET的群聊 自助获取资料,交流一些遇到的问题也可以互相探讨:        自助获取资料  Q:983362248

最终效果

第一个视频:详细展示STM32上电后初始化ESP8266链接OneNET MQTT设备,再进行订阅操作,发送DHT11温湿度数据和接收数据

(已验证,完美实现)stm32+esp8266连接新版onenet上报与下发数据

微信小程序 :温湿度数据上报,数据下发控制单片机

微信小程序stm32+esp8266+onenet显示温湿度和控制单片机

 

读者们也可以加入STM32链接OneNET的群聊 自助获取资料,交流一些遇到的问题也可以互相探讨:           自助获取资料     Q:983362248 

开启本章节需要完成下方的前置任务:
点击跳转:

 

物联网实践教程:微信小程序结合OneNET平台MQTT实现STM32单片机远程智能控制 远程上报和接收数据——汇总 https://blog.csdn.net/Wang2869902214/article/details/142501323

目标

1.连接OneNET:STM32使用串口与ESP8266/01s连接发送AT指令连接上OneNET MQTT设备

2.数据上报OneNET:将STM32采集的数据上传到OneNET

3.接收OneNET下发数据:STM32接收OneNET下发的指令并进行对应的操作

 

代码主要逻辑

 

无线模块状态结构体
 

typedef struct { uint8_t receiveDataFlag;//接收数据标志位 uint8_t sendDataFlag;//发送数据标志位uint8_t wirelessInitFlag;//无线模块初始化完成标志位 uint16_t wirelessInitErrorCode;//无线模块初始化错误代码}Wireless_TypeDef;extern Wireless_TypeDef WirelessStatus;

无线模块连接OneNET MQTT设备需要发送的AT指令

全部使用宏定义,方便其他的用户直接修改设备等相关信息即可直接使用

#include \"wireless.h\"/** *CSDN文章:(代码完美实现)stm32 + 新版 onenet + mqtt物联网(保姆级教程) *CSDN博主:送外卖的CV工程师 *版权声明:本文件为博主原创代码,遵循 CC 4.0 BY-SA 版权协议,转载使用请附上原代码出处和本声明。 *本文博客链接:https://blog.csdn.net/Wang2869902214/article/details/142501323 *gitee地址: https://gitee.com/Wang2869902214/stm32-onenet-mqtt.git *更新日期:2024-9-25 *QQ群聊:STM连接onenet交流群983362248 *所需资料全部可以在群里下载 */ /*********代码中包含大量的【调试】语句,可以打开或者屏蔽查看运行状态*********//*只需更新这些信息*/#define ControlEnable 0 //是否使用OneNET下发数据,【如需使用则置 1 并添加Keil.Jansson库 ps:可以进群查看】#define JsonSendEnable 0 //是否使用json组装数据,需要在启动文件中设置更大的堆内存 【如需使用则置 1 并添加Keil.Jansson库 ps:可以进群查看】Wireless_TypeDef WirelessStatus = {0, 0, 0, 0};#define WIFI_SSID \"207\"//WIFI用户名#define WIFI_PASSWORD \"12345678\"//WIFI密码#define ONENET_MQTT_PRODUCT_ID \"YqRZ5hrM6p\"//OneNET MQTT产品ID#define ONENET_MQTT_DEVICE_NAME \"CSDN\"//OneNET MQTT设备名称#define ONENET_MQTT_TOKEN \"version=2018-10-31&res=products%2FYqRZ5hrM6p%2Fdevices%2FCSDN&et=2028715245&method=md5&sign=G4I0xqIYmYUtCdTTo2t%2FqQ%3D%3D\"//token#if JsonSendEnable#include \"jansson.h\"#endif#if ControlEnable#include \"jansson.h\"#define ONENET_MQTT_CMD_IDENTIFIER \"cmd\"//OneNET MQTT命令标识符#endifconst char *floatIdentifiers[] = {\"temp\", \"humi\"};//修改自己设备中的属性标识符float floatValues[] = {0, 0};//对应上方数组下标的数据const char *stringIdentifiers[] = {0};const char *stringValues[] = {0};/*只需更新这些信息*/#define WIRELESS_WIFI_INFO \"AT+CWJAP=\\\"\" WIFI_SSID \"\\\",\\\"\" WIFI_PASSWORD \"\\\"\\r\\n\"#define WIRELESS_RECEIVE_CMD \"\\\"\" ONENET_MQTT_CMD_IDENTIFIER \"\\\":\"#define ONENET_MQTT_SERVER_INFO \"AT+MQTTCONN=0,\\\"mqtts.heclouds.com\\\",1883,1\\r\\n\"#define ONENET_MQTT_USERCFG_INFO \"AT+MQTTUSERCFG=0,1,\\\"\" ONENET_MQTT_DEVICE_NAME \"\\\",\\\"\" ONENET_MQTT_PRODUCT_ID \"\\\",\\\"\" ONENET_MQTT_TOKEN \"\\\",0,0,\\\"\\\"\\r\\n\"#define ONENET_MQTT_SET_TOPIC \"AT+MQTTSUB=0,\\\"$sys/\" ONENET_MQTT_PRODUCT_ID \"/\" ONENET_MQTT_DEVICE_NAME \"/thing/property/set\\\",0\\r\\n\"#if JsonSendEnable#if ControlEnable#define ONENET_MQTT_SET_MQTTPUBRAW \"AT+MQTTPUBRAW=0,\\\"$sys/\" ONENET_MQTT_PRODUCT_ID \"/\" ONENET_MQTT_DEVICE_NAME \"/thing/property/set_reply\\\"\"#endif#define ONENET_MQTT_PUB_MQTTPUBRAW \"AT+MQTTPUBRAW=0,\\\"$sys/\" ONENET_MQTT_PRODUCT_ID \"/\" ONENET_MQTT_DEVICE_NAME \"/thing/property/post\\\"\"#else#if ControlEnable#define ONENET_MQTT_PUB_SET \"AT+MQTTPUB=0,\\\"$sys/\" ONENET_MQTT_PRODUCT_ID \"/\" ONENET_MQTT_DEVICE_NAME \"/thing/property/set_reply\\\"\"#endif#define ONENET_MQTT_PUBTOPIC \"AT+MQTTPUB=0,\\\"$sys/\" ONENET_MQTT_PRODUCT_ID \"/\" ONENET_MQTT_DEVICE_NAME \"/thing/property/post\\\"\"#endif

1.初始化

由前置任务可以知道,每次发送AT指令后,无线模块总是会回应我们,例如“OK”又或者其他的内容,这里初始化发送的每条AT指令都必须要得到无线模块的回应,这样防止无线模块未按照预期模式运行,如果初始化出现错误时,需要即使去处理对应的问题

这里如果不了解为什么要这样写代码的逻辑,放个传送门:
物联网实践教程:微信小程序结合OneNET平台MQTT实现STM32单片机远程智能控制 远程上报和接收数据——ESP8266/01s AT指令连接OneNET MQTT篇
 

/** * @简要 无线模块初始化函数 * @参数 无 * @注意事项 如果函数初始化失败,会进入错误函数 * @返回值 无 */void Wireless_Init(void){const uint8_t sendDataCount = 10; printf(\"\\r\\nStart MQTT service\\r\\n\");printf(\"1. AT+RST\\r\\n\"); //需要延迟最少500ms,否则下一句指令发送无效if(Wireless_Send_Command(\"AT+RST\\r\\n\\r\\n\", \"\", sendDataCount) == 1) WirelessStatus.wirelessInitErrorCode |= 1 << 0;HAL_Delay(500);printf(\"2. ATE0\\r\\n\");//关闭回显if(Wireless_Send_Command(\"ATE0\\r\\n\", \"OK\", sendDataCount) == 1)WirelessStatus.wirelessInitErrorCode |= 1 << 1;HAL_Delay(100);printf(\"3. AT+CWAUTOCONN=0\\r\\n\");//上电不自动连接 APif(Wireless_Send_Command(\"AT+CWAUTOCONN=0\\r\\n\", \"OK\", sendDataCount) == 1) WirelessStatus.wirelessInitErrorCode |= 1 << 2;HAL_Delay(100);printf(\"4. AT+CWMODE=1\\r\\n\");//设置 Station 模式if(Wireless_Send_Command(\"AT+CWMODE=1\\r\\n\", \"OK\", sendDataCount) == 1)WirelessStatus.wirelessInitErrorCode |= 1 << 3;HAL_Delay(100);printf(\"5. AT+CWDHCP=1,0\\r\\n\");//启用DHCPif(Wireless_Send_Command(\"AT+CWDHCP=1,0\\r\\n\", \"OK\", sendDataCount) == 1)WirelessStatus.wirelessInitErrorCode |= 1 << 4;HAL_Delay(100);printf(\"6. AT+CWJAP=\\\"%s\\\",\\\"%s\\\"\\r\\n\", WIFI_SSID, WIFI_PASSWORD);//连接APif(Wireless_Send_Command(WIRELESS_WIFI_INFO, \"GOT IP\", 8) == 1) WirelessStatus.wirelessInitErrorCode |= 1 << 5;HAL_Delay(100);printf(\"7. ESP8266_USERCFG_INFO=%s\\r\\n\", ONENET_MQTT_USERCFG_INFO); //设置 MQTT 用户属性if(Wireless_Send_Command(ONENET_MQTT_USERCFG_INFO, \"OK\", sendDataCount) == 1)WirelessStatus.wirelessInitErrorCode |= 1 << 6;HAL_Delay(100);printf(\"8. ESP8266_ONENET_INFO=%s\\r\\n\",ONENET_MQTT_SERVER_INFO); //连接 MQTT Brokerif(Wireless_Send_Command(ONENET_MQTT_SERVER_INFO, \"OK\", sendDataCount) == 1) WirelessStatus.wirelessInitErrorCode |= 1 << 7;HAL_Delay(100);printf(\"9. SET_TOPIC=%s\\r\\n\",ONENET_MQTT_SET_TOPIC);//设置 MQTT 用户属性if(Wireless_Send_Command(ONENET_MQTT_SET_TOPIC, \"OK\", sendDataCount) == 1) WirelessStatus.wirelessInitErrorCode |= 1 << 8;HAL_Delay(100);if(WirelessStatus.wirelessInitErrorCode == 0) {WirelessStatus.wirelessInitFlag = 1;printf(\"MQTT service started successfully\\r\\n\");}else {WirelessStatus.wirelessInitFlag = 0;printf(\"MQTT service failed to start,ERROR CODE:%X\\r\\n\", WirelessStatus.wirelessInitErrorCode);Wireless_Error_Handler(WirelessStatus.wirelessInitErrorCode); //错误处理函数}}

 在上方代码中:

if(Wireless_Send_Command(\"AT+RST\\r\\n\\r\\n\", \"\", sendDataCount) == 1)

这个函数原型:
 

/** * @简要 无线模块发送指令并且等待回应数据 * @参数 cmd:需要发送的指令字符串地址 * @参数 res:需要回应的指令 * @参数 sendCount:最大发送指令次数 * @返回值 无 */uint8_t Wireless_Send_Command(char *cmd, char *res, uint8_t sendCount){uint8_t status = 1;while(sendCount--){Wireless_Usart_Send(cmd);//printf(\"cmd :%s\",cmd);if(WirelessStatus.receiveDataFlag == 1){if(strstr((const char *)WirelessRx.RxBuffer, res) != NULL)//若找到关键字{status = 0;WirelessStatus.receiveDataFlag = 0;Wireless_Buffer_Clear();break;}Wireless_Buffer_Clear();WirelessStatus.receiveDataFlag = 0;}HAL_Delay(200);}return status;}

这里还需要修改明白一个底层的发送函数:

需要将里面的串口发送修改为自己的
这里面的DMA配置也有文章可以参考:
STM32基于HAL库使用串口+DMA 不定长接收数据 学习记录

/** * @简要 用来适配无线模块发送字符的函数 * @参数 cmd: 传入需要发送字符指针 * @返回值 无 */void Wireless_Usart_Send(char *cmd){ if (cmd == NULL) return; // 确保指针不为空 // 发送字符串 // 参数依次为:USART句柄指针、发送数据缓冲区指针、数据字节长度HAL_UART_Transmit_DMA(&huart2, (uint8_t *)cmd, strlen(cmd));}

串口接收采用了DMA空闲接收回调函数处理(可以参考上方连接配置):

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){ if (huart->Instance == USART1) { Uart1Rx.RxDataCnt = RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);if(Uart1Rx.RxBuffer[Uart1Rx.RxDataCnt - 2] == \'\\r\' && Uart1Rx.RxBuffer[Uart1Rx.RxDataCnt - 1] == \'\\n\'){HAL_UART_Transmit_DMA(&huart1, Uart1Rx.RxBuffer, Uart1Rx.RxDataCnt);} }if (huart->Instance == USART2) { WirelessRx.RxDataCnt = RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);if(WirelessRx.RxBuffer[WirelessRx.RxDataCnt - 2] == \'\\r\' && WirelessRx.RxBuffer[WirelessRx.RxDataCnt - 1] == \'\\n\'){WirelessStatus.receiveDataFlag = 1;if(WirelessStatus.wirelessInitFlag == 1) printf(\"Receive\\r\\n\");//HAL_UART_Transmit_DMA(&huart1, WirelessRx.RxBuffer, WirelessRx.RxDataCnt);} }}

 

2.上报数据

这里开启了一个定时器,用一个LED灯去显示当前wifi模块状态,同时也在后台计时,准备设置发送数据标志位

这个定时器的存在只是为了加强用户交互,显示当前WiFi模块的工作状态,例如连接OneNET初始化失败,正在连接,成功连接等等,如果不需要的话完全可以删除,然后发送计时可以在主函数用一个变量累加到一定数量时触发发送

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){static uint16_t countTimer_SendData_OneNET = 0;static uint16_t countTimer_LED_Toggle = 0; if (htim == (&htim1)) { if(countTimer_SendData_OneNET++ > 4000) { countTimer_SendData_OneNET = 0; WirelessStatus.sendDataFlag = 1; } if(countTimer_LED_Toggle++ >= 1000) { countTimer_LED_Toggle = 0;if(WirelessStatus.wirelessInitErrorCode == 0 && WirelessStatus.wirelessInitFlag == 0)HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); //正在初始化else if(WirelessStatus.wirelessInitErrorCode == 0 && WirelessStatus.wirelessInitFlag == 1)HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);//初始化成功else if(WirelessStatus.wirelessInitErrorCode != 0)HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);//初始化失败 } }}

这里是整个无线模块的运行函数

/** * @简要 无线模块运行函数 * @参数 无 * @注意事项一直轮询,可以设置为定时触发,但是回应下发的数据会变慢 * @返回值 无 */void Wireless_Loop(void){if(WirelessStatus.receiveDataFlag == 1){WirelessStatus.receiveDataFlag = 0;//清除接收数据标志位Wireless_Receive_Command_Respond((char *)WirelessRx.RxBuffer);//接收到指令后进行回应操作Wireless_Buffer_Clear(); //执行完接收数据的所有操作后再清除缓存}else if(WirelessStatus.sendDataFlag == 1 && WirelessStatus.wirelessInitFlag == 1) {WirelessStatus.sendDataFlag = 0;//清除发送数据标志位Wireless_Publish_Data(2, floatIdentifiers, floatValues, 0, stringIdentifiers, stringValues);//上报数据}}

这里代码是放在主函数的while循环中一直执行

在这个代码中可以看到,上报数据和接收数据是互斥的,接收数据处理优先级比发送大,这里这样互斥处理的原因是:如果在wifi模块正在接收OneNET下发的数据时,又正好发送数据,无线模块接收的数据通过串口发送到STM32中,数据中可能会连带两种状态的数据(1:OneNET下发的数据,2:STM32上报数据时发送的AT指令的应答)这样解析接收的数据时出错率会大大提升

 

上报数据的核心代码:

这里代码逻辑不清楚可以参考下方两个文章:

这两个文章中有说明需要发送的数据json格式和数据类型

物联网实践教程:微信小程序结合OneNET平台MQTT实现STM32单片机远程智能控制 远程上报和接收数据——ESP8266/01s AT指令连接OneNET MQTT篇

OneNET官方文档:MQTT协议接入 最佳实践

手动拼装json格式数据

/** * @简要 无线模块上报数据 * @参数 floatCount:需要发送的float数据个数 * @参数 *floatIdentifiers[]:float标识符数组 * @参数 floatValues[]:float数据数组 * @参数 stringCount:需要发送的string数据个数 * @参数 *stringIdentifiers[]:string标识符数组 * @参数 const char *stringValues[]:string数据数组 * @注意事项这里需要二重转义:第一次转义字符是软件上字符串要求格式,第二次是因为AT指令发送字符串,需要再转义一次,故不方便使用json组装数据 * @返回值 无 */void Wireless_Publish_Data(unsigned char floatCount, const char *floatIdentifiers[], float floatValues[], unsigned char stringCount, const char *stringIdentifiers[], const char *stringValues[]) { // 初始化缓冲区位置 size_t bufferPos = 0; const uint8_t BUFFER_SIZE = 255;char globalBuffer[BUFFER_SIZE];// 拼接主题和JSON开头 bufferPos += snprintf(globalBuffer + bufferPos, BUFFER_SIZE - bufferPos, \"%s,\\\"{\\\\\\\"id\\\\\\\":\\\\\\\"123\\\\\\\"\\\\,\\\\\\\"params\\\\\\\":{\", PUBTOPIC); // 处理浮点数数据 for (unsigned char i = 0; i < floatCount; ++i) { bufferPos += snprintf(globalBuffer + bufferPos, BUFFER_SIZE - bufferPos, \"\\\\\\\"%s\\\\\\\":{\\\\\\\"value\\\\\\\":%.2f\\\\}%s\", floatIdentifiers[i], floatValues[i], (i  0) ? \"\\\\,\" : \"\"); } // 处理字符串数据 for (unsigned char i = 0; i < stringCount; ++i) { bufferPos += snprintf(globalBuffer + bufferPos, BUFFER_SIZE - bufferPos, \"\\\\\\\"%s\\\\\\\":{\\\\\\\"value\\\\\\\":\\\\\\\"%s\\\\\\\"\\\\}%s\", stringIdentifiers[i], stringValues[i], (i = BUFFER_SIZE) { // 处理错误,例如通过日志记录 return; } Wireless_Send_Command(globalBuffer,\"OK\",1);}

使用keil.Jansson库组装

需要注意使用jansson需要调大启动文件中的堆空间大小(方法可参考下方链接中)

这里放个keil.Jansson使用方法:

STM32在Keil5中利用Jansson库处理和组装JSON数据【详细版】

/** * @简要 无线模块上报数据 * @参数 floatCount:需要发送的float数据个数 * @参数 *floatIdentifiers[]:float标识符数组 * @参数 floatValues[]:float数据数组 * @参数 stringCount:需要发送的string数据个数 * @参数 *stringIdentifiers[]:string标识符数组 * @参数 const char *stringValues[]:string数据数组 * @注意事项这里使用json组装,需要动态分配大量的内容,需要将堆大小设置最小0x600 * @返回值 无 */void Wireless_Publish_Data(unsigned char floatCount, const char *floatIdentifiers[], float floatValues[], unsigned char stringCount, const char *stringIdentifiers[], const char *stringValues[]) { json_t *root, *id_obj, *version_obj, *params_obj; char *json_str; size_t json_str_len; // 创建JSON对象 root = json_object(); id_obj = json_string(\"123\"); version_obj = json_string(\"1.0\"); params_obj = json_object(); // 添加id和version到root对象 json_object_set_new(root, \"id\", id_obj); json_object_set_new(root, \"version\", version_obj); // 添加浮点数数据到params对象 for (unsigned char i = 0; i < floatCount; ++i) { json_t *float_val_obj = json_object(); json_object_set_new(float_val_obj, \"value\", json_real(floatValues[i])); json_object_set_new(params_obj, floatIdentifiers[i], float_val_obj); } // 添加字符串数据到params对象 for (unsigned char i = 0; i < stringCount; ++i) { json_t *string_val_obj = json_object(); json_object_set_new(string_val_obj, \"value\", json_string(stringValues[i])); json_object_set_new(params_obj, stringIdentifiers[i], string_val_obj); } // 将params对象添加到root对象 json_object_set_new(root, \"params\", params_obj); // 将JSON对象转换为字符串 json_str = json_dumps(root, JSON_INDENT(0) | JSON_REAL_PRECISION(4)); json_str_len = strlen(json_str); // printf(\"json_str = %s\\r\\n\",json_str);// 为MQTT发布准备最终的消息字符串 char globalBuffer[256]; // 确保缓冲区足够大 snprintf(globalBuffer, sizeof(globalBuffer), \"%s,%d,0,0\\r\\n\", ONENET_MQTT_PUB_MQTTPUBRAW, json_str_len + 2); //添加\\r\\n的长度// 发送命令 Wireless_Send_Command(globalBuffer, \"OK\", 1); strcat(json_str, \"\\r\\n\");printf(\"%s%s\",globalBuffer, json_str);Wireless_Send_Command(json_str, \"+MQTTPUB:OK\", 1); // 释放JSON对象 json_decref(root); free(json_str); // 注意:json_dumps分配的内存需要手动释放 } 

该函数使用示例:

Wireless_Publish_Data(2, floatIdentifiers, floatValues, 0, stringIdentifiers, stringValues);//代表发送两个浮点数据,0个字符串数据

 

 

3.接收OneNET下发的指令数据

这里下发数据部分可以查看该文章:

物联网实践教程:微信小程序结合OneNET平台MQTT实现STM32单片机远程智能控制 远程上报和接收数据——ESP8266/01s AT指令连接OneNET MQTT篇

在OneNET的API调试:物模型设置:设备属性设置,填入对应的json格式数据和参数
如果上文宏定义中的命令标识符是什么,那么OneNET API调试中就应该填写对应的

这是串口接收函数

if (huart->Instance == USART2) { WirelessRx.RxDataCnt = RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);if(WirelessRx.RxBuffer[WirelessRx.RxDataCnt - 2] == \'\\r\' && WirelessRx.RxBuffer[WirelessRx.RxDataCnt - 1] == \'\\n\'){WirelessStatus.receiveDataFlag = 1;if(WirelessStatus.wirelessInitFlag == 1) printf(\"Receive\\r\\n\");//HAL_UART_Transmit_DMA(&huart1, WirelessRx.RxBuffer, WirelessRx.RxDataCnt);} }

这里可以看出,如果wifi模块接收到OneNET下发的数据后,接收标志位会被置1,这里不影响无线模块函数初始化

这里是整个无线模块的运行函数

/** * @简要 无线模块运行函数 * @作者 [CSDN:送外卖的CV工程师,博客地址:https://blog.csdn.net/Wang2869902214/article/details/142501323] * @参数 无 * @注意事项一直轮询,可以设置为定时触发,但是回应下发的数据会变慢 * @返回值 无 */void Wireless_Loop(void){if(WirelessStatus.receiveDataFlag == 1){WirelessStatus.receiveDataFlag = 0;//清除接收数据标志位Wireless_Receive_Command_Respond((char *)WirelessRx.RxBuffer);//接收到指令后进行回应操作Wireless_Buffer_Clear(); //执行完接收数据的所有操作后再清除缓存}else if(WirelessStatus.sendDataFlag == 1 && WirelessStatus.wirelessInitFlag == 1) {DHT11_Read_Data();//读取DHT11的数据floatValues[0] = DHT11_Get_Temp(); printf(\"tmep:%.1f\\r\\n\",floatValues[0]);//赋值floatValues[1] = DHT11_Get_Humi(); printf(\"humi:%.1f\\r\\n\",floatValues[1]);//赋值WirelessStatus.sendDataFlag = 0;//清除发送数据标志位Wireless_Publish_Data(2, floatIdentifiers, floatValues, 0, stringIdentifiers, stringValues);//上报数据}}

这里代码是放在主函数的while循环中一直执行

可以看出如果接受标志位被置1后,会执行这个函数

/** * @简要 无线模块接收到下发的数据后进行回应 * @参数 str:无线模块接收到的数据 * @注意事项这里判断下发的指令中是否包含关键字: \"+MQTTSUBRECV\"里面的printf可以打印接收到的数据和转换后的数据 * @返回值 无 */void Wireless_Receive_Command_Respond(const char * str){char *jsonData;char id[5] = {0};int command = 0;if(strstr(str, \"+MQTTSUBRECV\") != NULL)//利用AT指令的特性去判断接受的内容是否包含关键字以验证数据来源 {//printf(\"str = %s\",str);//【调试】jsonData = strchr((const char*)str, \'{\');//提取json格式数据,通常是以 “{”开始 以“}”结尾//printf(\"jsonData = %s\",jsonData);//【调试】Remove_Trailing_Crlf(jsonData);//这里需要去除末尾的换行回车符Wireless_Extract_Receive_Command(jsonData, id, &command);//这里使用keil.Jansson去提取下发数据的id和commandWireless_Receive_Ack_CloudPlatform((char *)str, id);//这里回应OneNET,表示接收到了数据Wireless_Receive_Command_Control(command);//这里对接收到的command执行对应的操作 }}

这个函数会先判断数据来源,再利用Keil.Jansson库解析数据,这个库的使用方法:

STM32在Keil5中利用Jansson库处理和组装JSON数据【详细版】

 

这个函数就是通过OneNET下发的数据去执行对应的操作

/** * @简要 执行无线模块接收到下发指令对应的操作 * @参数 cmdValue:提取后的指令数据 * @注意事项这里的指令可以更改为比int更大类型,需要在提取Wireless_Extract_Receive_Command函数中修改提取的数据大小 * @返回值 无 */void Wireless_Receive_Command_Control(int cmdValue){//1000 1 0 :1000灯 2 代表2号灯 0代表灭 if(cmdValue == 10021) HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin,GPIO_PIN_SET);else if(cmdValue == 10020) HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin,GPIO_PIN_RESET); if(cmdValue == 10031) HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin,GPIO_PIN_SET);else if(cmdValue == 10030) HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin,GPIO_PIN_RESET); }

 

代码下载

文章和代码创作不易,为了防止代码被不当使用或者其他人员下载代码后收费,需要源码或者相关资料的读者可以在评论区留下邮箱联系方式 或者 加入下方的交流群自助下载资料,博主看到了会第一时间发送噢!

看到这里的哥哥姐姐们,如果感觉此文章对你们有帮助的话,麻烦点个赞,支持一下!

补充

后续有什么内容也会及时在交流群里补充

读者们也可以加入STM32链接OneNET的群聊,交流一些遇到的问题也可以互相探讨:

自助获取资料,Q:983362248