ESP WebSocket Client ==================== Overview -------- The ESP WebSocket client is an implementation of `WebSocket protocol client `_ for {IDF_TARGET_NAME} 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`` schemes - WebSocket samples: - ``ws://echo.websocket.org``: WebSocket over TCP, default port 80 - ``wss://echo.websocket.org``: WebSocket over SSL, default port 443 Minimal configurations: .. code:: c 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: .. code:: c 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 :cpp:type:`esp_websocket_client_config_t`, the option defined by the URI will be overridden. Sample: .. code:: c 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: .. code:: c 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 :cpp:type:`websocket_client_config_t`. If no certficate is provided then the TLS connection will default to 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. Mutual TLS with DS Peripheral """"""""""""""""""""""""""""" To leverage the Digital Signature (DS) peripheral on supported targets, use `esp_secure_cert_mgr `_ to flash an encrypted client certificate. In your project, add the dependency: :: idf.py add-dependency esp_secure_cert_mgr Set ``client_cert`` and ``client_ds_data`` in the config struct: .. code:: c char *client_cert = NULL; uint32_t client_cert_len = 0; esp_err_t err = esp_secure_cert_get_device_cert(&client_cert, &client_cert_len); assert(err == ESP_OK); esp_ds_data_ctx_t *ds_data = esp_secure_cert_get_ds_ctx(); assert(ds_data != NULL); esp_websocket_client_config_t config = { .uri = "wss://echo.websocket.org", .cert_pem = (const char *)websocket_org_pem_start, .client_cert = client_cert, .client_ds_data = ds_data, }; .. note:: ``client_cert`` provided by `esp_secure_cert_mgr` is a null-terminated PEM; so ``client_cert_len`` (DER format) should not be set. Subprotocol ^^^^^^^^^^^ The subprotocol field in the config struct can be used to request a subprotocol .. code:: c 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 :cpp:type:`esp_websocket_client_config_t`, please refer to API reference below Events ------ * `WEBSOCKET_EVENT_BEGIN`: The client thread is running. * `WEBSOCKET_EVENT_BEFORE_CONNECT`: The client is about to connect. * `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_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`: The client has experienced an error. Examples include transport write or read failures. * `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_CLOSED`: The connection has been closed cleanly. * `WEBSOCKET_EVENT_FINISH`: The client thread is about to exit. If the client handle is needed in the event handler it can be accessed through the pointer passed to the event handler: .. code:: c 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: `example `_ 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: .. code:: cpp esp_websocket_client_send_text(client, data, len, portMAX_DELAY); API Reference ------------- .. include-build-file:: inc/esp_websocket_client.inc