完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
单片机学习笔记 - 08 - WebSocket客户端 一、应用层协议 科普概念 在看例程之前先补补概念,我现在还是一脸懵逼,不知道这个是什么的状态。明明上一层的tcp已经能够通讯了,怎么又加多了一层。
二、编程指南 翻译 1. 概述
2. 特点
3. 配置 1)URI
// 最小的配置: const esp_websocket_client_config_t ws_cfg = { .uri = "ws://echo.websocket.org", }; // WebSocket客户端支持在URI中同时使用路径和查询。示例: const esp_websocket_client_config_t ws_cfg = { .uri = "ws://echo.websocket.org/connectionhandler?id=104", }; // 如果在 esp_websocket_client_config_t 中有任何与URI相关的选项,则URI定义的选项将被覆盖。示例: const esp_websocket_client_config_t ws_cfg = { .uri = "ws://echo.websocket.org:123", .port = 4567, //WebSocket客户端将使用端口4567连接到websocket.org }; 2)TLS
// 配置 const esp_websocket_client_config_t ws_cfg = { .uri = "wss://echo.websocket.org", .cert_pem = (const char *)websocket_org_pem_start, }; 3)子协议
// 配置结构中的子协议字段可用于请求子协议 const esp_websocket_client_config_t ws_cfg = { .uri = "ws://websocket.org", .subprotocol = "soap", }; 4. 事件
// 如果客户端句柄需要在事件处理程序中,它可以通过传递给事件处理程序的指针访问: esp_websocket_client_handle_t client = (esp_websocket_client_handle_t)handler_args; 5. 限制和已知问题
6. 应用举例
// WebSocket客户端支持以文本数据帧的形式发送数据,这告知应用层有效载荷数据是编码为UTF-8的文本数据。例子: esp_websocket_client_send_text(client, data, len, portMAX_DELAY); 三、例程解析
ESP_LOGI(TAG, "[APP] Startup.."); ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); esp_log_level_set("*", ESP_LOG_INFO); esp_log_level_set("WEBSOCKET_CLIENT", ESP_LOG_DEBUG); esp_log_level_set("TRANS_TCP", ESP_LOG_DEBUG); ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. * Read "Establishing Wi-Fi or Ethernet Connection" section in * examples/protocols/README.md for more information about this function. */ ESP_ERROR_CHECK(example_connect());
// 定时器超时函数 static void shutdown_signaler(TimerHandle_t xTimer) { ESP_LOGI(TAG, "No data received for %d seconds, signaling shutdown", NO_DATA_TIMEOUT_SEC); // 宏定义 释放信号量 xSemaphoreGive(shutdown_sema); } // 创建一个新的软件计时器实例,并返回一个句柄,通过这个句柄可以引用创建的软件计时器。 shutdown_signal_timer = xTimerCreate("Websocket shutdown timer", // 只是一个文本名称,不被内核使用。 NO_DATA_TIMEOUT_SEC * 1000 / portTICK_PERIOD_MS, // 计时器周期(单位是tick)。 pdFALSE, // 计时器将在到期时自动重新加载。(不会) NULL, // 为每个计时器分配一个唯一的id等于它的数组索引。 shutdown_signaler); // 每个计时器在到期时调用同一个回调。 // 创建一个新的二进制信号量实例,并返回一个句柄,通过这个句柄可以引用新的信号量。 shutdown_sema = xSemaphoreCreateBinary();
// 打包函数,用于获取uri字符串 #if CONFIG_WEBSOCKET_URI_FROM_STDIN static void get_string(char *line, size_t size) { int count = 0; while (count < size) { int c = fgetc(stdin); if (c == 'n') { line[count] = ' |