ESP WebSocket Client
Overview
The ESP WebSocket client is an implementation of WebSocket protocol client for ESP32
Features
Supports WebSocket over TCP, TLS with mbedtls
Easy to setup with URI
Multiple instances (Multiple clients in one application)
Configuration
URI
Supports
ws
,wss
schemesWebSocket samples:
ws://echo.websocket.org
: WebSocket over TCP, default port 80wss://echo.websocket.org
: WebSocket over SSL, default port 443
Minimal configurations:
const esp_websocket_client_config_t ws_cfg = {
.uri = "ws://echo.websocket.org",
};
The WebSocket client supports the use of both path and query in the URI. Sample:
const esp_websocket_client_config_t ws_cfg = {
.uri = "ws://echo.websocket.org/connectionhandler?id=104",
};
If there are any options related to the URI in
esp_websocket_client_config_t
, the option defined by the URI will be
overridden. Sample:
const esp_websocket_client_config_t ws_cfg = {
.uri = "ws://echo.websocket.org:123",
.port = 4567,
};
//WebSocket client will connect to websocket.org using port 4567
TLS
Configuration:
const esp_websocket_client_config_t ws_cfg = {
.uri = "wss://echo.websocket.org",
.cert_pem = (const char *)websocket_org_pem_start,
};
Note
If you want to verify the server, then you need to provide a certificate in PEM format, and provide to cert_pem
in websocket_client_config_t
. If no certficate is provided then the TLS connection will to default not requiring verification.
PEM certificate for this example could be extracted from an openssl s_client command connecting to websocket.org.
In case a host operating system has openssl and sed packages installed, one could execute the following command to download and save the root or intermediate root certificate to a file (Note for Windows users: Both Linux like environment or Windows native packages may be used).
`
echo "" | openssl s_client -showcerts -connect websocket.org:443 | sed -n "1,/Root/d; /BEGIN/,/END/p" | openssl x509 -outform PEM >websocket_org.pem
`
This command will extract the second certificate in the chain and save it as a pem-file.
Subprotocol
The subprotocol field in the config struct can be used to request a subprotocol
const esp_websocket_client_config_t ws_cfg = {
.uri = "ws://websocket.org",
.subprotocol = "soap",
};
Note
The client is indifferent to the subprotocol field in the server response and will accept the connection no matter what the server replies.
For more options on esp_websocket_client_config_t
, please refer to API reference below
Events
WEBSOCKET_EVENT_CONNECTED: The client has successfully established a connection to the server. The client is now ready to send and receive data. Contains no event data.
WEBSOCKET_EVENT_DISCONNECTED: The client has aborted the connection due to the transport layer failing to read data, e.g. because the server is unavailable. Contains no event data.
WEBSOCKET_EVENT_DATA: The client has successfully received and parsed a WebSocket frame. The event data contains a pointer to the payload data, the length of the payload data as well as the opcode of the received frame. A message may be fragmented into multiple events if the length exceeds the buffer size. This event will also be posted for non-payload frames, e.g. pong or connection close frames.
WEBSOCKET_EVENT_ERROR: Not used in the current implementation of the client.
If the client handle is needed in the event handler it can be accessed through the pointer passed to the event handler:
esp_websocket_client_handle_t client = (esp_websocket_client_handle_t)handler_args;
Limitations and Known Issues
The client is able to request the use of a subprotocol from the server during the handshake, but does not do any subprotocol related checks on the response from the server.
Application Example
A simple WebSocket example that uses esp_websocket_client to establish a websocket connection and send/receive data with the websocket.org server can be found here: protocols/websocket.
Sending Text Data
The WebSocket client supports sending data as a text data frame, which informs the application layer that the payload data is text data encoded as UTF-8. Example:
esp_websocket_client_send_text(client, data, len, portMAX_DELAY);
API Reference
Functions
-
esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_client_config_t *config)
Start a Websocket session This function must be the first function to call, and it returns a esp_websocket_client_handle_t that you must use as input to other functions in the interface. This call MUST have a corresponding call to esp_websocket_client_destroy when the operation is complete.
- Parameters
config – [in] The configuration
- Returns
esp_websocket_client_handle_t
NULL if any errors
-
esp_err_t esp_websocket_client_set_uri(esp_websocket_client_handle_t client, const char *uri)
Set URL for client, when performing this behavior, the options in the URL will replace the old ones Must stop the WebSocket client before set URI if the client has been connected.
- Parameters
client – [in] The client
uri – [in] The uri
- Returns
esp_err_t
-
esp_err_t esp_websocket_client_start(esp_websocket_client_handle_t client)
Open the WebSocket connection.
- Parameters
client – [in] The client
- Returns
esp_err_t
-
esp_err_t esp_websocket_client_stop(esp_websocket_client_handle_t client)
Stops the WebSocket connection without websocket closing handshake.
This API stops ws client and closes TCP connection directly without sending close frames. It is a good practice to close the connection in a clean way using esp_websocket_client_close().
Notes:
Cannot be called from the websocket event handler
- Parameters
client – [in] The client
- Returns
esp_err_t
-
esp_err_t esp_websocket_client_destroy(esp_websocket_client_handle_t client)
Destroy the WebSocket connection and free all resources. This function must be the last function to call for an session. It is the opposite of the esp_websocket_client_init function and must be called with the same handle as input that a esp_websocket_client_init call returned. This might close all connections this handle has used.
Notes:
Cannot be called from the websocket event handler
- Parameters
client – [in] The client
- Returns
esp_err_t
-
int esp_websocket_client_send(esp_websocket_client_handle_t client, const char *data, int len, TickType_t timeout)
Generic write data to the WebSocket connection; defaults to binary send.
- Parameters
client – [in] The client
data – [in] The data
len – [in] The length
timeout – [in] Write data timeout in RTOS ticks
- Returns
Number of data was sent
(-1) if any errors
-
int esp_websocket_client_send_bin(esp_websocket_client_handle_t client, const char *data, int len, TickType_t timeout)
Write binary data to the WebSocket connection (data send with WS OPCODE=02, i.e. binary)
- Parameters
client – [in] The client
data – [in] The data
len – [in] The length
timeout – [in] Write data timeout in RTOS ticks
- Returns
Number of data was sent
(-1) if any errors
-
int esp_websocket_client_send_text(esp_websocket_client_handle_t client, const char *data, int len, TickType_t timeout)
Write textual data to the WebSocket connection (data send with WS OPCODE=01, i.e. text)
- Parameters
client – [in] The client
data – [in] The data
len – [in] The length
timeout – [in] Write data timeout in RTOS ticks
- Returns
Number of data was sent
(-1) if any errors
-
esp_err_t esp_websocket_client_close(esp_websocket_client_handle_t client, TickType_t timeout)
Close the WebSocket connection in a clean way.
Sequence of clean close initiated by client:
Client sends CLOSE frame
Client waits until server echos the CLOSE frame
Client waits until server closes the connection
Client is stopped the same way as by the
esp_websocket_client_stop()
Notes:
Cannot be called from the websocket event handler
- Parameters
client – [in] The client
timeout – [in] Timeout in RTOS ticks for waiting
- Returns
esp_err_t
-
esp_err_t esp_websocket_client_close_with_code(esp_websocket_client_handle_t client, int code, const char *data, int len, TickType_t timeout)
Close the WebSocket connection in a clean way with custom code/data Closing sequence is the same as for esp_websocket_client_close()
Notes:
Cannot be called from the websocket event handler
- Parameters
client – [in] The client
code – [in] Close status code as defined in RFC6455 section-7.4
data – [in] Additional data to closing message
len – [in] The length of the additional data
timeout – [in] Timeout in RTOS ticks for waiting
- Returns
esp_err_t
-
bool esp_websocket_client_is_connected(esp_websocket_client_handle_t client)
Check the WebSocket client connection state.
- Parameters
client – [in] The client handle
- Returns
true
false
-
esp_err_t esp_websocket_register_events(esp_websocket_client_handle_t client, esp_websocket_event_id_t event, esp_event_handler_t event_handler, void *event_handler_arg)
Register the Websocket Events.
- Parameters
client – The client handle
event – The event id
event_handler – The callback function
event_handler_arg – User context
- Returns
esp_err_t
Structures
-
struct esp_websocket_event_data_t
Websocket event data.
Public Members
-
const char *data_ptr
Data pointer
-
int data_len
Data length
-
uint8_t op_code
Received opcode
-
esp_websocket_client_handle_t client
esp_websocket_client_handle_t context
-
void *user_context
user_data context, from esp_websocket_client_config_t user_data
-
int payload_len
Total payload length, payloads exceeding buffer will be posted through multiple events
-
int payload_offset
Actual offset for the data associated with this event
-
const char *data_ptr
-
struct esp_websocket_client_config_t
Websocket client setup configuration.
Public Members
-
const char *uri
Websocket URI, the information on the URI can be overrides the other fields below, if any
-
const char *host
Domain or IP as string
-
int port
Port to connect, default depend on esp_websocket_transport_t (80 or 443)
-
const char *username
Using for Http authentication - Not supported for now
-
const char *password
Using for Http authentication - Not supported for now
-
const char *path
HTTP Path, if not set, default is
/
-
bool disable_auto_reconnect
Disable the automatic reconnect function when disconnected
-
void *user_context
HTTP user data context
-
int task_prio
Websocket task priority
-
int task_stack
Websocket task stack
-
int buffer_size
Websocket buffer size
-
const char *cert_pem
Pointer to certificate data in PEM or DER format for server verify (with SSL), default is NULL, not required to verify the server. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in cert_len.
-
size_t cert_len
Length of the buffer pointed to by cert_pem. May be 0 for null-terminated pem
-
const char *client_cert
Pointer to certificate data in PEM or DER format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also
client_key
has to be provided. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in client_cert_len.
-
size_t client_cert_len
Length of the buffer pointed to by client_cert. May be 0 for null-terminated pem
-
const char *client_key
Pointer to private key data in PEM or DER format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also
client_cert
has to be provided. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in client_key_len
-
size_t client_key_len
Length of the buffer pointed to by client_key_pem. May be 0 for null-terminated pem
-
esp_websocket_transport_t transport
Websocket transport type, see `esp_websocket_transport_t
-
const char *subprotocol
Websocket subprotocol
-
const char *user_agent
Websocket user-agent
-
const char *headers
Websocket additional headers
-
int pingpong_timeout_sec
Period before connection is aborted due to no PONGs received
-
bool disable_pingpong_discon
Disable auto-disconnect due to no PONG received within pingpong_timeout_sec
-
bool use_global_ca_store
Use a global ca_store for all the connections in which this bool is set.
-
bool skip_cert_common_name_check
Skip any validation of server certificate CN field
-
bool keep_alive_enable
Enable keep-alive timeout
-
int keep_alive_idle
Keep-alive idle time. Default is 5 (second)
-
int keep_alive_interval
Keep-alive interval time. Default is 5 (second)
-
int keep_alive_count
Keep-alive packet retry send count. Default is 3 counts
-
size_t ping_interval_sec
Websocket ping interval, defaults to 10 seconds if not set
-
struct ifreq *if_name
The name of interface for data to go through. Use the default interface without setting
-
const char *uri
Enumerations
-
enum esp_websocket_event_id_t
Websocket Client events id.
Values:
-
enumerator WEBSOCKET_EVENT_ANY
-
enumerator WEBSOCKET_EVENT_ERROR
This event occurs when there are any errors during execution
-
enumerator WEBSOCKET_EVENT_CONNECTED
Once the Websocket has been connected to the server, no data exchange has been performed
-
enumerator WEBSOCKET_EVENT_DISCONNECTED
The connection has been disconnected
-
enumerator WEBSOCKET_EVENT_DATA
When receiving data from the server, possibly multiple portions of the packet
-
enumerator WEBSOCKET_EVENT_CLOSED
The connection has been closed cleanly
-
enumerator WEBSOCKET_EVENT_MAX
-
enumerator WEBSOCKET_EVENT_ANY