content_views"
class="markdown_views prism-atom-one-dark">
ESP32S3板子, 一运行class="tags" href="/HTTP.html" title=http>http请求百度网站的例子, 就会panic死机, 记录下出现及解决过程.
class="tags" href="/ESP32.html" title=esp32>esp32s3_class="tags" href="/HTTP.html" title=http>http_4">class="tags" href="/ESP32.html" title=esp32>esp32s3 class="tags" href="/HTTP.html" title=http>http请求崩溃
一执行class="tags" href="/HTTP.html" title=http>http请求的perform就会崩溃,
打印如图
c="class="tags" href="/HTTP.html" title=http>https://i-blog.csdnimg.cn/direct/ba40d1f12e4c441e8e61b90058c1de5f.jpeg#pic_center" alt="在这里插入图片描述" />
ESP32-IDF 的class="tags" href="/HTTP.html" title=http>http请求代码是根据官方demo来改的,
第一步先连接wifi,
连接上后执行class="tags" href="/HTTP.html" title=http>http get请求百度网站.
理论上写法是没问题的,但是运行到板子上发现很容易崩溃.
问题代码讨论
会在可能有问题的地方注释,有4个问题点,具体看代码 ,
最主要问题是运行内存有限, 容易发生栈或堆溢出或越界导致崩溃.
<code class="prism language-c">class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><stdio.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><pthread.h>class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><string.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><stdlib.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"freertos/FreeRTOS.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"freertos/task.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_err.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_log.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_system.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"nvs_flash.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_event.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_netif.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_wifi.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_tls.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_crt_bundle.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_class="tags" href="/HTTP.html" title=http>http_client.h"class="token keyword">static class="token keyword">const class="token keyword">char class="token operator">*TAG class="token operator">= class="token string">"HTTP_REQUEST"class="token punctuation">;class="token comment">// 这里的buffer要适当, 如果改太大了, 比如10240就可能导致死机, 要根据实际运行结果做调整
class="token macro property">class="token directive-hash">#class="token directive keyword">define class="token macro-name">MAX_HTTP_OUTPUT_BUFFER class="token expression">class="token number">2048
class="token macro property">class="token directive-hash">#class="token directive keyword">define class="token macro-name">HTTP_URL class="token string">"class="tags" href="/HTTP.html" title=http>http://www.baidu.com"class="token comment">// HTTP 请求的处理函数
class="token class-name">esp_err_t class="token function">class="tags" href="/HTTP.html" title=http>http_event_handlerclass="token punctuation">(class="token class-name">esp_class="tags" href="/HTTP.html" title=http>http_client_event_t class="token operator">*evtclass="token punctuation">)
class="token punctuation">{class="token comment">// 缓存class="tags" href="/HTTP.html" title=http>http响应的bufferclass="token keyword">static class="token keyword">char class="token operator">*output_bufferclass="token punctuation">;class="token comment">// 已经读取的字节数class="token keyword">static class="token keyword">int output_lenclass="token punctuation">;class="token keyword">switchclass="token punctuation">(evtclass="token operator">->event_idclass="token punctuation">) class="token punctuation">{class="token keyword">case HTTP_EVENT_ERRORclass="token operator">:class="token function">ESP_LOGDclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_ERROR"class="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token keyword">case HTTP_EVENT_ON_CONNECTEDclass="token operator">:class="token function">ESP_LOGDclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_ON_CONNECTED"class="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token keyword">case HTTP_EVENT_HEADER_SENTclass="token operator">:class="token function">ESP_LOGDclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_HEADER_SENT"class="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token keyword">case HTTP_EVENT_ON_HEADERclass="token operator">:class="token function">ESP_LOGDclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_ON_HEADER, key=%s, value=%s"class="token punctuation">, evtclass="token operator">->header_keyclass="token punctuation">, evtclass="token operator">->header_valueclass="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token keyword">case HTTP_EVENT_ON_DATAclass="token operator">:class="token function">ESP_LOGDclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_ON_DATA, len=%d"class="token punctuation">, evtclass="token operator">->data_lenclass="token punctuation">)class="token punctuation">;class="token keyword">if class="token punctuation">(class="token operator">!class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_is_chunked_responseclass="token punctuation">(evtclass="token operator">->clientclass="token punctuation">)class="token punctuation">) class="token punctuation">{class="token keyword">if class="token punctuation">(evtclass="token operator">->user_dataclass="token punctuation">) class="token punctuation">{class="token comment">// 问题1: 这里没有做防溢出限制, 当class="tags" href="/HTTP.html" title=http>http返回的数据长度趤过预留的buffer大小MAX_HTTP_OUTPUT_BUFFER时就会溢出崩溃class="token function">memcpyclass="token punctuation">(evtclass="token operator">->user_data class="token operator">+ output_lenclass="token punctuation">, evtclass="token operator">->dataclass="token punctuation">, evtclass="token operator">->data_lenclass="token punctuation">)class="token punctuation">;class="token punctuation">} class="token keyword">else class="token punctuation">{class="token keyword">if class="token punctuation">(output_buffer class="token operator">== class="token constant">NULLclass="token punctuation">) class="token punctuation">{class="token comment">// 问题2: 这里直接用malloc申请class="tags" href="/HTTP.html" title=http>http返回的数据长度的堆空间, 实测在class="tags" href="/ESP32.html" title=esp32>esp32s3板子上跑会崩溃output_buffer class="token operator">= class="token punctuation">(class="token keyword">char class="token operator">*class="token punctuation">) class="token function">mallocclass="token punctuation">(class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_get_content_lengthclass="token punctuation">(evtclass="token operator">->clientclass="token punctuation">)class="token punctuation">)class="token punctuation">;output_len class="token operator">= class="token number">0class="token punctuation">;class="token keyword">if class="token punctuation">(output_buffer class="token operator">== class="token constant">NULLclass="token punctuation">) class="token punctuation">{class="token function">ESP_LOGEclass="token punctuation">(TAGclass="token punctuation">, class="token string">"Failed to allocate memory for output buffer"class="token punctuation">)class="token punctuation">;class="token keyword">return ESP_FAILclass="token punctuation">;class="token punctuation">}class="token punctuation">}class="token function">memcpyclass="token punctuation">(output_buffer class="token operator">+ output_lenclass="token punctuation">, evtclass="token operator">->dataclass="token punctuation">, evtclass="token operator">->data_lenclass="token punctuation">)class="token punctuation">;class="token punctuation">}output_len class="token operator">+= evtclass="token operator">->data_lenclass="token punctuation">;class="token punctuation">}class="token keyword">breakclass="token punctuation">;class="token keyword">case HTTP_EVENT_ON_FINISHclass="token operator">:class="token function">ESP_LOGDclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_ON_FINISH"class="token punctuation">)class="token punctuation">;class="token keyword">if class="token punctuation">(output_buffer class="token operator">!= class="token constant">NULLclass="token punctuation">) class="token punctuation">{class="token comment">// Response is accumulated in output_buffer. Uncomment the below line to print the accumulated responseclass="token comment">// ESP_LOG_BUFFER_HEX(TAG, output_buffer, output_len);class="token function">freeclass="token punctuation">(output_bufferclass="token punctuation">)class="token punctuation">;output_buffer class="token operator">= class="token constant">NULLclass="token punctuation">;class="token punctuation">}output_len class="token operator">= class="token number">0class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token keyword">case HTTP_EVENT_DISCONNECTEDclass="token operator">:class="token function">ESP_LOGIclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_DISCONNECTED"class="token punctuation">)class="token punctuation">;class="token keyword">if class="token punctuation">(output_buffer class="token operator">!= class="token constant">NULLclass="token punctuation">) class="token punctuation">{class="token function">freeclass="token punctuation">(output_bufferclass="token punctuation">)class="token punctuation">;output_buffer class="token operator">= class="token constant">NULLclass="token punctuation">;class="token punctuation">}output_len class="token operator">= class="token number">0class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token punctuation">}class="token keyword">return ESP_OKclass="token punctuation">;
class="token punctuation">}class="token keyword">void class="token function">requestclass="token punctuation">(class="token keyword">const class="token keyword">char class="token operator">*urlclass="token punctuation">) class="token punctuation">{class="token function">printfclass="token punctuation">(class="token string">"request -----------1\n"class="token punctuation">)class="token punctuation">;class="token comment">// 响应结果放在这里class="token keyword">char local_response_bufferclass="token punctuation">[MAX_HTTP_OUTPUT_BUFFERclass="token punctuation">] class="token operator">= class="token punctuation">{class="token number">0class="token punctuation">}class="token punctuation">;class="token comment">// 创建一个 HTTP 客户端配置class="token class-name">esp_class="tags" href="/HTTP.html" title=http>http_client_config_t config class="token operator">= class="token punctuation">{class="token punctuation">.method class="token operator">= HTTP_METHOD_GETclass="token punctuation">,class="token punctuation">.url class="token operator">= urlclass="token punctuation">,class="token punctuation">.event_handler class="token operator">= class="tags" href="/HTTP.html" title=http>http_event_handlerclass="token punctuation">,class="token punctuation">.user_data class="token operator">= local_response_bufferclass="token punctuation">,class="token punctuation">.disable_auto_redirect class="token operator">= trueclass="token punctuation">,class="token punctuation">}class="token punctuation">;class="token comment">// 创建一个 HTTP 客户端并执行 GET 请求class="token class-name">esp_class="tags" href="/HTTP.html" title=http>http_client_handle_t client class="token operator">= class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_initclass="token punctuation">(class="token operator">&configclass="token punctuation">)class="token punctuation">;class="token function">printfclass="token punctuation">(class="token string">"request -----------2\n"class="token punctuation">)class="token punctuation">;class="token class-name">esp_err_t err class="token operator">= class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_performclass="token punctuation">(clientclass="token punctuation">)class="token punctuation">; class="token comment">// 请求百度网页时,一执行这行系统就会崩溃class="token function">printfclass="token punctuation">(class="token string">"request -----------3\n"class="token punctuation">)class="token punctuation">;class="token comment">// 检查请求是否成功class="token keyword">if class="token punctuation">(err class="token operator">== ESP_OKclass="token punctuation">) class="token punctuation">{class="token keyword">int len class="token operator">= class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_get_content_lengthclass="token punctuation">(clientclass="token punctuation">)class="token punctuation">;class="token function">ESP_LOGIclass="token punctuation">(TAGclass="token punctuation">, class="token string">"Status = %d, content_length = %d"class="token punctuation">,class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_get_status_codeclass="token punctuation">(clientclass="token punctuation">)class="token punctuation">,class="token comment">//状态码lenclass="token punctuation">)class="token punctuation">;class="token comment">//数据长度class="token punctuation">} class="token keyword">else class="token punctuation">{class="token function">printfclass="token punctuation">(class="token string">"HTTP GET request failed: %s\n"class="token punctuation">, class="token function">esp_err_to_nameclass="token punctuation">(errclass="token punctuation">)class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token function">printfclass="token punctuation">(class="token string">"Response: %.*s\n"class="token punctuation">, class="token function">strlenclass="token punctuation">(local_response_bufferclass="token punctuation">)class="token punctuation">, local_response_bufferclass="token punctuation">)class="token punctuation">;class="token comment">//断开并释放资源class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_cleanupclass="token punctuation">(clientclass="token punctuation">)class="token punctuation">;class="token function">printfclass="token punctuation">(class="token string">"request -----------4\n"class="token punctuation">)class="token punctuation">;
class="token punctuation">}class="token keyword">void class="token function">class="tags" href="/HTTP.html" title=http>http_test_taskclass="token punctuation">(class="token keyword">void class="token operator">*argclass="token punctuation">)
class="token punctuation">{class="token function">sleepclass="token punctuation">(class="token number">15class="token punctuation">)class="token punctuation">;class="token function">requestclass="token punctuation">(HTTP_URLclass="token punctuation">)class="token punctuation">;class="token function">vTaskDeleteclass="token punctuation">(class="token constant">NULLclass="token punctuation">)class="token punctuation">;
class="token punctuation">}class="token comment">/*** @brief WiFi 的事件循环Handler* @param arg* @param event_base* @param event_id* @param event_data*/
class="token keyword">void class="token function">wifi_event_handlerclass="token punctuation">(class="token keyword">void class="token operator">*argclass="token punctuation">, class="token class-name">esp_event_base_t event_baseclass="token punctuation">, class="token class-name">int32_t event_idclass="token punctuation">, class="token keyword">void class="token operator">*event_dataclass="token punctuation">)
class="token punctuation">{class="token function">printfclass="token punctuation">(class="token string">"wifi_event_handler base:%s, id:%d\n"class="token punctuation">, event_baseclass="token punctuation">, event_idclass="token punctuation">)class="token punctuation">;class="token keyword">if class="token punctuation">(event_base class="token operator">== WIFI_EVENT class="token operator">&& event_id class="token operator">== WIFI_EVENT_STA_STARTclass="token punctuation">)class="token punctuation">{class="token function">printfclass="token punctuation">(class="token string">"esp_wifi_connect\n"class="token punctuation">)class="token punctuation">;class="token function">esp_wifi_connectclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">else class="token keyword">if class="token punctuation">(event_base class="token operator">== WIFI_EVENT class="token operator">&& event_id class="token operator">== WIFI_EVENT_STA_DISCONNECTEDclass="token punctuation">)class="token punctuation">{class="token function">printfclass="token punctuation">(class="token string">"esp_wifi_connect\n"class="token punctuation">)class="token punctuation">;class="token function">esp_wifi_connectclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">if class="token punctuation">(event_base class="token operator">== IP_EVENT class="token operator">&& event_id class="token operator">== IP_EVENT_STA_GOT_IPclass="token punctuation">)class="token punctuation">{class="token class-name">ip_event_got_ip_t class="token operator">*event class="token operator">= class="token punctuation">(class="token class-name">ip_event_got_ip_t class="token operator">*class="token punctuation">)event_dataclass="token punctuation">;class="token function">ESP_LOGIclass="token punctuation">(class="token string">"ESP32"class="token punctuation">, class="token string">"IP地址:: " IPSTRclass="token punctuation">, class="token function">IP2STRclass="token punctuation">(class="token operator">&eventclass="token operator">->ip_infoclass="token punctuation">.ipclass="token punctuation">)class="token punctuation">)class="token punctuation">;class="token comment">//request(HTTP_URL); 问题点3: 获取到ip地址后,不要直接在这里执行class="tags" href="/HTTP.html" title=http>http请求, 否则会直接崩溃class="token punctuation">}
class="token punctuation">}class="token keyword">void class="token function">app_mainclass="token punctuation">(class="token keyword">voidclass="token punctuation">)
class="token punctuation">{class="token class-name">esp_err_t ret class="token operator">= class="token function">nvs_flash_initclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 初始化默认NVS分区class="token keyword">if class="token punctuation">(ret class="token operator">== ESP_ERR_NVS_NO_FREE_PAGES class="token operator">|| ret class="token operator">== ESP_ERR_NVS_NEW_VERSION_FOUNDclass="token punctuation">)class="token punctuation">{class="token function">ESP_ERROR_CHECKclass="token punctuation">(class="token function">nvs_flash_eraseclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">; class="token comment">// 擦除默认NVS分区ret class="token operator">= class="token function">nvs_flash_initclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 初始化默认NVS分区class="token punctuation">}class="token function">ESP_ERROR_CHECKclass="token punctuation">(retclass="token punctuation">)class="token punctuation">;class="token function">ESP_ERROR_CHECKclass="token punctuation">(class="token function">esp_netif_initclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">; class="token comment">// 初始化底层TCP/IP堆栈class="token function">ESP_ERROR_CHECKclass="token punctuation">(class="token function">esp_event_loop_create_defaultclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">; class="token comment">// 创建默认事件循环class="token function">esp_netif_create_default_wifi_staclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 创建默认的WIFI STA。class="token class-name">wifi_init_config_t cfg class="token operator">= class="token function">WIFI_INIT_CONFIG_DEFAULTclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token function">esp_wifi_initclass="token punctuation">(class="token operator">&cfgclass="token punctuation">)class="token punctuation">; class="token comment">// 初始化WiFi为WiFi驱动程序class="token class-name">wifi_sta_config_t cfg_sta class="token operator">= class="token punctuation">{class="token punctuation">.ssid class="token operator">= class="token string">"black"class="token punctuation">,class="token punctuation">.password class="token operator">= class="token string">"black1234"class="token punctuation">,class="token punctuation">.thresholdclass="token punctuation">.authmode class="token operator">= WIFI_AUTH_WPA2_PSKclass="token punctuation">, class="token comment">//加密方式class="token punctuation">.pmf_cfg class="token operator">= class="token punctuation">{class="token punctuation">.capable class="token operator">= trueclass="token punctuation">,class="token punctuation">.required class="token operator">= falseclass="token punctuation">}class="token punctuation">,class="token punctuation">}class="token punctuation">;class="token function">esp_wifi_set_configclass="token punctuation">(WIFI_IF_STAclass="token punctuation">, class="token punctuation">(class="token class-name">wifi_config_t class="token operator">*class="token punctuation">)class="token operator">&cfg_staclass="token punctuation">)class="token punctuation">; class="token comment">// 设置ESP32 STA或AP的配置class="token function">esp_wifi_set_modeclass="token punctuation">(WIFI_MODE_STAclass="token punctuation">)class="token punctuation">; class="token comment">// 设置WiFi操作模式class="token comment">// 将事件处理程序的实例注册到默认循环中 任何事件class="token function">esp_event_handler_instance_registerclass="token punctuation">(WIFI_EVENTclass="token punctuation">, ESP_EVENT_ANY_IDclass="token punctuation">, wifi_event_handlerclass="token punctuation">, class="token constant">NULLclass="token punctuation">, class="token constant">NULLclass="token punctuation">)class="token punctuation">;class="token comment">// 将事件处理程序的实例注册到默认循环中 工作站从连接的AP获得IP事件class="token function">esp_event_handler_instance_registerclass="token punctuation">(IP_EVENTclass="token punctuation">, IP_EVENT_STA_GOT_IPclass="token punctuation">, wifi_event_handlerclass="token punctuation">, class="token constant">NULLclass="token punctuation">, class="token constant">NULLclass="token punctuation">)class="token punctuation">;class="token function">esp_wifi_startclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 根据当前配置启动wificlass="token function">xTaskCreateclass="token punctuation">(class="token operator">&class="tags" href="/HTTP.html" title=http>http_test_taskclass="token punctuation">, class="token string">"class="tags" href="/HTTP.html" title=http>http_test_task"class="token punctuation">, class="token number">8192class="token punctuation">, class="token constant">NULLclass="token punctuation">, class="token number">5class="token punctuation">, class="token constant">NULLclass="token punctuation">)class="token punctuation">; class="token comment">//问题点4: 这里参数需要设置足够大的栈大小, 否则会导致崩溃
class="token punctuation">}
code>
修正后不崩溃的代码
百度网页返回的class="tags" href="/HTTP.html" title=http>http结果太多了,会导致空间不够,
针对问题代码, 做出调整, 对栈空间大小做限制, 当class="tags" href="/HTTP.html" title=http>http返回内容过长时,直接丢弃
<code class="prism language-c">class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><stdio.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><pthread.h>class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><string.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><stdlib.h>
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"freertos/FreeRTOS.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"freertos/task.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_err.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_log.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_system.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"nvs_flash.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_event.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_netif.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_wifi.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_tls.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_crt_bundle.h"
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string">"esp_class="tags" href="/HTTP.html" title=http>http_client.h"class="token keyword">static class="token keyword">const class="token keyword">char class="token operator">*TAG class="token operator">= class="token string">"HTTP_REQUEST"class="token punctuation">;
class="token macro property">class="token directive-hash">#class="token directive keyword">define class="token macro-name">MAX_HTTP_OUTPUT_BUFFER class="token expression">class="token number">2048
class="token macro property">class="token directive-hash">#class="token directive keyword">define class="token macro-name">HTTP_URL class="token string">"class="tags" href="/HTTP.html" title=http>http://www.baidu.com"class="token comment">// HTTP 请求的处理函数
class="token class-name">esp_err_t class="token function">class="tags" href="/HTTP.html" title=http>http_event_handlerclass="token punctuation">(class="token class-name">esp_class="tags" href="/HTTP.html" title=http>http_client_event_t class="token operator">*evtclass="token punctuation">)
class="token punctuation">{class="token comment">// 缓存class="tags" href="/HTTP.html" title=http>http响应的bufferclass="token keyword">static class="token keyword">char class="token operator">*output_bufferclass="token punctuation">;class="token comment">// 已经读取的字节数class="token keyword">static class="token keyword">int output_lenclass="token punctuation">;class="token keyword">switchclass="token punctuation">(evtclass="token operator">->event_idclass="token punctuation">) class="token punctuation">{class="token keyword">case HTTP_EVENT_ERRORclass="token operator">:class="token function">ESP_LOGDclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_ERROR"class="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token keyword">case HTTP_EVENT_ON_CONNECTEDclass="token operator">:class="token function">ESP_LOGDclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_ON_CONNECTED"class="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token keyword">case HTTP_EVENT_HEADER_SENTclass="token operator">:class="token function">ESP_LOGDclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_HEADER_SENT"class="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token keyword">case HTTP_EVENT_ON_HEADERclass="token operator">:class="token function">ESP_LOGDclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_ON_HEADER, key=%s, value=%s"class="token punctuation">, evtclass="token operator">->header_keyclass="token punctuation">, evtclass="token operator">->header_valueclass="token punctuation">)class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token keyword">case HTTP_EVENT_ON_DATAclass="token operator">:class="token function">ESP_LOGDclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_ON_DATA, len=%d"class="token punctuation">, evtclass="token operator">->data_lenclass="token punctuation">)class="token punctuation">;class="token keyword">if class="token punctuation">(class="token operator">!class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_is_chunked_responseclass="token punctuation">(evtclass="token operator">->clientclass="token punctuation">)class="token punctuation">) class="token punctuation">{class="token keyword">if class="token punctuation">(evtclass="token operator">->user_dataclass="token punctuation">) class="token punctuation">{class="token comment">// 这里对buffer长度进行判断, 如果class="tags" href="/HTTP.html" title=http>http返回长度过长, 为防止溢出就丢弃,否则进行追加拷贝class="token keyword">int left class="token operator">= MAX_HTTP_OUTPUT_BUFFER class="token operator">- output_len class="token operator">-class="token number">1class="token punctuation">;class="token keyword">if class="token punctuation">(left class="token operator">> evtclass="token operator">->data_lenclass="token punctuation">)class="token function">memcpyclass="token punctuation">(evtclass="token operator">->user_data class="token operator">+ output_lenclass="token punctuation">, evtclass="token operator">->dataclass="token punctuation">, evtclass="token operator">->data_lenclass="token punctuation">)class="token punctuation">;class="token keyword">else class="token keyword">if class="token punctuation">(left class="token operator">> class="token number">0class="token punctuation">)class="token function">memcpyclass="token punctuation">(evtclass="token operator">->user_data class="token operator">+ output_lenclass="token punctuation">, evtclass="token operator">->dataclass="token punctuation">, leftclass="token punctuation">)class="token punctuation">;class="token keyword">elseclass="token function">ESP_LOGIclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_ON_DATA, buffer full"class="token punctuation">)class="token punctuation">;class="token punctuation">} class="token keyword">else class="token punctuation">{class="token comment">// 如果实测user_data设置为空时,走这里申请堆内存会崩溃则可以注释掉这段,否则可以使用class="token keyword">if class="token punctuation">(output_buffer class="token operator">== class="token constant">NULLclass="token punctuation">) class="token punctuation">{output_buffer class="token operator">= class="token punctuation">(class="token keyword">char class="token operator">*class="token punctuation">) class="token function">mallocclass="token punctuation">(class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_get_content_lengthclass="token punctuation">(evtclass="token operator">->clientclass="token punctuation">)class="token punctuation">)class="token punctuation">;output_len class="token operator">= class="token number">0class="token punctuation">;class="token keyword">if class="token punctuation">(output_buffer class="token operator">== class="token constant">NULLclass="token punctuation">) class="token punctuation">{class="token function">ESP_LOGEclass="token punctuation">(TAGclass="token punctuation">, class="token string">"Failed to allocate memory for output buffer"class="token punctuation">)class="token punctuation">;class="token keyword">return ESP_FAILclass="token punctuation">;class="token punctuation">}class="token punctuation">}class="token function">memcpyclass="token punctuation">(output_buffer class="token operator">+ output_lenclass="token punctuation">, evtclass="token operator">->dataclass="token punctuation">, evtclass="token operator">->data_lenclass="token punctuation">)class="token punctuation">;class="token punctuation">}output_len class="token operator">+= evtclass="token operator">->data_lenclass="token punctuation">;class="token punctuation">}class="token keyword">breakclass="token punctuation">;class="token keyword">case HTTP_EVENT_ON_FINISHclass="token operator">:class="token function">ESP_LOGDclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_ON_FINISH"class="token punctuation">)class="token punctuation">;class="token keyword">if class="token punctuation">(output_buffer class="token operator">!= class="token constant">NULLclass="token punctuation">) class="token punctuation">{class="token comment">// Response is accumulated in output_buffer. Uncomment the below line to print the accumulated responseclass="token comment">// ESP_LOG_BUFFER_HEX(TAG, output_buffer, output_len);class="token function">freeclass="token punctuation">(output_bufferclass="token punctuation">)class="token punctuation">;output_buffer class="token operator">= class="token constant">NULLclass="token punctuation">;class="token punctuation">}output_len class="token operator">= class="token number">0class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token keyword">case HTTP_EVENT_DISCONNECTEDclass="token operator">:class="token function">ESP_LOGIclass="token punctuation">(TAGclass="token punctuation">, class="token string">"HTTP_EVENT_DISCONNECTED"class="token punctuation">)class="token punctuation">;class="token keyword">if class="token punctuation">(output_buffer class="token operator">!= class="token constant">NULLclass="token punctuation">) class="token punctuation">{class="token function">freeclass="token punctuation">(output_bufferclass="token punctuation">)class="token punctuation">;output_buffer class="token operator">= class="token constant">NULLclass="token punctuation">;class="token punctuation">}output_len class="token operator">= class="token number">0class="token punctuation">;class="token keyword">breakclass="token punctuation">;class="token punctuation">}class="token keyword">return ESP_OKclass="token punctuation">;
class="token punctuation">}class="token keyword">void class="token function">requestclass="token punctuation">(class="token keyword">const class="token keyword">char class="token operator">*urlclass="token punctuation">) class="token punctuation">{class="token function">printfclass="token punctuation">(class="token string">"request -----------1\n"class="token punctuation">)class="token punctuation">;class="token comment">// 响应结果放在这里class="token keyword">char local_response_bufferclass="token punctuation">[MAX_HTTP_OUTPUT_BUFFERclass="token punctuation">] class="token operator">= class="token punctuation">{class="token number">0class="token punctuation">}class="token punctuation">;class="token comment">// 创建一个 HTTP 客户端配置class="token class-name">esp_class="tags" href="/HTTP.html" title=http>http_client_config_t config class="token operator">= class="token punctuation">{class="token punctuation">.method class="token operator">= HTTP_METHOD_GETclass="token punctuation">,class="token punctuation">.url class="token operator">= urlclass="token punctuation">,class="token punctuation">.event_handler class="token operator">= class="tags" href="/HTTP.html" title=http>http_event_handlerclass="token punctuation">,class="token punctuation">.user_data class="token operator">= local_response_bufferclass="token punctuation">,class="token punctuation">.disable_auto_redirect class="token operator">= trueclass="token punctuation">,class="token punctuation">}class="token punctuation">;class="token comment">// 创建一个 HTTP 客户端并执行 GET 请求class="token class-name">esp_class="tags" href="/HTTP.html" title=http>http_client_handle_t client class="token operator">= class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_initclass="token punctuation">(class="token operator">&configclass="token punctuation">)class="token punctuation">;class="token function">printfclass="token punctuation">(class="token string">"request -----------2\n"class="token punctuation">)class="token punctuation">;class="token class-name">esp_err_t err class="token operator">= class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_performclass="token punctuation">(clientclass="token punctuation">)class="token punctuation">; class="token comment">// 请求百度网页时,一执行这行系统就会崩溃class="token function">printfclass="token punctuation">(class="token string">"request -----------3\n"class="token punctuation">)class="token punctuation">;class="token comment">// 检查请求是否成功class="token keyword">if class="token punctuation">(err class="token operator">== ESP_OKclass="token punctuation">) class="token punctuation">{class="token keyword">int len class="token operator">= class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_get_content_lengthclass="token punctuation">(clientclass="token punctuation">)class="token punctuation">;class="token function">ESP_LOGIclass="token punctuation">(TAGclass="token punctuation">, class="token string">"Status = %d, content_length = %d"class="token punctuation">,class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_get_status_codeclass="token punctuation">(clientclass="token punctuation">)class="token punctuation">,class="token comment">//状态码lenclass="token punctuation">)class="token punctuation">;class="token comment">//数据长度class="token punctuation">} class="token keyword">else class="token punctuation">{class="token function">printfclass="token punctuation">(class="token string">"HTTP GET request failed: %s\n"class="token punctuation">, class="token function">esp_err_to_nameclass="token punctuation">(errclass="token punctuation">)class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token function">printfclass="token punctuation">(class="token string">"Response: %.*s\n"class="token punctuation">, class="token function">strlenclass="token punctuation">(local_response_bufferclass="token punctuation">)class="token punctuation">, local_response_bufferclass="token punctuation">)class="token punctuation">;class="token comment">//断开并释放资源class="token function">esp_class="tags" href="/HTTP.html" title=http>http_client_cleanupclass="token punctuation">(clientclass="token punctuation">)class="token punctuation">;class="token function">printfclass="token punctuation">(class="token string">"request -----------4\n"class="token punctuation">)class="token punctuation">;
class="token punctuation">}class="token keyword">void class="token function">class="tags" href="/HTTP.html" title=http>http_test_taskclass="token punctuation">(class="token keyword">void class="token operator">*argclass="token punctuation">)
class="token punctuation">{class="token function">sleepclass="token punctuation">(class="token number">15class="token punctuation">)class="token punctuation">;class="token function">requestclass="token punctuation">(HTTP_URLclass="token punctuation">)class="token punctuation">;class="token function">vTaskDeleteclass="token punctuation">(class="token constant">NULLclass="token punctuation">)class="token punctuation">;
class="token punctuation">}class="token comment">/*** @brief WiFi 的事件循环Handler* @param arg* @param event_base* @param event_id* @param event_data*/
class="token keyword">void class="token function">wifi_event_handlerclass="token punctuation">(class="token keyword">void class="token operator">*argclass="token punctuation">, class="token class-name">esp_event_base_t event_baseclass="token punctuation">, class="token class-name">int32_t event_idclass="token punctuation">, class="token keyword">void class="token operator">*event_dataclass="token punctuation">)
class="token punctuation">{class="token function">printfclass="token punctuation">(class="token string">"wifi_event_handler base:%s, id:%d\n"class="token punctuation">, event_baseclass="token punctuation">, event_idclass="token punctuation">)class="token punctuation">;class="token keyword">if class="token punctuation">(event_base class="token operator">== WIFI_EVENT class="token operator">&& event_id class="token operator">== WIFI_EVENT_STA_STARTclass="token punctuation">)class="token punctuation">{class="token function">printfclass="token punctuation">(class="token string">"esp_wifi_connect\n"class="token punctuation">)class="token punctuation">;class="token function">esp_wifi_connectclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">else class="token keyword">if class="token punctuation">(event_base class="token operator">== WIFI_EVENT class="token operator">&& event_id class="token operator">== WIFI_EVENT_STA_DISCONNECTEDclass="token punctuation">)class="token punctuation">{class="token function">printfclass="token punctuation">(class="token string">"esp_wifi_connect\n"class="token punctuation">)class="token punctuation">;class="token function">esp_wifi_connectclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token punctuation">}class="token keyword">if class="token punctuation">(event_base class="token operator">== IP_EVENT class="token operator">&& event_id class="token operator">== IP_EVENT_STA_GOT_IPclass="token punctuation">)class="token punctuation">{class="token class-name">ip_event_got_ip_t class="token operator">*event class="token operator">= class="token punctuation">(class="token class-name">ip_event_got_ip_t class="token operator">*class="token punctuation">)event_dataclass="token punctuation">;class="token function">ESP_LOGIclass="token punctuation">(class="token string">"ESP32"class="token punctuation">, class="token string">"IP地址:: " IPSTRclass="token punctuation">, class="token function">IP2STRclass="token punctuation">(class="token operator">&eventclass="token operator">->ip_infoclass="token punctuation">.ipclass="token punctuation">)class="token punctuation">)class="token punctuation">;class="token comment">//request(HTTP_URL); 问题点2: 获取到ip地址后,不要直接在这里执行class="tags" href="/HTTP.html" title=http>http请求, 否则会直接崩溃 , 这里注释掉不用class="token punctuation">}
class="token punctuation">}class="token keyword">void class="token function">app_mainclass="token punctuation">(class="token keyword">voidclass="token punctuation">)
class="token punctuation">{class="token class-name">esp_err_t ret class="token operator">= class="token function">nvs_flash_initclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 初始化默认NVS分区class="token keyword">if class="token punctuation">(ret class="token operator">== ESP_ERR_NVS_NO_FREE_PAGES class="token operator">|| ret class="token operator">== ESP_ERR_NVS_NEW_VERSION_FOUNDclass="token punctuation">)class="token punctuation">{class="token function">ESP_ERROR_CHECKclass="token punctuation">(class="token function">nvs_flash_eraseclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">; class="token comment">// 擦除默认NVS分区ret class="token operator">= class="token function">nvs_flash_initclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 初始化默认NVS分区class="token punctuation">}class="token function">ESP_ERROR_CHECKclass="token punctuation">(retclass="token punctuation">)class="token punctuation">;class="token function">ESP_ERROR_CHECKclass="token punctuation">(class="token function">esp_netif_initclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">; class="token comment">// 初始化底层TCP/IP堆栈class="token function">ESP_ERROR_CHECKclass="token punctuation">(class="token function">esp_event_loop_create_defaultclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">; class="token comment">// 创建默认事件循环class="token function">esp_netif_create_default_wifi_staclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 创建默认的WIFI STA。class="token class-name">wifi_init_config_t cfg class="token operator">= class="token function">WIFI_INIT_CONFIG_DEFAULTclass="token punctuation">(class="token punctuation">)class="token punctuation">;class="token function">esp_wifi_initclass="token punctuation">(class="token operator">&cfgclass="token punctuation">)class="token punctuation">; class="token comment">// 初始化WiFi为WiFi驱动程序class="token class-name">wifi_sta_config_t cfg_sta class="token operator">= class="token punctuation">{class="token punctuation">.ssid class="token operator">= class="token string">"black"class="token punctuation">,class="token punctuation">.password class="token operator">= class="token string">"black1234"class="token punctuation">,class="token punctuation">.thresholdclass="token punctuation">.authmode class="token operator">= WIFI_AUTH_WPA2_PSKclass="token punctuation">, class="token comment">//加密方式class="token punctuation">.pmf_cfg class="token operator">= class="token punctuation">{class="token punctuation">.capable class="token operator">= trueclass="token punctuation">,class="token punctuation">.required class="token operator">= falseclass="token punctuation">}class="token punctuation">,class="token punctuation">}class="token punctuation">;class="token function">esp_wifi_set_configclass="token punctuation">(WIFI_IF_STAclass="token punctuation">, class="token punctuation">(class="token class-name">wifi_config_t class="token operator">*class="token punctuation">)class="token operator">&cfg_staclass="token punctuation">)class="token punctuation">; class="token comment">// 设置ESP32 STA或AP的配置class="token function">esp_wifi_set_modeclass="token punctuation">(WIFI_MODE_STAclass="token punctuation">)class="token punctuation">; class="token comment">// 设置WiFi操作模式class="token comment">// 将事件处理程序的实例注册到默认循环中 任何事件class="token function">esp_event_handler_instance_registerclass="token punctuation">(WIFI_EVENTclass="token punctuation">, ESP_EVENT_ANY_IDclass="token punctuation">, wifi_event_handlerclass="token punctuation">, class="token constant">NULLclass="token punctuation">, class="token constant">NULLclass="token punctuation">)class="token punctuation">;class="token comment">// 将事件处理程序的实例注册到默认循环中 工作站从连接的AP获得IP事件class="token function">esp_event_handler_instance_registerclass="token punctuation">(IP_EVENTclass="token punctuation">, IP_EVENT_STA_GOT_IPclass="token punctuation">, wifi_event_handlerclass="token punctuation">, class="token constant">NULLclass="token punctuation">, class="token constant">NULLclass="token punctuation">)class="token punctuation">;class="token function">esp_wifi_startclass="token punctuation">(class="token punctuation">)class="token punctuation">; class="token comment">// 根据当前配置启动wificlass="token function">xTaskCreateclass="token punctuation">(class="token operator">&class="tags" href="/HTTP.html" title=http>http_test_taskclass="token punctuation">, class="token string">"class="tags" href="/HTTP.html" title=http>http_test_task"class="token punctuation">, class="token number">8192class="token punctuation">, class="token constant">NULLclass="token punctuation">, class="token number">5class="token punctuation">, class="token constant">NULLclass="token punctuation">)class="token punctuation">; class="token comment">//问题点3: 这里参数需要设置足够大的栈大小, 否则会导致崩溃, 可以根据实测来改, 最好MAX_HTTP_OUTPUT_BUFFER大,否则可能会崩溃.
class="token punctuation">}
code>
这样连上wifi后, class="tags" href="/HTTP.html" title=http>http get请求百度网页就正常了, 可以打印部分内容, 建议换成简单的页面的网址, 百度返回的数据太多了.
class="tags" href="/ESP32.html" title=esp32>esp32_433">class="tags" href="/ESP32.html" title=esp32>esp32相关文章
可见我的class="tags" href="/ESP32.html" title=esp32>esp32专栏
作者:帅得不敢出门 csdn原创谢绝转载