mirror of
https://github.com/espressif/esp-mqtt.git
synced 2025-07-29 18:28:24 +02:00
add support websocket
This commit is contained in:
13
examples/websocket/Makefile
Normal file
13
examples/websocket/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
PROJECT_NAME := websocket
|
||||
EXTRA_COMPONENT_DIRS += $(PROJECT_PATH)/../../../
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
1
examples/websocket/README.md
Normal file
1
examples/websocket/README.md
Normal file
@ -0,0 +1 @@
|
||||
# ESPMQTT Sample application
|
15
examples/websocket/main/Kconfig.projbuild
Normal file
15
examples/websocket/main/Kconfig.projbuild
Normal file
@ -0,0 +1,15 @@
|
||||
menu "Websocket Application sample"
|
||||
|
||||
config WIFI_SSID
|
||||
string "WiFi SSID"
|
||||
default "myssid"
|
||||
help
|
||||
SSID (network name) for the example to connect to.
|
||||
|
||||
config WIFI_PASSWORD
|
||||
string "WiFi Password"
|
||||
default "mypassword"
|
||||
help
|
||||
WiFi password (WPA or WPA2) for the example to use.
|
||||
|
||||
endmenu
|
130
examples/websocket/main/app_main.c
Executable file
130
examples/websocket/main/app_main.c
Executable file
@ -0,0 +1,130 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_system.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_event_loop.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "websocket_client.h"
|
||||
|
||||
static const char *TAG = "WEBSOCKET";
|
||||
|
||||
static EventGroupHandle_t wifi_event_group;
|
||||
const static int CONNECTED_BIT = BIT0;
|
||||
|
||||
|
||||
static esp_err_t websocket_event_handler(esp_websocket_event_handle_t event)
|
||||
{
|
||||
esp_websocket_client_handle_t client = event->client;
|
||||
// your_context_t *context = event->context;
|
||||
switch (event->event_id) {
|
||||
case WEBSOCKET_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "WEBSOCKET_EVENT_CONNECTED");
|
||||
|
||||
|
||||
break;
|
||||
case WEBSOCKET_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "WEBSOCKET_EVENT_DISCONNECTED");
|
||||
break;
|
||||
|
||||
case WEBSOCKET_EVENT_DATA:
|
||||
ESP_LOGI(TAG, "WEBSOCKET_EVENT_DATA");
|
||||
printf("DATA=%.*s\r\n", event->data_len, event->data);
|
||||
break;
|
||||
case WEBSOCKET_EVENT_ERROR:
|
||||
ESP_LOGI(TAG, "WEBSOCKET_EVENT_ERROR");
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t wifi_event_handler(void *ctx, system_event_t *event)
|
||||
{
|
||||
switch (event->event_id) {
|
||||
case SYSTEM_EVENT_STA_START:
|
||||
esp_wifi_connect();
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
|
||||
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
esp_wifi_connect();
|
||||
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void wifi_init(void)
|
||||
{
|
||||
tcpip_adapter_init();
|
||||
wifi_event_group = xEventGroupCreate();
|
||||
ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL));
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = CONFIG_WIFI_SSID,
|
||||
.password = CONFIG_WIFI_PASSWORD,
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
|
||||
ESP_LOGI(TAG, "start the WIFI SSID:[%s] password:[%s]", CONFIG_WIFI_SSID, "******");
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
ESP_LOGI(TAG, "Waiting for wifi");
|
||||
xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
|
||||
}
|
||||
|
||||
static void websocket_app_start(void)
|
||||
{
|
||||
const esp_websocket_client_config_t websocket_cfg = {
|
||||
.uri = "ws://echo.websocket.org",
|
||||
.event_handle = websocket_event_handler,
|
||||
// .user_context = (void *)your_context
|
||||
};
|
||||
|
||||
esp_websocket_client_handle_t client = esp_websocket_client_init(&websocket_cfg);
|
||||
esp_websocket_client_start(client);
|
||||
while(1) {
|
||||
if (esp_websocket_client_is_connected(client)) {
|
||||
esp_websocket_client_send(client, "hello", 5);
|
||||
}
|
||||
vTaskDelay(500/portTICK_RATE_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
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_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
|
||||
|
||||
nvs_flash_init();
|
||||
wifi_init();
|
||||
websocket_app_start();
|
||||
}
|
0
examples/websocket/main/component.mk
Normal file
0
examples/websocket/main/component.mk
Normal file
70
include/websocket_client.h
Executable file
70
include/websocket_client.h
Executable file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions defined in
|
||||
* file 'LICENSE', which is part of this source code package.
|
||||
* Tuan PM <tuanpm at live dot com>
|
||||
*/
|
||||
|
||||
#ifndef _WEBSOCKET_CLIENT_H_
|
||||
#define _WEBSOCKET_CLIENT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mqtt_config.h"
|
||||
|
||||
typedef struct esp_websocket_client* esp_websocket_client_handle_t;
|
||||
|
||||
typedef enum {
|
||||
WEBSOCKET_EVENT_ERROR = 0,
|
||||
WEBSOCKET_EVENT_CONNECTED,
|
||||
WEBSOCKET_EVENT_DISCONNECTED,
|
||||
WEBSOCKET_EVENT_DATA,
|
||||
} esp_websocket_event_id_t;
|
||||
|
||||
typedef enum {
|
||||
WEBSOCKET_TRANSPORT_UNKNOWN = 0x0,
|
||||
WEBSOCKET_TRANSPORT_OVER_TCP,
|
||||
WEBSOCKET_TRANSPORT_OVER_SSL,
|
||||
} esp_websocket_transport_t;
|
||||
|
||||
typedef struct {
|
||||
esp_websocket_event_id_t event_id;
|
||||
esp_websocket_client_handle_t client;
|
||||
void *user_context;
|
||||
char *data;
|
||||
int data_len;
|
||||
} esp_websocket_event_t;
|
||||
|
||||
typedef esp_websocket_event_t* esp_websocket_event_handle_t;
|
||||
|
||||
typedef esp_err_t (* websocket_event_callback_t)(esp_websocket_event_handle_t event);
|
||||
|
||||
|
||||
typedef struct {
|
||||
websocket_event_callback_t event_handle;
|
||||
const char *uri;
|
||||
const char *scheme;
|
||||
const char *host;
|
||||
int port;
|
||||
const char *username;
|
||||
const char *password;
|
||||
const char *path;
|
||||
bool disable_auto_reconnect;
|
||||
void *user_context;
|
||||
int task_prio;
|
||||
int task_stack;
|
||||
int buffer_size;
|
||||
const char *cert_pem;
|
||||
esp_websocket_transport_t transport;
|
||||
} esp_websocket_client_config_t;
|
||||
|
||||
esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_client_config_t *config);
|
||||
esp_err_t esp_websocket_client_set_uri(esp_websocket_client_handle_t client, const char *uri);
|
||||
esp_err_t esp_websocket_client_start(esp_websocket_client_handle_t client);
|
||||
esp_err_t esp_websocket_client_stop(esp_websocket_client_handle_t client);
|
||||
esp_err_t esp_websocket_client_destroy(esp_websocket_client_handle_t client);
|
||||
int esp_websocket_client_send(esp_websocket_client_handle_t client, const char *data, int len);
|
||||
bool esp_websocket_client_is_connected(esp_websocket_client_handle_t client);
|
||||
|
||||
#endif
|
435
websocket_client.c
Normal file
435
websocket_client.c
Normal file
@ -0,0 +1,435 @@
|
||||
#include <stdio.h>
|
||||
#include "platform.h"
|
||||
|
||||
#include "websocket_client.h"
|
||||
#include "transport.h"
|
||||
#include "transport_tcp.h"
|
||||
#include "transport_ssl.h"
|
||||
#include "transport_ws.h"
|
||||
#include "platform.h"
|
||||
|
||||
/* using uri parser */
|
||||
#include "http_parser.h"
|
||||
|
||||
static const char *TAG = "WEBSOCKET_CLIENT";
|
||||
|
||||
#define WEBSOCKET_TCP_DEFAULT_PORT (80)
|
||||
#define WEBSOCKET_SSL_DEFAULT_PORT (443)
|
||||
#define WEBSOCKET_BUFFER_SIZE_BYTE (1024)
|
||||
#define WEBSOCKET_RECONNECT_TIMEOUT_MS (10*1000)
|
||||
#define WEBSOCKET_TASK_PRIORITY (5)
|
||||
#define WEBSOCKET_TASK_STACK (4*1024)
|
||||
#define WEBSOCKET_NETWORK_TIMEOUT_MS (10*1000)
|
||||
|
||||
const static int STOPPED_BIT = BIT0;
|
||||
|
||||
typedef struct {
|
||||
websocket_event_callback_t event_handle;
|
||||
int task_stack;
|
||||
int task_prio;
|
||||
char *uri;
|
||||
char *host;
|
||||
char *path;
|
||||
char *scheme;
|
||||
char *username;
|
||||
char *password;
|
||||
int port;
|
||||
bool auto_reconnect;
|
||||
void *user_context;
|
||||
int network_timeout_ms;
|
||||
} websockeet_config_storage_t;
|
||||
|
||||
typedef enum {
|
||||
WEBSOCKET_STATE_ERROR = -1,
|
||||
WEBSOCKET_STATE_UNKNOW = 0,
|
||||
WEBSOCKET_STATE_INIT,
|
||||
WEBSOCKET_STATE_CONNECTED,
|
||||
WEBSOCKET_STATE_WAIT_TIMEOUT,
|
||||
} websocket_client_state_t;
|
||||
|
||||
struct esp_websocket_client {
|
||||
transport_list_handle_t transport_list;
|
||||
transport_handle_t transport;
|
||||
websockeet_config_storage_t *config;
|
||||
websocket_client_state_t state;
|
||||
long long keepalive_tick;
|
||||
long long reconnect_tick;
|
||||
int wait_timeout_ms;
|
||||
int auto_reconnect;
|
||||
esp_websocket_event_t event;
|
||||
bool run;
|
||||
EventGroupHandle_t status_bits;
|
||||
char *buffer;
|
||||
int buffer_size;
|
||||
};
|
||||
|
||||
static char *create_string(const char *ptr, int len)
|
||||
{
|
||||
char *ret;
|
||||
if (len <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
ret = calloc(1, len + 1);
|
||||
mem_assert(ret);
|
||||
memcpy(ret, ptr, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_websocket_client_dispatch_event(esp_websocket_client_handle_t client)
|
||||
{
|
||||
client->event.user_context = client->config->user_context;
|
||||
client->event.client = client;
|
||||
|
||||
if (client->config->event_handle) {
|
||||
return client->config->event_handle(&client->event);
|
||||
}
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
static esp_err_t esp_websocket_client_abort_connection(esp_websocket_client_handle_t client)
|
||||
{
|
||||
transport_close(client->transport);
|
||||
client->wait_timeout_ms = WEBSOCKET_RECONNECT_TIMEOUT_MS;
|
||||
client->reconnect_tick = platform_tick_get_ms();
|
||||
client->state = WEBSOCKET_STATE_WAIT_TIMEOUT;
|
||||
ESP_LOGI(TAG, "Reconnect after %d ms", client->wait_timeout_ms);
|
||||
client->event.event_id = WEBSOCKET_EVENT_DISCONNECTED;
|
||||
esp_websocket_client_dispatch_event(client);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_websocket_client_set_config(esp_websocket_client_handle_t client, const esp_websocket_client_config_t *config)
|
||||
{
|
||||
//Copy user configurations to client context
|
||||
websockeet_config_storage_t *cfg = calloc(1, sizeof(websockeet_config_storage_t));
|
||||
mem_assert(cfg);
|
||||
|
||||
cfg->task_prio = config->task_prio;
|
||||
if (cfg->task_prio <= 0) {
|
||||
cfg->task_prio = WEBSOCKET_TASK_PRIORITY;
|
||||
}
|
||||
|
||||
cfg->task_stack = config->task_stack;
|
||||
if (cfg->task_stack == 0) {
|
||||
cfg->task_stack = WEBSOCKET_TASK_STACK;
|
||||
}
|
||||
|
||||
if (config->host) {
|
||||
cfg->host = strdup(config->host);
|
||||
}
|
||||
|
||||
cfg->port = config->port;
|
||||
|
||||
if (config->username) {
|
||||
cfg->username = strdup(config->username);
|
||||
}
|
||||
|
||||
if (config->password) {
|
||||
cfg->password = strdup(config->password);
|
||||
}
|
||||
|
||||
if (config->uri) {
|
||||
cfg->uri = strdup(config->uri);
|
||||
}
|
||||
|
||||
cfg->network_timeout_ms = WEBSOCKET_NETWORK_TIMEOUT_MS;
|
||||
cfg->user_context = config->user_context;
|
||||
cfg->event_handle = config->event_handle;
|
||||
cfg->auto_reconnect = true;
|
||||
if (config->disable_auto_reconnect) {
|
||||
cfg->auto_reconnect = false;
|
||||
}
|
||||
|
||||
client->config = cfg;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_websocket_client_destroy_config(esp_websocket_client_handle_t client)
|
||||
{
|
||||
websockeet_config_storage_t *cfg = client->config;
|
||||
if (cfg->host) {
|
||||
free(cfg->host);
|
||||
}
|
||||
if (cfg->uri) {
|
||||
free(cfg->uri);
|
||||
}
|
||||
if (cfg->path) {
|
||||
free(cfg->path);
|
||||
}
|
||||
if (cfg->scheme) {
|
||||
free(cfg->scheme);
|
||||
}
|
||||
if (cfg->username) {
|
||||
free(cfg->username);
|
||||
}
|
||||
if (cfg->password) {
|
||||
free(cfg->password);
|
||||
}
|
||||
|
||||
free(client->config);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_client_config_t *config)
|
||||
{
|
||||
esp_websocket_client_handle_t client = calloc(1, sizeof(struct esp_websocket_client));
|
||||
mem_assert(client);
|
||||
|
||||
client->transport_list = transport_list_init();
|
||||
|
||||
transport_handle_t tcp = transport_tcp_init();
|
||||
transport_set_default_port(tcp, WEBSOCKET_TCP_DEFAULT_PORT);
|
||||
transport_list_add(client->transport_list, tcp, "_tcp");
|
||||
|
||||
|
||||
transport_handle_t ws = transport_ws_init(tcp);
|
||||
transport_set_default_port(ws, WEBSOCKET_TCP_DEFAULT_PORT);
|
||||
transport_list_add(client->transport_list, ws, "ws");
|
||||
if (config->transport == WEBSOCKET_TRANSPORT_OVER_TCP) {
|
||||
client->config->scheme = create_string("ws", 2);
|
||||
}
|
||||
|
||||
transport_handle_t ssl = transport_ssl_init();
|
||||
transport_set_default_port(ssl, WEBSOCKET_SSL_DEFAULT_PORT);
|
||||
if (config->cert_pem) {
|
||||
transport_ssl_set_cert_data(ssl, config->cert_pem, strlen(config->cert_pem));
|
||||
}
|
||||
transport_list_add(client->transport_list, ssl, "_ssl");
|
||||
|
||||
transport_handle_t wss = transport_ws_init(ssl);
|
||||
transport_set_default_port(wss, WEBSOCKET_SSL_DEFAULT_PORT);
|
||||
transport_list_add(client->transport_list, wss, "wss");
|
||||
if (config->transport == WEBSOCKET_TRANSPORT_OVER_TCP) {
|
||||
client->config->scheme = create_string("wss", 3);
|
||||
}
|
||||
|
||||
esp_websocket_client_set_config(client, config);
|
||||
|
||||
if (client->config->uri) {
|
||||
if (esp_websocket_client_set_uri(client, client->config->uri) != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (client->config->scheme == NULL) {
|
||||
client->config->scheme = create_string("ws", 2);
|
||||
}
|
||||
|
||||
client->keepalive_tick = platform_tick_get_ms();
|
||||
client->reconnect_tick = platform_tick_get_ms();
|
||||
|
||||
int buffer_size = config->buffer_size;
|
||||
if (buffer_size <= 0) {
|
||||
buffer_size = WEBSOCKET_BUFFER_SIZE_BYTE;
|
||||
}
|
||||
|
||||
client->buffer = malloc(buffer_size);
|
||||
assert(client->buffer);
|
||||
client->buffer_size = buffer_size;
|
||||
|
||||
esp_websocket_client_set_config(client, config);
|
||||
if (config->uri) {
|
||||
esp_websocket_client_set_uri(client, config->uri);
|
||||
}
|
||||
|
||||
client->status_bits = xEventGroupCreate();
|
||||
return client;
|
||||
}
|
||||
|
||||
esp_err_t esp_websocket_client_destroy(esp_websocket_client_handle_t client)
|
||||
{
|
||||
esp_websocket_client_stop(client);
|
||||
esp_websocket_client_destroy_config(client);
|
||||
transport_list_destroy(client->transport_list);
|
||||
free(client->buffer);
|
||||
vEventGroupDelete(client->status_bits);
|
||||
free(client);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_websocket_client_set_uri(esp_websocket_client_handle_t client, const char *uri)
|
||||
{
|
||||
struct http_parser_url puri;
|
||||
http_parser_url_init(&puri);
|
||||
int parser_status = http_parser_parse_url(uri, strlen(uri), 0, &puri);
|
||||
if (parser_status != 0) {
|
||||
ESP_LOGE(TAG, "Error parse uri = %s", uri);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (client->config->scheme == NULL) {
|
||||
client->config->scheme = create_string(uri + puri.field_data[UF_SCHEMA].off, puri.field_data[UF_SCHEMA].len);
|
||||
}
|
||||
|
||||
if (client->config->host == NULL) {
|
||||
client->config->host = create_string(uri + puri.field_data[UF_HOST].off, puri.field_data[UF_HOST].len);
|
||||
}
|
||||
|
||||
if (client->config->path == NULL) {
|
||||
client->config->path = create_string(uri + puri.field_data[UF_PATH].off, puri.field_data[UF_PATH].len);
|
||||
}
|
||||
|
||||
if (client->config->path) {
|
||||
transport_handle_t trans = transport_list_get_transport(client->transport_list, "ws");
|
||||
if (trans) {
|
||||
transport_ws_set_path(trans, client->config->path);
|
||||
}
|
||||
trans = transport_list_get_transport(client->transport_list, "wss");
|
||||
if (trans) {
|
||||
transport_ws_set_path(trans, client->config->path);
|
||||
}
|
||||
}
|
||||
|
||||
char *port = create_string(uri + puri.field_data[UF_PORT].off, puri.field_data[UF_PORT].len);
|
||||
if (port) {
|
||||
client->config->port = atoi(port);
|
||||
free(port);
|
||||
}
|
||||
|
||||
char *user_info = create_string(uri + puri.field_data[UF_USERINFO].off, puri.field_data[UF_USERINFO].len);
|
||||
if (user_info) {
|
||||
char *pass = strchr(user_info, ':');
|
||||
if (pass) {
|
||||
pass[0] = 0; //terminal username
|
||||
pass ++;
|
||||
client->config->password = strdup(pass);
|
||||
}
|
||||
client->config->username = strdup(user_info);
|
||||
|
||||
free(user_info);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static void esp_websocket_client_task(void *pv)
|
||||
{
|
||||
int rlen;
|
||||
esp_websocket_client_handle_t client = (esp_websocket_client_handle_t) pv;
|
||||
client->run = true;
|
||||
|
||||
//get transport by scheme
|
||||
client->transport = transport_list_get_transport(client->transport_list, client->config->scheme);
|
||||
|
||||
if (client->transport == NULL) {
|
||||
ESP_LOGE(TAG, "There are no transports valid, stop websocket client");
|
||||
client->run = false;
|
||||
}
|
||||
//default port
|
||||
if (client->config->port == 0) {
|
||||
client->config->port = transport_get_default_port(client->transport);
|
||||
}
|
||||
|
||||
client->state = WEBSOCKET_STATE_INIT;
|
||||
xEventGroupClearBits(client->status_bits, STOPPED_BIT);
|
||||
|
||||
while (client->run) {
|
||||
switch ((int)client->state) {
|
||||
case WEBSOCKET_STATE_INIT:
|
||||
if (client->transport == NULL) {
|
||||
ESP_LOGE(TAG, "There are no transport");
|
||||
client->run = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (transport_connect(client->transport,
|
||||
client->config->host,
|
||||
client->config->port,
|
||||
client->config->network_timeout_ms) < 0) {
|
||||
ESP_LOGE(TAG, "Error transport connect");
|
||||
esp_websocket_client_abort_connection(client);
|
||||
break;
|
||||
}
|
||||
ESP_LOGD(TAG, "Transport connected to %s://%s:%d", client->config->scheme, client->config->host, client->config->port);
|
||||
|
||||
client->event.event_id = WEBSOCKET_EVENT_CONNECTED;
|
||||
client->state = WEBSOCKET_STATE_CONNECTED;
|
||||
esp_websocket_client_dispatch_event(client);
|
||||
|
||||
break;
|
||||
case WEBSOCKET_STATE_CONNECTED:
|
||||
rlen = transport_read(client->transport, client->buffer, client->buffer_size, client->config->network_timeout_ms);
|
||||
if (rlen < 0) {
|
||||
ESP_LOGE(TAG, "Error read data");
|
||||
esp_websocket_client_abort_connection(client);
|
||||
break;
|
||||
}
|
||||
if (rlen > 0) {
|
||||
client->event.event_id = WEBSOCKET_EVENT_DATA;
|
||||
client->event.data = client->buffer;
|
||||
client->event.data_len = rlen;
|
||||
esp_websocket_client_dispatch_event(client);
|
||||
}
|
||||
break;
|
||||
case WEBSOCKET_STATE_WAIT_TIMEOUT:
|
||||
|
||||
if (!client->config->auto_reconnect) {
|
||||
client->run = false;
|
||||
break;
|
||||
}
|
||||
if (platform_tick_get_ms() - client->reconnect_tick > client->wait_timeout_ms) {
|
||||
client->state = WEBSOCKET_STATE_INIT;
|
||||
client->reconnect_tick = platform_tick_get_ms();
|
||||
ESP_LOGD(TAG, "Reconnecting...");
|
||||
}
|
||||
vTaskDelay(client->wait_timeout_ms / 2 / portTICK_RATE_MS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
transport_close(client->transport);
|
||||
xEventGroupSetBits(client->status_bits, STOPPED_BIT);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
esp_err_t esp_websocket_client_start(esp_websocket_client_handle_t client)
|
||||
{
|
||||
if (client->state >= WEBSOCKET_STATE_INIT) {
|
||||
ESP_LOGE(TAG, "Client has started");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (xTaskCreate(esp_websocket_client_task, "websocket_task", client->config->task_stack, client, client->config->task_prio, NULL) != pdTRUE) {
|
||||
ESP_LOGE(TAG, "Error create websocket task");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
xEventGroupClearBits(client->status_bits, STOPPED_BIT);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_websocket_client_stop(esp_websocket_client_handle_t client)
|
||||
{
|
||||
client->run = false;
|
||||
xEventGroupWaitBits(client->status_bits, STOPPED_BIT, false, true, portMAX_DELAY);
|
||||
client->state = WEBSOCKET_STATE_UNKNOW;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
int esp_websocket_client_send(esp_websocket_client_handle_t client, const char *data, int len)
|
||||
{
|
||||
int need_write = len;
|
||||
int wlen = 0, widx = 0;
|
||||
while (widx < len) {
|
||||
if (need_write > client->buffer_size) {
|
||||
need_write = client->buffer_size;
|
||||
}
|
||||
memcpy(client->buffer, data + widx, need_write);
|
||||
wlen = transport_write(client->transport,
|
||||
(char *)client->buffer,
|
||||
need_write,
|
||||
client->config->network_timeout_ms);
|
||||
if (wlen <= 0) {
|
||||
return wlen;
|
||||
}
|
||||
widx += wlen;
|
||||
need_write = len - widx;
|
||||
}
|
||||
return widx;
|
||||
}
|
||||
|
||||
bool esp_websocket_client_is_connected(esp_websocket_client_handle_t client)
|
||||
{
|
||||
return client->state == WEBSOCKET_STATE_CONNECTED;
|
||||
}
|
Reference in New Issue
Block a user