Introduction: Why Is It Important to Understand Socket? Part 1

About: Do you like technology? Follow my channel on Youtube and my Blog. In them I put videos every week of microcontrollers, arduinos, networks, among other subjects.

I’ll be discussing what I consider to be some very important subjects in this article today. The first subject concerns the MultiClient Socket with two ESP32s. They send data to a third party (in this case, the server). The second subject is about a remote control where I implanted my own Callback. Thus, I’ll show the operation of Multiclients with Sockets, and I’ll show the creation of a Lib that will warn us (through a Callback function) on the change of the status of pins that happen in ESP clients connected to an ESP server. In addition, I’ll show the operation of Callbacks. And I’ll speak even more specifically about the Lib in the next video.

Step 1: Demonstration

Step 2: Client Assembly

Step 3: Mounting Server

Step 4: Fluxograma Server

Step 5: Client Loop Flowchart

Step 6: Implementing the .ino Files

After our Lib is finished and

in the correct place (folder in C: \ Users \ \ Documents \ Arduino \ libraries), we can go to the Client.ino and Server.ino files

Step 7: Client.ino

Declarations and variables

#include <WiFi.h>
#include <RemoteCliente.h> //Faz parte da nossa lib //Configurações da rede e porta do socket do outro ESP //Devem ser iguais nos dois arquivos #define SSID "ESP32Server" #define PASSWORD "87654321" #define SERVER_PORT 5000 //Quantidade de pinos cujo os estados serão verificados #define PIN_COUNT 2 //Array com os pinos que iremos verificar int pinNumbers[PIN_COUNT] = {23, 22}; //Objeto que verificará se os pinos mudaram de estado e enviará para o server RemoteClient remoteClient(pinNumbers, PIN_COUNT);

Setup

void setup()
{ Serial.begin(115200); //Conecta à rede criada pelo outro ESP connectWiFi(); remoteClient.setServerAddressAndPort(WiFi.gatewayIP(), SERVER_PORT); }

ConnectWiFi

void connectWiFi()
{ Serial.print("Connecting to " + String(SSID)); //Conectamos ao Access Point criado pelo outro ESP WiFi.begin(SSID, PASSWORD); //Esperamos conectar while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); } Serial.println(); Serial.println("Connected!"); }

Loop

void loop()
{ //Se não está conectado à rede WiFi if(WiFi.status() != WL_CONNECTED) { //Mandamos conectar connectWiFi(); } //Chama o método loop do remoteClient e este verificará se aconteceu mudança no estado dos pinos //e enviará para o server caso tenha acontecido remoteClient.loop(); }

Step 8: Server.ino

Declarations and variables

#include <WiFi.h>
#include <RemoteServer.h> //Faz parte da nossa lib //Configurações da rede e porta do socket criados por este ESP //Devem ser iguais nos dois arquivos #define SSID "ESP32Server" #define PASSWORD "87654321" #define SERVER_PORT 5000 //Objeto que irá receber por socket informações sobre mudança no estado dos pinos dos ESPs clients RemoteServer remoteServer(SERVER_PORT);

Setup

void setup()
{ Serial.begin(115200); //Cria uma rede WiFi para os outros ESPs se conectarem createWiFiAP(); //Inicia o remoteServer para que ele possa receber conexões remoteServer.begin(); //Passamos a função que será nosso callback quando um pino de um dos clients mudar de estado remoteServer.onStatusChange(statusChange); }

createWiFiAP

void createWiFiAP()
{ Serial.println("Creating AP " + String(SSID) + "..."); //Coloca este ESP como Access Point WiFi.mode(WIFI_AP); //SSID e Senha para se conectarem a este ESP WiFi.softAP(SSID, PASSWORD); Serial.println("Created"); }

statusChange

//Função chamada toda vez que um pino em um dos clients mudar de estado
void statusChange(int pinNumber, int pinStatus) { //Aqui vamos apenas replicar o estado no mesmo pino deste ESP //Colocamos o pino como saída pinMode(pinNumber, OUTPUT); //E mudamos o estado para o mesmo que recebemos do client digitalWrite(pinNumber, pinStatus); }

Loop

void loop()
{ //Chama a função do remoteServer que irá verificar novas conexões //e ler os dados dos pinos que os clients enviam quando há mudança de estado remoteServer.loop(); }

Step 9: Library "Libraries"

First, we’ll build our Lib which will consist of the Pin.h, RemoteClient.h, RemoteClient.cpp, RemoteServer.h, and RemoteServer.cpp files

The folder with these files should be placed in:

C: \ Users \ \ Documents \ Arduino \ libraries

Step 10: Pin.h

#ifndef Remote_Pin_h
#define Remote_Pin_h //Struct que será enviada entre o client e o server typedef struct { int number; int status; } Pin; #endif

Step 11: RemoteClient.h

#ifndef RemoteClient_h
#define RemoteClient_h #include #include #include #include "Pin.h" class RemoteClient { public: RemoteClient(int* pinNumbers, int pinCount); void loop(); void setServerAddressAndPort(IPAddress serverIpAddress, int serverPort); int* pinNumbers; int pinCount; std::vector pins; IPAddress serverIpAddress; int serverPort; private: boolean hasPinStatusChanged(int i); void sendPinStatus(int i); }; #endif

Step 12: RemoteClient.cpp

RemoteClient :: setServerAddressAndPort

//Endereço ip do server e a porta
void RemoteClient::setServerAddressAndPort(IPAddress serverIpAddress, int serverPort) { this->serverIpAddress = serverIpAddress; this->serverPort = serverPort; }

RemoteClient :: loop

void RemoteClient::loop()
{ //Para cada pino for(int i=0; i<pinCount; i++)

{ //Se o estado foi alterado if(hasPinStatusChanged(i)) { //Enviaremos para o server os dados do pino cujo estado foi alterado sendPinStatus(i); } } }

RemoteClient :: hasPinStatusChanged

bool RemoteClient::hasPinStatusChanged(int i)
{ //Faz a leitura do estado do pino na posição 'i' do array de pinos int status = digitalRead(pins[i].number); //Se está diferente if(pins[i].status != status) { //Atualizamos os dados do pino e retornamos true pins[i].status = status; return true; } //Se chegou aqui então o pino não teve seu estado alterado, então retornamos falso return false; }

RemoteClient :: sendPinStatus

void RemoteClient::sendPinStatus(int i)
{ //Conectamos com o server WiFiClient client; client.connect(serverIpAddress, serverPort); //Enviamos os dados do pino na posição 'i'do array para o server client.write((uint8_t*) &pins[i], sizeof(Pin)); client.flush(); client.stop(); }

Step 13: RemoteServer.h

Include

#ifndef RemoteServer_h
#define RemoteServer_h #include <Arduino.h> #include <WiFi.h> #include <vector> #include "Pin.h" typedef void (*OnStatusChangeCallback)(int pinNumber, int pinStatus); class RemoteServer { public: RemoteServer(int serverPort); std::vector clients; void begin(); void loop(); void stop(); void onStatusChange(OnStatusChangeCallback callback); //ou // void onStatusChange(void (*callback)(int pinNumber, int pinStatus)); //ou // void onStatusChange(void (*callback)(int, int)); //ou // void onStatusChange(void (*)(int, int));

readAndNotify

private:
void readAndNotify(WiFiClient client); WiFiServer server; void (*callback)(int, int); //Variável que irá apontar para função callback //ou // void (*callback)(int pinNumber, int pinStatus); //ou // OnStatusChangeCallback callback; }; #endif

RemoteServer :: RemoteServer

#include "RemoteServer.h"
//Construimos o server com o valor de serverPort RemoteServer::RemoteServer(int serverPort) : server(serverPort) { }

RemoteServer :: begin

void RemoteServer::begin()
{ //Iniciamos o server para que este possa receber conexões server.begin(); }

RemoteServer :: onStatusChange

void RemoteServer::onStatusChange(OnStatusChangeCallback callback)
{ this->callback = callback; } //ou // void RemoteServer::onStatusChange(void (*callback)(int pinNumber, int pinStatus)) // { // this->callback = callback; // } //ou // void RemoteServer::onStatusChange(void (*callback)(int, int)) // { // this->callback = callback; // }

RemoteServer :: loop

void RemoteServer::loop()
{ //Verificamos se temos um client tentando se conectar WiFiClient client = server.available(); //Se temos if (client) { //Colocamos no final do vector que armazena os clients clients.push_back(client); } for (std::vector::iterator it = clients.begin(); it != clients.end();) { //O conteúdo apontado pelo iterator é o client WiFiClient client = *it; if(client.connected()) { //Se o client possui algo para nos enviar if (client.available()) { readAndNotify(client); } //Vamos para o próximo client it++; } //Se não estiver mais conectado else { //Apagamos do vector clients.erase(it); } } }

readAndNotify

void RemoteServer::readAndNotify(WiFiClient client)
{ //Fazemos a leitura dos dados do client para a variável pin Pin pin; client.read((uint8_t*)&pin, sizeof(pin)); //Se possuímos um callback adicionado if(callback) { //Chamamos o callback informando o número do pino que foi alterado e o novo estado callback(pin.number, pin.status); } }

RemoteServer :: stop

void RemoteServer::stop()
{ //Paramos o servidor server.stop(); }

Step 14: Files

Download the files:

INO

PDF