Assuntos que considero muito
importantes serão tratados neste artigo de hoje. O primeiro: Socket MultiClient,
com dois ESP32 enviando dados para um terceiro, no caso, o Server. Segundo:
controle remoto no qual implantei meu próprio Callback. Vou, portanto, mostrar
o funcionamento de Multclients com Sockets, criar uma Lib que vai nos avisar
através de callback sobre a mudança de status de pinos que acontecem em ESPs
clientes conectados a um ESP servidor, além de mostrar o funcionamento dos
Callbacks. Mas, especificamente sobre a LIB eu vou falar no próximo vídeo, ok!
Demonstração
Montagem Client
Montagem Server
Fluxograma Server
Fluxograma Client Loop
Implementando os arquivos .ino
Após a nossa lib estar
finalizada e no local correto (pasta em
C:\Users\<SEU_USUARIO>\Documents\Arduino\libraries) podemos partir para
os arquivos Client.ino e Server.ino.
Client.ino
Declarações e variáveis
#include <WiFi.h>
#include <RemoteClient.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
Declarações e variáveis
#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();
}
Biblioteca “Libraries”
Primeiramente vamos construir
nossa lib que será constituída dos arquivos Pin.h, RemoteClient.h,
RemoteClient.cpp, RemoteServer.h e RemoteServer.cpp
A pasta com estes arquivos
deverá ser colocada em:
C:\Users\<SEU_USUARIO>\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 <Arduino.h>
#include <WiFi.h>
#include <vector>
#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<Pin> pins;
IPAddress serverIpAddress;
int serverPort;
private:
boolean hasPinStatusChanged(int i);
void sendPinStatus(int i);
};
#endif
RemoteClient.cpp
Include
#include "RemoteClient.h"
//pinNumbers - Ponteiro para um array com os números dos pinos que serão verificados
//pinCount - Quantidade de pinos no array pinNumbers
RemoteClient::RemoteClient(int* pN, int pC) : pinNumbers(pN), pinCount(pC)
{
//Para cada pino
for(int i=0; i<pinCount; i++)
{
Pin pin;
//Vinculamos o pino da struct com o recebido por parâmetro
pin.number = pinNumbers[i];
//Colocamos como INPUT
pinMode(pin.number, INPUT);
//Dizemos que o estado está em LOW
pin.status = LOW;
//adicionamos ao vector
pins.push_back(pin);
}
}
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<WiFiClient> 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();
}







1 Comentários
Boa tarde Prof.
ResponderExcluirQuando tento gravar o client, tenho o seguinte erro:
C:\Program Files (x86)\Arduino\libraries\LibESP32Remote\RemoteServer.cpp: In member function 'void RemoteServer::stop()':
Alguma sugestão?