# ali_mqtt智能云app控制外设 **Repository Path**: kalipy3/liteos_stm32f407zgtx_ali_mqtt ## Basic Information - **Project Name**: ali_mqtt智能云app控制外设 - **Description**: 人脸识别门禁—远程控制—云共享开发板项目 - **Primary Language**: C - **License**: MIT - **Default Branch**: master - **Homepage**: https://gitee.com/kalipy3/liteos_stm32f407zgtx_ali_mqtt - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 2 - **Created**: 2020-12-26 - **Last Updated**: 2023-05-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ``` readme.md :Author: kalipy :Email: kalipy@debian :Date: 2020-12-23 08:42 ``` # 人脸识别门禁—远程控制—云共享开发板项目开发课程设计 ``` 课程:嵌入式开发与实践 班级:18计科(1)班 学生姓名:刘泳、黄圣峰 指导老师:陈翠和 时间:2020-12-25 ``` # 项目背景 当今社会是科学技术飞速发展、信息广泛传播的时代。人们在感受高科技进步的同时,还希望借助于科学技术拥有更舒适、更安全的生活环境。智能建筑的提出,使作为智能建筑中重要部分的门禁系统得到迅猛发展。传统的机械锁、单片机控制类的刷卡式等门禁系统由于要近距离接触,而且容易丢失、损坏和复制,已经不能满足人们生活的需要。如何更有效的防盗成为人们关注的问题。另外,鉴于在校大学生资源有限,很多同学没有自己的开发板,非常不便于嵌入式的学习,云共享开发板可能是个好的解决办法 # 设备选型 esp8266wifi、人体红外感应传感器、安卓手机摄像头、继电器 台灯、stm32f407开发板、pc服务器(onenet_http、阿里_mqtt、node_http等) # 项目代码结构 ``` kalipy@debian ~/s/liteos_stm32f407zgtx> tree HARDWARE/ HARDWARE/ ├── BEEP │   ├── beep.c │   └── beep.h ├── esp8266 │   ├── wifi.c │   └── wifi.h ├── GLOBAL │   ├── global.c │   └── global.h ├── hmac │   ├── utils_hmac.c │   ├── utils_hmac.h │   ├── utils_md5.c │   ├── utils_md5.h │   ├── utils_sha1.c │   └── utils_sha1.h ├── KEY │   ├── key.c │   └── key.h ├── LED │   ├── led.c │   └── led.h ├── mqtt │   ├── ali_mqtt.c │   └── ali_mqtt.h ├── node_http │   ├── node_http.c │   └── node_http.h ├── onenet_http │   ├── onenet_http.c │   └── onenet_http.h ├── picture │   ├── picture.c │   └── picture.h ├── task │   ├── ali_mqtt_task.c │   ├── ali_mqtt_task.h │   ├── nodeserver_task.c │   └── nodeserver_task.h ├── uart4 │   ├── uart4.c │   └── uart4.h └── usart3 ├── usart3.c └── usart3.h ``` # 各模块结构图 *onenet_http模块* ``` #define SWITCH_DEVICE_ID "650910227"//开关设备的device_id #define API_KEY "UHcaDXdTbfergaoddyvmMJXfkvk="//api_key ▼ variables extern char * onenet_server_ip; extern int onenet_server_port; extern char RXbuff[2048]; //接收数据缓冲区 extern char TXbuff[2048]; //发送数据缓冲区 ▼ functions //@depress 已废弃 //void OneNet_GET(char *device_id); //@depress 已废弃 //void OneNet_POST(char *device_id); //onenet接收报文解析 void onenet_recive_msg_paser(char * resp); //服务器返回的数据在esp8266的串口寄存器,请自行编写中断接收,推荐用中断+操作系统的任务来处理数据 void esp8266_onenet_doGet(char *device_id, char *resp, int timeout); //开发板周期性轮询onenet服务器任务 onetnet_doGet_cycle_Task(void *arg) ``` *node_http模块* ``` ▼ variables TXbuff //发送数据缓冲器 char * node_server_ip = "192.168.43.96"; int node_server_port = 3000; ▼ functions //请求node服务器 请求路径:/takePicture //服务器返回的数据在esp8266的串口寄存器,请自行编写中断接收,推荐用中断+操作系统的任务来处理数据 void nodeserver_take_picture_doGet(char *resp, int timeout); //nodeserver接收报文解析 void nodeserver_recive_msg_paser(char *resp); ``` *node_http_task模块* ``` ▼ functions //自删除的一次性任务 嵌入式不需要太大的并发 一个请求对应一个进程的网络模型 nodeserver_doGet_msg_recive_and_paser_Task(void *arg) nodeserver_doGet_msg_recive_and_paser_task_start(void) ``` *esp8266 wifi模块* ``` #define RESET_IO(x) HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, x); #define WiFi_printf u4_printf //串口4控制 WiFi #define WiFi_RxCounter Usart4_RxCounter //串口4控制 WiFi #define WiFi_RX_BUF Usart4_RxBuff //串口4控制 WiFi #define WiFi_RXBUFF_SIZE USART4_RXBUFF_SIZE //串口4控制 WiFi #define SSID "aabbcc" //路由器SSID名称 #define PASS "Abcd1234" //路由器密码 ▼ variables extern char Connect_flag; //外部变量声明,同服务器连接状态 /*@depress 已废弃 http与mqtt不可以并发 未来将支持同时并发 所以现在connect_flag只有0或1两种状态 http的时候 0:还没有连接服务器 1:连接上服务器了 mqtt的时候 2:代表还没连接阿里mqtt服务器 3:代表已连接阿里mqtt服务器 */ char wifi_mode = 0; //联网模式 0:SSID和密码写在程序里 1:Smartconfig方式用APP发送 ▼ functions WiFi_Close(int timeout) WiFi_GetIP(int timeout) WiFi_Get_Data(char *data, char *len, char *id) WiFi_Get_LinkSta(void) WiFi_Init(void) WiFi_JoinAP(int timeout) WiFi_Reset(int timeout) WiFi_ResetIO_Init(void) WiFi_SendCmd(char *cmd, int timeout) WiFi_SendData(char id, char *databuff, int data_len, int timeout) WiFi_Smartconfig(int timeout) WiFi_WaitAP(int timeout) esp8266_connect_server(char * server_ip, int server_port, int timeout) ``` *picture模块(还没买摄像头 暂时只能通过调用与服务器相连的安卓手机的相机来实现拍照)* ``` //收到客户从浏览器/或串口助手发来的拍照请求 void drv_picture_usart_receive_msg_handler(char * receive_str) { if(strcmp("take a picture",receive_str)==0) { //Take a picture with your Android phone of remote by esp8266 //why not the camera module of STM32,because I don't have enough money //so I chose to use ADB to call android's camera indirectly through wifi //为了实现http请求的并发,这个函数每次执行都会启动一个一次性的liteos进程 //用到了一个连接对应一个进程的网络模型 //因为嵌入式不需要太大的高并发 这个模型还算合适 nodeserver_doGet_msg_recive_and_paser_task_start();//启动一个进程来处理请求 } } ``` *人体红外感应触发百度人脸识别模块* ``` ▼ variables infrared_flag ▼ functions body_infrared_Task(void *arg) body_infrared_task_start(void) drv_body_infrared_init(void) //人体红外感应task void body_infrared_Task(void *arg) { LOS_TaskDelay(15000); while (1) { LOS_TaskDelay(20); if (HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_1) == GPIO_PIN_SET && infrared_flag == 0) { infrared_flag = 1; u3_printf("drv_body_infrared gpio set.."); //Take a picture with your Android phone of remote by esp8266 //why not the camera module of STM32,because I don't have enough money,so I chose to use ADB to call android's camera indirectly through wifi nodeserver_doGet_msg_recive_and_paser_task_start();//start a liteos task } } } int body_infrared_task_start(void) { UINT32 uwRet = 0; UINT32 uwTask; TSK_INIT_PARAM_S stInitParam; stInitParam.pfnTaskEntry = body_infrared_Task; stInitParam.usTaskPrio = 9; stInitParam.uwStackSize = 0x400; stInitParam.pcName = "infrared"; drv_body_infrared_init(); u3_printf("body_infrared_Task create...\r\n"); uwRet = LOS_TaskCreate(&uwTask, &stInitParam); if(uwRet != LOS_OK) { u3_printf("body_infrared_Task create failed\r\n"); return uwRet; } u3_printf("body_infrared_Task create ok\r\n"); } ``` *usart3控制外设模块* ``` ▼ variables USART3_Handler//串口3句柄 Usart3_RxBuff//接收缓冲区 Usart3_RxCompleted//接收完成标志 Usart3_RxCounter//接收字符个数 Usart3_TxBuff//发送缓冲区 ▼ functions u3_printf(char* fmt,...)//打印到串口3 usart3_init(int bound) usart3_receive_msg_handler(char *receive_str)//负责处理来自usart3的所有的消息 void usart3_receive_msg_handler(char *receive_str) { //led msg handler drv_led_usart_receive_msg_handler(receive_str); //beep msg handler drv_beep_usart_receive_msg_handler(receive_str); //picture msg handler drv_picture_usart_receive_msg_handler(receive_str); } USART3_IRQHandler(void)//接收来自串口助手的数据并通过idle_flag通过消息队列发往上层模块 void USART3_IRQHandler(void) { UINT32 uwRet = 0; if (__HAL_UART_GET_FLAG(&USART3_Handler, UART_FLAG_RXNE)) { R[cnt++] = USART3->DR;//这里不要写printf 会影响数据接收 R[cnt] = '\0'; } else if (__HAL_UART_GET_FLAG(&USART3_Handler, UART_FLAG_IDLE)) { __HAL_UART_CLEAR_IDLEFLAG(&USART3_Handler); uwRet = LOS_QueueWrite(g_usart3_rececie_irq_idle_msgQueue, R, cnt+1, 0);//把消息发往上层处理 cnt = 0; if(uwRet != LOS_OK) { u3_printf("send message failure,error:%x\n",uwRet); } } } //从liteos的消息队列拿出消息 并进行分发 处理 //所有来自usart3的消息都经由此地 usart3_Receive_Handler_Task(void *arg) void *usart3_Receive_Handler_Task(void *arg) { UINT32 uwReadbuf; UINT32 uwRet = 0; while (1) { uwRet = LOS_QueueRead(g_usart3_rececie_irq_idle_msgQueue, &uwReadbuf, 100, LOS_WAIT_FOREVER); if(uwRet != LOS_OK) { u3_printf("recv message failure,error:%x\n",uwRet); //break; } u3_printf("recv message:%s\n", (char *)uwReadbuf); usart3_receive_msg_handler((char *)uwReadbuf); } } ``` *uart4模块 让stm32和esp8266wifi通信的代理人* ``` ▼ variables UART4_Handler USART4_TxBuff Usart4_RxBuff Usart4_RxCompleted Usart4_RxCounter ▼ functions UART4_IRQHandler(void) Usart4_Init(unsigned int bound) u4_TxData(unsigned char *data) u4_printf(char* fmt,...) //什么都没做 现在只是用来初始化esp8266 wifi模块 仅此而已 //in future, this task will be depressed //现在还没废弃 出于以后可能的扩展考虑 void *esp8266usart4_Receive_Handler_Task(void *arg) ``` *ali_mqtt物联网模块* ``` #define MQTT_TxData(x) u4_TxData(x) //串口4负责数据发送 #define PRODUCTKEY "a1t7ZGW0OAB" //产品ID #define PRODUCTKEY_LEN strlen(PRODUCTKEY) //产品ID长度 #define DEVICENAME "D001" //设备名 #define DEVICENAME_LEN strlen(DEVICENAME) //设备名长度 #define DEVICESECRE "4b4a1dc7d016d8778d271fcbcae5c8fa" //设备秘钥 #define DEVICESECRE_LEN strlen(DEVICESECRE) //设备秘钥长度 #define S_TOPIC_NAME "/sys/a1t7ZGW0OAB/D001/thing/service/property/set" //需要订阅的主题 #define P_TOPIC_NAME "/sys/a1t7ZGW0OAB/D001/thing/event/property/post" //需要发布的主题 ▼ variables extern unsigned char MQTT_RxDataBuf[R_NUM][RBUFF_UNIT]; //外部变量声明,数据的接收缓冲区,所有服务器发来的数据,存放在该缓冲区,缓冲区第一个字节存放数据长度 extern unsigned char *MQTT_RxDataInPtr; //外部变量声明,指向缓冲区存放数据的位置 extern unsigned char *MQTT_RxDataOutPtr; //外部变量声明,指向缓冲区读取数据的位置 extern unsigned char *MQTT_RxDataEndPtr; //外部变量声明,指向缓冲区结束的位置 extern unsigned char MQTT_TxDataBuf[T_NUM][TBUFF_UNIT]; //外部变量声明,数据的发送缓冲区,所有发往服务器的数据,存放在该缓冲区,缓冲区第一个字节存放数据长度 extern unsigned char *MQTT_TxDataInPtr; //外部变量声明,指向缓冲区存放数据的位置 extern unsigned char *MQTT_TxDataOutPtr; //外部变量声明,指向缓冲区读取数据的位置 extern unsigned char *MQTT_TxDataEndPtr; //外部变量声明,指向缓冲区结束的位置 extern unsigned char MQTT_CMDBuf[C_NUM][CBUFF_UNIT]; //外部变量声明,命令数据的接收缓冲区 extern unsigned char *MQTT_CMDInPtr; //外部变量声明,指向缓冲区存放数据的位置 extern unsigned char *MQTT_CMDOutPtr; //外部变量声明,指向缓冲区读取数据的位置 extern unsigned char *MQTT_CMDEndPtr; //外部变量声明,指向缓冲区结束的位置 extern char Ping_flag; //外部变量声明,ping报文状态 0:正常状态,等待计时时间到,发送Ping报文 extern char Connect_flag; //外部变量声明,同服务器连接状态 0:还没有连接服务器 1:连接上服务器了 extern char ReConnect_flag; //外部变量声明,重连服务器状态 0:连接还存在 1:连接断开,重连 extern char ConnectPack_flag; //外部变量声明,CONNECT报文状态 1:CONNECT报文成功 extern char SubcribePack_flag; //外部变量声明,订阅报文状态 1:订阅报文成功 extern char mqtt_ServerIP[128]; //存放服务器IP或是域名 extern int mqtt_ServerPort; //存放服务器的端口号 ▼ functions AliIoT_Parameter_Init(void) CMDBuf_Deal(unsigned char *data, int size) MQTT_Buff_Init(void) MQTT_ConectPack(void) MQTT_DealPushdata_Qs0(unsigned char *redata) MQTT_PingREQ(void) MQTT_PublishQs0(char *topic, char *data, int data_len) MQTT_Subscribe(char *topic_name, int QoS) TxDataBuf_Deal(unsigned char *data, int size) ``` *ali_mqtt模块* ``` ▼ functions LED1_State(void)//通过阿里智能云app控制stm32的led ali_mqtt_Task(void *arg) ali_mqtt_task_start(void)//启动ali_mqtt进程 link_to_ali_mqttserver(int timeout) ``` *main函数入口模块* ``` drv_led_init(); drv_beep_init(); drv_key_init(); usart3_init(9600); Usart4_Init(115200); //一定要使能 hal库并没有帮我们自动使能 __HAL_UART_ENABLE_IT(&USART3_Handler, UART_IT_IDLE); __HAL_UART_ENABLE_IT(&UART4_Handler, UART_IT_IDLE); uwRet = LOS_KernelInit(); if(uwRet != LOS_OK) { u3_printf("LOS_KernelInit failed\r\n"); return LOS_NOK; } uwRet = Example_create_task(); if(uwRet != LOS_OK) { u3_printf("Example_create_task failed\r\n"); return LOS_NOK; } ali_mqtt_task_start(); LOS_Start(); ``` *liteos任务创建模块* ``` int Example_create_task(void) { UINT32 uwRet = 0; UINT32 uwTask1, uwTask2, uwTask3; TSK_INIT_PARAM_S stInitParam1; stInitParam1.pfnTaskEntry = esp8266usart4_Receive_Handler_Task; stInitParam1.usTaskPrio = 8; stInitParam1.uwStackSize = 0x400; stInitParam1.pcName = "sendQueue"; /*创建互斥锁*/ LOS_MuxCreate(&g_doGetMux); u3_printf("g_doGetMux created\r\n"); stInitParam1.usTaskPrio = 8; uwRet = LOS_TaskCreate(&uwTask1, &stInitParam1); if(uwRet != LOS_OK) { u3_printf(" LOS_Task Create failed\r\n"); return uwRet; } stInitParam1.usTaskPrio = 8; stInitParam1.pfnTaskEntry = usart3_Receive_Handler_Task; uwRet = LOS_TaskCreate(&uwTask2, &stInitParam1); if(uwRet != LOS_OK) { u3_printf(" LOS_Task Create failed\r\n"); return uwRet; } //http不可与mqtt同时使用 因为esp8266只有一个 准确的说是只有一个wifi串口 //而mqtt又是有状态连接 //stInitParam1.pfnTaskEntry = onetnet_doGet_cycle_Task; //uwRet = LOS_TaskCreate(&uwTask3, &stInitParam1); //if(uwRet != LOS_OK) //{ // u3_printf(" LOS_Task Create failed\r\n"); // return uwRet; //} uwRet = LOS_QueueCreate("queue", 5, &g_usart3_rececie_irq_idle_msgQueue, 0, 50); if(uwRet != LOS_OK) { u3_printf(" LOS_Task Create failed\r\n"); return uwRet; } //ali_mqtt_task_start();//由于任务调度问题 放在这里会创建失败 } ``` --- # 协议学习 ## http协议 ### 报文结构 ![Image](./img/image_2020-12-25-13-26-10.png) ### telnet构造报文测试 先进行测试,测试没问题了,再编写嵌入式c代码 #### node_http人脸识别测试 ``` //先开启自己编写的node_http服务器 kalipy@debian ~/s/express_ok> node app.js 服务器启动成功 //然后用telnet发个http报文 kalipy@debian ~> telnet 127.0.0.1 3000 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. GET /takePicture HTTP/1.0 HTTP/1.1 200 OK X-Powered-By: Express Content-Type: application/json; charset=utf-8 Content-Length: 253 ETag: W/"fd-tDWrSRsmR7E0GtLfP/0wvjz8raw" Date: Fri, 25 Dec 2020 05:39:00 GMT Connection: close {"matchRes":{"error_code":0,"error_msg":"SUCCESS","log_id":7579750545849,"timestamp":1608874738,"cached":0,"result":{"score":95.57254791,"face_list":[{"face_token":"336aa2a9b5e65b8019d4088c4a53e49d"},{"face_token":"41d5e0a556e67424c4d375181264e542"}]}}} ``` #### onenet_http测试 ``` kalipy@debian ~> telnet api.heclouds.com 80 Trying 183.230.40.33... Connected to gtm-cn-45910ssln07.gtm-a2b4.com. Escape character is '^]'. GET /devices/650910227/datapoints HTTP/1.0 api-key: UHcaDXdTbfergaoddyvmMJXfkvk= Host: api.heclouds.com HTTP/1.1 200 OK Date: Fri, 25 Dec 2020 05:50:54 GMT Content-Type: application/json Content-Length: 137 Connection: close Server: Apache-Coyote/1.1 Pragma: no-cache {"errno":0,"data":{"count":1,"datastreams":[{"datapoints":[{"at":"2020-11-19 21:57:04.000","value":1}],"id":"switch_1"}]},"error":"succ"}Connection closed by foreign host. ``` --- ## mqtt协议 mqtt文档图片和相关知识来自csnd,因为ta写得很好,我就不重复编写mqtt的文档了 这里给出链接`https://blog.csdn.net/qq_39400113/article/details/107629842)` 表示尊重原作者 ### mqtt物联网控制的常用两种模式 ![Image](./img/image_2020-12-25-13-59-25.png) ![Image](./img/image_2020-12-25-13-59-58.png) ### mqtt业务层原理 #### stm32如何接收用户发来的消息? ![Image](./img/image_2020-12-25-14-02-06.png) stm32关注(订阅)云mqtt服务器后后即可收到服务器发来的消息 #### 用户如何向stm32发送消息? ![Image](./img/image_2020-12-25-14-05-50.png) 手机向云mqtt服务器发布消息后,云mqtt服务器就会向stm32推送消息 #### 总结图 ![Image](./img/image_2020-12-25-14-09-46.png) --- ## mqtt报文结构 ### connect报文 ![Image](./img/image_2020-12-25-14-16-57.png) #### 固定报头 ![Image](./img/image_2020-12-25-14-18-25.png) #### 可变报头 ![Image](./img/image_2020-12-25-14-21-08.png) #### 有效载荷 ![Image](./img/image_2020-12-25-14-21-57.png) #### 阿里mqtt三元组 ![Image](./img/image_2020-12-25-14-24-30.png) #### 把密码加密 ![Image](./img/image_2020-12-25-14-26-32.png) #### 转换成16进制 ![Image](./img/image_2020-12-25-14-27-11.png) #### 组合到一起 ![Image](./img/image_2020-12-25-14-28-43.png) #### 最终有效载荷 ![Image](./img/image_2020-12-25-14-29-26.png) #### 最终Connect控制报文为 ![Image](./img/image_2020-12-25-14-30-18.png) --- ## 网络调试助手构造报文测试 ### 发送connect报文连接阿里mqtt服务器 ![Image](./img/image_2020-12-25-14-32-06.png) ### ok 收到了阿里的回复报文 ![Image](./img/image_2020-12-25-14-33-56.png) ### 查阅mqtt开发手册查看回复报文的意思 ![Image](./img/image_2020-12-25-14-35-41.png) ### 登录阿里mqtt后台查看是否真的连接上了 ![Image](./img/image_2020-12-25-14-37-01.png) ### 断开连接测试 ![Image](./img/image_2020-12-25-14-37-57.png) ![Image](./img/image_2020-12-25-14-38-29.png) ### 再去阿里mqtt后台查看我们的开发板状态 断开连接成功 ![Image](./img/image_2020-12-25-14-39-25.png) ### ok 连接测试完成 再次感谢`https://blog.csdn.net/qq_39400113/article/details/107629842`这篇讲解mqtt协议好文章 --- ## mqtt代码实现 这里暂时不讲解,讲起来太费时间,按照上面这篇的文章的讲解和mqtt协议手册来写即可,当然,你也可以选择移植github上的mqtt实现 --- # 项目设计图纸(最重要的环节 所有代码按照思路图来编写) ### 整体思路图 ### 云共享开发板和串口3控制stm32外设思路图 ![Image](./img/image_2020-12-25-18-22-07.png) ### node_http人脸识别控制stm32外设思路图 ![Image](./img/image_2020-12-25-18-24-10.png) #### 函数调用关系图 ![Image](./img/1.png) ### 阿里mqtt控制stm32外设思路图 ![Image](./img/image_2020-12-25-18-24-55.png) #### 函数调用关系图 ![Image](./img/2.png) --- # 项目演示 ### 云共享开发版 ### 人体红外感应触发人脸识别请求控制led ### 人脸识别控制外设 ### 继电器控制台灯(由于时间关系加入) ### 串口控制stm32外设 --- # 项目开发中遇到的问题 ## 临界资源竞争问题 ### http并发请求的临界区访问问题 为什么会有共享资源竞争问题? ![Image](./img/image_2020-12-25-20-31-02.png) #### http并发请求问题重现 ![Image](./img/image_2020-12-25-20-33-07.png) 即在nodeserver_doGet连接上node_http服务器正在等待响应的时候,马上又再发个onenet_http请求,串口4esp8266则直接死掉,stm32卡死 ##### 解决方法一 直接在xx_http服务器中对用户来的并发请求进行同步 ##### 解决方法二 直接在stm32中通过互斥或消息队列等进行同步,这里我用了互斥 --- ### doGet里面while(1)死等造成发报文..和http无状态连接下的并发问题 问题产生的原因是usart3_Task这个liteos任务里有如下调用关系: ``` usart3_Receive_handler_Task() { while (1) { usart_receive_msg_handler() { drv_picture_usart_receive_msg_handler() { xx_picture_doGet() { while (usart4_Rxcompleted == 0);//死等 等待xx_http服务器的响应数据 wifi_close()//关闭与xx_http服务器的连接 } } } } } ``` 即while(1)里面写while(usart4_Rxcompleted == 0)无论如何都会阻塞在里面,主要是我们在uart4 esp8266这个公共资源只有一个的情况下,却要求esp8266要可以并发发起多个http请求还要不阻塞其它任务所导致的其中一种奇怪写法 #### 解决方法一 xx_http_doGet里面别写while(1)死等请求的响应,wifi_close在其它地方调用,可行,但是这样的代码维护困难 #### 解决方法二 把所有xx_http_doGet()都放在一个liteos的任务中进行轮询处理 #### 解决方法三(本项目采用这种方法) xx_http_doGet都分别用一个liteos的任务来处理,即相当于一个http请求对应一个进程的经典思想 #### 解决方法四 通过liteos的消息队列通信机制进行http请求的同步 --- ## ali_mqtt与其它xx_mqtt服务器并发运行是否可行的问题分析 主要矛盾是mqtt是有状态的长连接,esp8266是否可以并行支持多个连接? 答:虽然esp8266可以当server同时让多个客户端连接上,但是我暂时还不知道esp8266是否可以并行建立并多个mqtt连接 ## 串口问题 ### 串口中断使能及收发数据问题 使用cubemx生成代码除了要在cubemx中选中串口中断使能选项,还要在代码中自己加入如下使能代码,不然串口中断不会进入: ``` //一定要使能 hal库并没有帮我们自动使能 __HAL_UART_ENABLE_IT(&USART3_Handler, UART_IT_IDLE); __HAL_UART_ENABLE_IT(&UART4_Handler, UART_IT_IDLE); ``` ### 串口助手软件和串口插线先后顺序的硬件问题 如果自己写的串口程序不能正常输出结果或者没反应,请不要立即怀疑自己的代码,首先应该想到是不是串口线的问题,比如我们开发版,把程序下载到stm32后,必须重新插拔所有usb线并且串口线一定要等几秒在接上,不然stm32会卡死 ### 不同操作系统的问题 比如我们教室哪那个stm32f103,在win10是完全没问题,但是同样的串口程序放到我的linux系统上通过串口助手来print,则完全没用 --- ## liteos问题 ### 在任务while(1)定义大的数组导致liteos死掉的问题 ![Image](./img/image_2020-12-25-21-13-11.png) 加static关键字解决 ## 粗心问题 ### 没有细心的看人体红外感应模块的手册 只看到了触发后是由低电平到高电平,实际上是低电平->高电平->低电平的方式 --- # 项目开发中gdb调试工具的使用 省略...见我的my_study_notes仓库下的笔记,里面有几篇gdb的文章 --- # 课后自我实力提高 ``` 深入理解liteos等嵌入式系统的源码,通过研究源码,提高自己的代码质量和提升内力 可以考虑搭建自己的mqtt服务器 比如java里的activemq消息队列(java里一般叫消息中间件)等 高可用 高并发 持久化存储 异步晓峰 非常强大 ``` --- # 嵌入式与java高级知识的结合练习想法(弄懂这些东西 非常有好处) ``` 我们既要懂硬件懂软件也要懂架构 以云共享开发板为例 我们先看看将来可能存在的问题和现有问题..... ``` ## 以云共享开发板为例的解决方案参考 ### 高并发 高性能 高可用 分布式 (nginx mybatis redis activemq spring zookeeper的解决方案) #### 设计图参考 ![Image](./img/3.png) --- # 最终提高 ``` linux驱动开发 tcp/ip源码研究 select poll epoll等常见网络模型源码研究 linux内核源码研究 linux内核开发 高并发高性能网络模型代码研究与开发 植发 ```