#include "ws.h" #include #include #include #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; char str[100]; snprintf(&str[0], 100, "%04d;3440;" BOAT_NAME "\n", BoatId); esp_websocket_client_send_text(client->handle, &str[0], strlen(str), 1000); 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 %d", data->op_code); if (data->op_code == 0x02) { LOG_D("ws_event_handler: binary data recieved"); } 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]); } else if (data->op_code == 0x09 || data->op_code == 0x0A) { // pong or pong packet // do nothing, handled by esp_websocket } else if (data->op_code == 0x01 && data->data_len > 0) { // LOG_D("ws_event_handler: cmd recieved (len: %d): '%.*s'", 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; if (client->txBuffer_wp >= WS_RX_BUFFER_LEN) { client->txBuffer_wp -= WS_RX_BUFFER_LEN; } } else { LOG_E("ws_event_handler: no space left in buffer. data ignored (free space: %u)", data->data_len, sizeLeft + client->rxBuffer_rp); } } else { LOG_D("ws_event_handler: data recieved (opcode: 0x%02x, size: %d): '%.*s'", data->op_code, data->data_len, data->data_len, (char*) data->data_ptr); } 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; default: LOG_D("ws_event_handler: a unkown event happened: %d", event_id); 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; client->txBuffer_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) { if (client->txBuffer_wp == WS_TX_BUFFER_LEN) { ws_sendData(client); if (client->txBuffer_wp == WS_TX_BUFFER_LEN) { LOG_E("ws_sendData: no space left in tx buffer. data ignored"); return; } } client->txBuffer[client->txBuffer_wp] = c; client->txBuffer_wp++; } void ws_sendData(ws_client_t client) { if ((client->txBuffer_wp > 0) && esp_websocket_client_is_connected(client->handle)) { LOG_D("ws_sendData: (%d b) '%.*s'", client->txBuffer_wp, client->txBuffer_wp, (char *)&client->txBuffer[0]); esp_websocket_client_send_text(client->handle, (char *)&client->txBuffer[0], client->txBuffer_wp, 1000 * portTICK_PERIOD_MS); client->txBuffer_wp = 0; } }