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?