add inital websocket client

This commit is contained in:
Laila van Reenen 2024-07-25 17:40:35 +02:00
parent 8b1f8457b4
commit d45a88ed00
Signed by: LailaTheElf
GPG Key ID: 1F4E6EE3E6DDF769
10 changed files with 268 additions and 50 deletions

View File

@ -1,6 +1,12 @@
cmake_minimum_required(VERSION 3.16.0)
set(COMPONENT_DIRS $ENV{IDF_PATH}/components $ENV{IDF_PATH}/../idf-extra-components/led_strip ./lib ./src)
set(COMPONENT_DIRS
$ENV{IDF_PATH}/components
$ENV{IDF_PATH}/../idf-extra-components/led_strip
$ENV{IDF_PATH}/../esp-protocols/components/esp_websocket_client
./lib
./src
)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(rx_esp32)

View File

@ -4,6 +4,6 @@ dependencies:
source:
type: idf
version: 5.2.2
manifest_hash: 25da577a782e8f239c184378e32f45cca356a1cf3257d50b4f7446629da3faa1
manifest_hash: 0646c148cf0e35f84678cd2cb46e9929051a1c6db31905f3a584cca01fd1e49a
target: esp32c6
version: 1.0.0

View File

@ -1835,6 +1835,12 @@ CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30
CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y
# CONFIG_WIFI_PROV_STA_FAST_SCAN is not set
# end of Wi-Fi Provisioning Manager
#
# ESP WebSocket client
#
# CONFIG_ESP_WS_CLIENT_ENABLE_DYNAMIC_BUFFER is not set
# end of ESP WebSocket client
# end of Component config
# CONFIG_IDF_EXPERIMENTAL_FEATURES is not set

View File

@ -11,6 +11,7 @@ idf_component_register(
./commands.c
./servos.c
./logger.c
./ws.c
INCLUDE_DIRS "./"
PRIV_REQUIRES
# project components
@ -18,5 +19,6 @@ idf_component_register(
# idf extra components
led_strip
# idf base components
esp_websocket_client
spi_flash driver nvs_flash esp_wifi
)

View File

@ -24,4 +24,9 @@
#define SERVOS_CH5
#define SERVOS_CH6
#define WS_RX_BUFFER_LEN 512
#define WS_URL "ws://10.0.0.2:80/ws"
#define LOGGER_BUFFER_SIZE 65536
#endif

View File

@ -2,6 +2,7 @@
#include <stdint.h>
#include <stdio.h>
#include "config.h"
#include "logger.h"
#ifndef LOGGER_BUFFER_SIZE

View File

@ -4,6 +4,7 @@
#include <nvs_flash.h>
#include <esp_task_wdt.h>
#include <freertos/idf_additions.h>
#include <CLI/CLI.h>
#include <CMDList/CMDList.h>
@ -16,22 +17,37 @@
#include "led.h"
#include "servos.h"
#include "logger.h"
#include "ws.h"
bool volatile running = true;
CMDList_t* cmdList;
bool rxBuffer_overflow = false;
/*
* CLI char out function. used to print back to a CLI, but the lib
* is only used for reciving command and not having a full cli
*/
typedef enum {
STATE_WIFI_CONNECTING,
STATE_WIFI_WAIT_CONNECTION,
STATE_WS_CONNECTING,
STATE_WS_WAIT_CONNECTION,
STATE_IDEL,
STATE_DRIVING
} MainState_t;
MainState_t MainState = STATE_WIFI_CONNECTING;
ws_client_t ws_client;
int charOut_uart(const char* c)
{
printf("%c", *c);
return 0;
}
int charOut_ws(const char* c)
{
ws_putchar(ws_client, *c);
return 0;
}
void app_main() {
// disable watchdog
ESP_ERROR_CHECK(esp_task_wdt_deinit());
@ -59,58 +75,89 @@ void app_main() {
servo_init();
wifiInit();
wifi_connect();
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
* happened. */
if (bits & WIFI_CONNECTED_BIT)
{
led_setRGB(0, 20, 0);
LOG_I("main: connected to ap SSID '%s'", WIFI_SSID);
}
else if (bits & WIFI_FAIL_BIT)
{
led_setRGB(2, 0, 0);
LOG_E("main: Failed to connect to SSID '%s',", WIFI_SSID);
}
else
{
led_setRGB(2, 0, 0);
LOG_C("main: UNEXPECTED EVENT");
return;
}
// // setup UDP server
// int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
// if (sock < 0)
// {
// printf("FAITAL: main: failed to create UDP socket\n");
// return;
// }
running = true;
cmdList = getCMDList();
// init cli
cmdList = getCMDList();
CLI_t cli_uart = CLI_init((CLI_charOutFn)&charOut_uart, cmdList);
uint8_t ch_uart = 0;
uint8_t charIn = 0;
EventBits_t bits;
MainState_t lastMainState = MainState;
CLI_t cli_ws_client;
LOG_D("main: main loop starting in state %d", MainState);
while (running)
{
ch_uart = getchar();
if (ch_uart != 255)
charIn = getchar();
if (charIn != 255)
{
CLI_charIn(&cli_uart, ch_uart);
CLI_charIn(&cli_uart, charIn);
}
if (lastMainState != MainState)
{
LOG_D("main: MainState changed from %d to %d", lastMainState, MainState);
lastMainState = MainState;
}
switch (MainState)
{
case STATE_WIFI_CONNECTING:
wifi_connect();
MainState = STATE_WIFI_WAIT_CONNECTION;
break;
case STATE_WIFI_WAIT_CONNECTION:
bits = xEventGroupGetBits(s_wifi_event_group);
if ((bits & WIFI_CONNECTED_BIT) != 0)
{
led_setRGB(0, 20, 0);
MainState = STATE_WS_CONNECTING;
LOG_I("main: connected to ap SSID '%s'", WIFI_SSID);
}
else if ((bits & WIFI_FAIL_BIT) != 0)
{
led_setRGB(2, 0, 0);
MainState = STATE_WIFI_CONNECTING;
// wifi_reconnect();
LOG_E("main: Failed to connect to SSID '%s'", WIFI_SSID);
}
else if (bits != 0)
{
led_setRGB(2, 0, 0);
// MainState = STATE_WIFI_CONNECTING;
LOG_C("main: UNEXPECTED EVENT (bits: 0x%04x)", bits);
}
break;
case STATE_WS_CONNECTING:
ws_client = ws_connect(WS_URL);
cli_ws_client = CLI_init((CLI_charOutFn)&charOut_uart, cmdList);
MainState = STATE_WS_WAIT_CONNECTION;
break;
case STATE_WS_WAIT_CONNECTION:
if (ws_client->connected)
{
MainState = STATE_IDEL;
}
case STATE_IDEL:
case STATE_DRIVING:
if (!ws_client->connected)
{
MainState = STATE_WS_WAIT_CONNECTION;
}
charIn = ws_getchar(ws_client);
if (charIn != 255)
{
CLI_charIn(&cli_ws_client, charIn);
}
break;
}
}

View File

@ -106,7 +106,7 @@ void printChipInfo()
LOG_W("Get flash size failed");
return;
}
LOG_D("%" PRIu32 "MB %s flash",
flash_size / (uint32_t)(1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"

128
rx_esp32/src/ws.c Normal file
View File

@ -0,0 +1,128 @@
#include "ws.h"
#include <stdint.h>
#include <string.h>
#include <esp_websocket_client.h>
#include "config.h"
#include "logger.h"
static void ws_event_handler(void* handler_args, esp_event_base_t base, int32_t event_id, void* event_data)
{
esp_websocket_event_data_t* data = (esp_websocket_event_data_t*)event_data;
ws_client_t client = (ws_client_t)handler_args;
switch (event_id)
{
case WEBSOCKET_EVENT_CONNECTED:
LOG_I("ws_event_handler: connected");
client->connected = true;
break;
case WEBSOCKET_EVENT_DISCONNECTED:
LOG_W("ws_event_handler: disconnected");
client->connected = false;
if (data->error_handle.esp_ws_handshake_status_code != 0)
LOG_E("ws_event_handler: HTTP status code %d", data->error_handle.esp_ws_handshake_status_code);
if (data->error_handle.error_type == WEBSOCKET_ERROR_TYPE_TCP_TRANSPORT) {
if (data->error_handle.esp_tls_last_esp_err != 0)
LOG_E("ws_event_handler: reported from esp-tls", data->error_handle.esp_tls_last_esp_err);
if (data->error_handle.esp_tls_stack_err != 0)
LOG_E("ws_event_handler: reported from tls stack", data->error_handle.esp_tls_stack_err);
if (data->error_handle.esp_transport_sock_errno != 0)
LOG_E("ws_event_handler: captured as transport's socket errno", data->error_handle.esp_transport_sock_errno);
}
esp_websocket_client_start(client->handle);
break;
case WEBSOCKET_EVENT_DATA:
LOG_D("ws_event_handler: data recieved (opcode=%02x)", data->op_code);
if (data->op_code == 0x2)
{
LOG_D("ws_event_handler: binary data recieved");
// ESP_LOG_BUFFER_HEX("Received binary data", data->data_ptr, data->data_len);
}
else if (data->op_code == 0x08 && data->data_len == 2)
{
LOG_W("ws_event_handler: recieved closed message (code: %d)", (((int16_t)(data->data_ptr[0]))<<8) + data->data_ptr[1]);
// ESP_LOGW(TAG, "Received closed message with code=%d", 256 * data->data_ptr[0] + data->data_ptr[1]);
}
else
{
LOG_D("ws_event_handler: data recieved (opcode: %d, size: %d): %.*s", data->op_code, data->data_len, data->data_len, (char*) data->data_ptr);
uint16_t sizeLeft = WS_RX_BUFFER_LEN + client->rxBuffer_rp - client->rxBuffer_wp;
if (sizeLeft > WS_RX_BUFFER_LEN)
{
sizeLeft -= WS_RX_BUFFER_LEN;
}
if (data->data_len <= sizeLeft)
{
if (WS_RX_BUFFER_LEN - client->rxBuffer_wp <= data->data_len)
{
memcpy(&client->rxBuffer[client->rxBuffer_wp], data->data_ptr, data->data_len);
}
else
{
memcpy(&client->rxBuffer[client->rxBuffer_wp], data->data_ptr, sizeLeft);
memcpy(&client->rxBuffer[0], data->data_ptr + sizeLeft, data->data_len - sizeLeft);
}
client->rxBuffer_wp += data->data_len;
}
else
{
LOG_E("ws_event_handler: no space left in buffer. data ignored (free space: %u)", data->data_len, sizeLeft + client->rxBuffer_rp);
}
}
break;
case WEBSOCKET_EVENT_ERROR:
if (data->error_handle.esp_ws_handshake_status_code != 0)
LOG_E("ws_event_handler: HTTP status code %d", data->error_handle.esp_ws_handshake_status_code);
if (data->error_handle.error_type == WEBSOCKET_ERROR_TYPE_TCP_TRANSPORT) {
if (data->error_handle.esp_tls_last_esp_err != 0)
LOG_E("ws_event_handler: reported from esp-tls %d", data->error_handle.esp_tls_last_esp_err);
if (data->error_handle.esp_tls_stack_err != 0)
LOG_E("ws_event_handler: reported from tls stack %d", data->error_handle.esp_tls_stack_err);
if (data->error_handle.esp_transport_sock_errno != 0)
LOG_E("ws_event_handler: captured as transport's socket errno %d", data->error_handle.esp_transport_sock_errno);
}
break;
}
}
ws_client_t ws_connect(char *url)
{
ws_client_t client = malloc(sizeof(ws_client_data_t));
client->rxBuffer_rp = 0;
client->rxBuffer_wp = 0;
memset(&(client->rxBuffer[0]), 0, WS_RX_BUFFER_LEN);
const esp_websocket_client_config_t ws_conf = {
.uri = url
};
client->handle = esp_websocket_client_init(&ws_conf);
esp_websocket_register_events(client->handle, WEBSOCKET_EVENT_ANY, ws_event_handler, (void *)client);
esp_websocket_client_start(client->handle);
return client;
}
int ws_getchar(ws_client_t client)
{
int out = 255;
if (client->rxBuffer_rp != client->rxBuffer_wp)
{
out = client->rxBuffer[client->rxBuffer_rp];
client->rxBuffer_rp++;
if (client->rxBuffer_rp >= WS_RX_BUFFER_LEN)
{
client->rxBuffer_rp = 0;
}
}
return out;
}
void ws_putchar(ws_client_t client, char c);

23
rx_esp32/src/ws.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef WS_H
#define WS_H
#include <stdint.h>
#include <esp_websocket_client.h>
#include "config.h"
typedef struct {
esp_websocket_client_handle_t handle;
int connected;
unsigned char rxBuffer[WS_RX_BUFFER_LEN];
uint16_t rxBuffer_wp;
uint16_t rxBuffer_rp;
} ws_client_data_t;
typedef ws_client_data_t* ws_client_t;
ws_client_t ws_connect(char *url);
int ws_getchar(ws_client_t client);
void ws_putchar(ws_client_t client, char c);
#endif