esp32-net6-websockets

Cómo conectar un ESP32 con NET6 por WebSockets

Nueva entrada de la serie de entradas destinadas a ver formas de comunicación entre un ESP32 y una aplicación en NET6 escrita en C#. Esta vez nos toca ver comunicación por Websockets.

Anteriormente ya hemos visto la comunicación a través de puerto de serie, y la comunicación mediante peticiones HTTP. Continuamos en la entrada de hoy viendo la comunicación por Websockets.

NET6 es multiplataforma y está disponible en ordenadores con Windows, Android, Linux o Mac, así como en arquitecturas x86/x64 y ARM7 o superior. Esto significa que podemos ejecutar el mismo programa en diferentes dispositivos, como ordenadores de sobremesa con Windows o Linux, móviles Android o Raspberry Pi.

Como comentamos en entrada anterior la entrada anterior, y no es la primera vez en el blog, aunque veamos una forma de comunicación después de la otra, no significa que la comunicación por WebSockets sea “mejor” que la comunicación por peticiones Http. Cada comunicación tiene sus ventajas y desventajas.

En concreto, la comunicación por Websocket es interesante cuando se necesita una comunicación completamente bidireccional entre cliente y servidor, y la velocidad de transferencia de datos requerida es alta.

No todo son ventajas, no obstante. También tiene la parte negativa de que requiere muchos recursos. Además, supone un gran consumo de puertos en la máquina servidor, lo que obliga a soluciones de sistemas más complejos. Por lo que puede no ser recomendable en el caso de que tengamos muchos clientes que hacen una conexión eventual.

Una vez aclarado esto ¡vamos al lio!

Código ESP32

Al igual que en el resto de entradas de la serie, yo voy a utilizar un M5 Stick C como dispositivo de desarrollo. Sin embargo, cualquier dispositivo con Wifi similar a Arduino, como cualquier modelo de la familia ESP32, os servirá igualmente.

Y como es habitual en nuestras entradas del blog, por orden y limpieza vamos separaremos el código según agrupando por funcionalidad. Así, en el fichero APIWebSocket.hpp tenemos toda la lógica asociada a los WebSockets.

void InitWebSockets()
{
    webSocket.begin(ApiHost, 81, "/API");
    webSocket.onEvent(webSocketEvent);
    Serial.println("Connected websockets");
}

void SendA()
{
webSocket.sendTXT("A");
}

void SendB()
{
    webSocket.sendTXT("B");
}

Cómo vemos, únicamente tenemos una función para inicializar la comunicación por WebSockets, y dos métodos para enviar ‘A’ y ‘B’. Sencillo, pero suficiente para nuestro ejemplo.

Por otro lado, nuestro sketch principal quedaría de la siguiente forma.

void setup()
 {
    Serial.begin(115200);

    WIFI_Connect();

    delay(2000);
    InitWebSockets();
}

bool isOn = false;
void Update()
{
    if (M5.BtnA.wasPressed())
    {
        if (isOn == false)
        {
            isOn = true;
            Serial.println("A");
            SendA();
        }
        else if (isOn == true)
        {
            isOn = false;
            Serial.println("B");
            SendB();
        }
    }
}

void loop()
{
    M5.update();
    webSocket.loop();
    delay(10);

    Update();
}

Donde, como vemos, básicamente en el setup iniciamos el WiFi y la comunicación por WebSockets. Por otro lado, loop() actualizamos la comunicación del WebSocket, y llamamos a la función de update().

En esta función de update() simplemente comprobamos si se ha pulsado el botón, para enviar alternativamente ‘A’ o ‘B’. Por supuesto, en un ejemplo real ahí pondríais la lógica necesaria por vuestro proyecto. Para este ejemplo de comunicación, con nuestra A/B nos basta y nos sobra.

Código NET6

Por otro lado, para la comunicación por WebSockets desde NET6 usaremos la librería WebsocketSharp que ya vimos en esta entrada.

Como hemos hecho en las entradas anteriores, vamos a crear un objeto que nos simplifique el uso de WebSockets en nuestro programa. En el caso de WebSockets es muy sencillo, y podría ser algo como lo siguiente.

public class ArduinoWebsocket : WebSocketBehavior
{
public static string LastRecieved { get; private set; } = "";

    public static event EventHandler DataArrived;

    protected override void OnMessage(MessageEventArgs e)
    {
        LastRecieved = e.Data;
        DataArrived?.Invoke(this, new EventArgs());
    }
}

Con este objeto, realizar la conexión por WebSockets desde NET6 al ESP32 sería tan sencilla como lo siguiente.

InitWebSocketServer();

Console.ReadLine();

void InitWebSocketServer()
{
    var web = new WebSocketServer(81);
    web.AddWebSocketService<ArduinoWebsocket>("/API");

    ArduinoWebsocket.DataArrived += DataArrived;
    web.Start();
}

void DataArrived(object sender, EventArgs e)
{
    if (ArduinoWebsocket.LastRecieved == "A")
    {
        Console.WriteLine("A");
    }
    else if (ArduinoWebsocket.LastRecieved == "B")
    {
        Console.WriteLine("B");
    }
}

¡Así de fácil! Realmente vemos que la comunicación por WebSockets, desde el punto de vista de código, no es nada complicada. De hecho, es muy sencillo comunicar un ESP32 con una aplicación NET6 en C# a través de WebSockets. En la próxima entrada veremos comunicación por MQTT. ¡Hasta la próxima!

Descarga el código

Todo el código de esta entrada está disponible para su descarga en Github. github-full