I have been working on trying to implement OCPP in Arduino for which I need WebSocket. There is a library called Arduino Websocket Links2004/arduinoWebSockets: arduinoWebSockets (github.com) but it requires a loop function to be called for the library to work which I want to avoid.
I found that the ESP32 has an internal implementation of WebSocket called esp_websocket_client.h which is supposed to be asynchronous. I first wrote it in ESP-IDF and verified that it works. But when I moved the same code to Arduino, the WebSocket callback no longer worked. I verifed that the websocket connection was successful and the send function also worked since I got the data on my local server, but I am unable to recieve data.
I wanted to know if there are some additional things I need to do in PlatformIO to get the callback to work.
The Arduino code is given below.
#include <Arduino.h>
#include <WiFi.h>
#include <esp_websocket_client.h>
#define DEBUG_OCPP_WS
#ifdef DEBUG_OCPP_WS
#define WS_INFO(x, ...) ESP_LOGI("WS", x, #__VA_ARGS__)
#define WS_ERROR(x, ...) ESP_LOGE("WS", x, #__VA_ARGS__)
#else
#define WS_INFO(x, ...) {}
#define WS_ERROR(x, ...) {}
#endif
char ssid[] = "";
char pass[] = "";
esp_websocket_client_handle_t client;
void websocketEventHandler(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;
switch (event_id)
{
case WEBSOCKET_EVENT_CONNECTED:
WS_INFO("WEBSOCKET_EVENT_CONNECTED");
break;
case WEBSOCKET_EVENT_DISCONNECTED:
WS_INFO("WEBSOCKET_EVENT_DISCONNECTED");
break;
case WEBSOCKET_EVENT_DATA:
WS_INFO("WEBSOCKET_EVENT_DATA");
WS_INFO("Received opcode=%d", data->op_code);
if (data->op_code == 0x08 && data->data_len == 2)
{
WS_INFO("Received closed message with code=%d", 256 * data->data_ptr[0] + data->data_ptr[1]);
}
else
{
WS_INFO("Received=%.*s", data->data_len, (char *)data->data_ptr);
}
WS_INFO("Total payload length=%d, data_len=%d, current payload offset=%d\r\n", data->payload_len, data->data_len, data->payload_offset);
break;
case WEBSOCKET_EVENT_ERROR:
WS_INFO("WEBSOCKET_EVENT_ERROR");
break;
}
}
void sendMessage(char *data, size_t len)
{
while (1)
{
if (esp_websocket_client_is_connected(client))
{
char toTransmit[len + 5];
snprintf(toTransmit, len + 5, "%s", data);
WS_INFO("Sending %s", toTransmit);
esp_websocket_client_send_text(client, toTransmit, len, portMAX_DELAY);
break;
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
while (!WiFi.isConnected())
{
Serial.print(".");
vTaskDelay(500 / portTICK_PERIOD_MS);
}
Serial.print("\nConnected, IP: ");
Serial.println(WiFi.localIP());
esp_websocket_client_config_t websocket_cfg = {};
websocket_cfg.uri = "ws://192.168.160.16:9000/vgtuhd";
websocket_cfg.subprotocol = "ocpp2.0.1";
client = esp_websocket_client_init(&websocket_cfg);
esp_websocket_register_events(client, WEBSOCKET_EVENT_ANY, websocketEventHandler, (void *)client);
esp_websocket_client_start(client);
char *message = "[2,\"706222\",\"BootNotification\",{\"reason\": \"ApplicationReset\",\"chargingStation\": {\"serialNumber\": \"57799\",\"model\": \"SingleSocketCharger\",\"vendorName\": \"VendorX\",\"firmwareVersion\": \"13\",\"modem\": {\"iccid\": \"64456\",\"imsi\": \"56304\"}}}]";
sendMessage(message, strlen(message));
Serial.println("Setup Done");
}
void loop()
{
// put your main code here, to run repeatedly:
}