Why Is It Important to Understand Socket? Part 1
by Fernando Koyanagi in Circuits > Microcontrollers
722 Views, 3 Favorites, 0 Comments
Why Is It Important to Understand Socket? Part 1
![Por que é importante entender Socket? Pt-1](/proxy/?url=https://content.instructables.com/FRG/ZIS7/JVH3H3Y0/FRGZIS7JVH3H3Y0.jpg&filename=Por que é importante entender Socket? Pt-1)
![1.png](/proxy/?url=https://content.instructables.com/F6N/0EC8/JVH3H3YU/F6N0EC8JVH3H3YU.png&filename=1.png)
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.
Demonstration
![demo.png](/proxy/?url=https://content.instructables.com/FIK/RUH0/JVH3H407/FIKRUH0JVH3H407.png&filename=demo.png)
Client Assembly
![5.png](/proxy/?url=https://content.instructables.com/F09/7BI0/JVH3H412/F097BI0JVH3H412.png&filename=5.png)
Mounting Server
![6.1.png](/proxy/?url=https://content.instructables.com/F24/P5K1/JVH3H41X/F24P5K1JVH3H41X.png&filename=6.1.png)
Fluxograma Server
![7.png](/proxy/?url=https://content.instructables.com/FII/KCVL/JVH3H42Q/FIIKCVLJVH3H42Q.png&filename=7.png)
Client Loop Flowchart
![8.png](/proxy/?url=https://content.instructables.com/F29/NMCD/JVH3H43R/F29NMCDJVH3H43R.png&filename=8.png)
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
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(); }
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(); }
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
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
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
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(); }
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(); }