Pois bem: Automação utilizando
linguagem Go conectada ao ESP32. É sobre isso que vou falar neste vídeo de
hoje. E, por que escolhi a linguagem Go? Porque ela é compilada e própria para
fazer aplicações do lado do servidor. Por isso, é importante você começar a
olhar melhor para esta linguagem, que chega a ser até 100 vezes mais rápida que
Phyton. Sem contar a vantagem de ser simples e possibilitar o trabalho com
concorrência. Vamos, então, comunicar o ESP32 com um servidor multiclient feito
em linguagem Go. Acompanhe!
RECURSOS USADOS
- ESP32
- Módulo de relé
- Computador (servidor windows)
- Raspberry Pi
MONTAGEM
CÓDIGO SERVER
Fluxograma
CÓDIGO SERVIDOR
Imports
package main // Imports necessários import ( "bufio" "fmt" "net" "strings" )
Main
func main() {
// Porta de conexão
PORT := ":8001"
// Inicia o listen
l, err := net.Listen("tcp4", PORT)
// Se acontecer algum erro, aborta o programa
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Listen ok")
// Aguarda conexões (Accept)
defer l.Close()
fmt.Println("Waiting for connections...")
for {
c, err := l.Accept()
if err != nil {
fmt.Println(err)
return
}
// Para uma nova conexão, executa os comandos através da função handleConnection
go handleConnection(c)
}
}
Instrução Defer
A instrução defer muitas vezes
é usada para garantir a limpeza adequada dos recursos do sistema em nosso
programa. Isso permite um melhor gerenciamento de memória e um melhor
desempenho.
Ao chamar a instrução defer, o
comando subsequente é executado como último, antes de sair da função. Ou seja,
de acordo com o código do slide anterior:
defer l.Close()
fmt.Println("Waiting for connections...")
for {
c, err := l.Accept()
if err != nil {
fmt.Println(err)
return
}
// Para uma nova conexão, executa os comandos através da função handleConnection
go handleConnection(c)
}
}
A função Close somente será chamada após todas as linhas abaixo dela serem executadas. Sendo o último comando a ser executado pela função main.
Goroutines
As Goroutines são rotinas que
são executadas concorrentementes. Essa intrução cria uma thread e permite
estruturar o programa de modo a executar múltiplas tarefas.
No nosso exemplo, a função
handleConnection é executada por uma thread. Isso permite que múltiplos
clientes sejam comunicados com o servidor ao mesmo tempo.
Handleconnection
// Tomada de ações ao receber requisições do ESP
func handleConnection(c net.Conn) {
// Variável booleana de estado do relé
state := true
// Exibe mensagem informando qual IP está sendo utilizado pelo host
fmt.Printf("Serving %s\n", c.RemoteAddr().String())
// Enquanto não houver erros
for {
// Verifica novas mensagens
netData, err := bufio.NewReader(c).ReadString('\n')
// Se ocorreu algum erro, aborta função
if err != nil {
fmt.Println(err)
return
}
// Se recebeu a mensagem "STOP", aborta conexão com o client correspondente
temp := strings.TrimSpace(string(netData))
if temp == "STOP" {
break
}
// Envia o estado para o cliente correspondente
if state {
c.Write([]byte(string("ON")))
} else {
c.Write([]byte(string("OFF")))
}
// Muda de estado
state = !state
}
// Fecha a conexão
c.Close()
}
Go Language no Linux
É possível compilar o mesmo
código no linux (Raspberry Pi por exemplo).
Basta instalar o Go com o comando:
sudo apt-get install golang
E depois compilar o código com
o comando: go build go_server.go
Após isso, arquivo binário
será gerado e pronto para ser executado
CÓDIGO CLIENT
Fluxograma
Declarações e variáveis
// Bibliotecas necessárias #include <WiFi.h> #include <WiFiMulti.h> // Dados de acesso a rede wifi #define SSID "SSID" #define PASSWORD "PASS" // Dados de conexão com o servidor go const uint16_t port = 8001; // porta const char * host = "192.168.0.103"; // ip // Objeto utilizado para conexão com a rede WiFiMulti wiFiMulti; // Objeto utilizado para conexão com o servidor (TCP) WiFiClient client; // Relé usado como exemplo const int relay = 23;
Setup
void setup()
{
// Inicia velocidade da serial
Serial.begin(115200);
pinMode(relay, OUTPUT);
// Inicia o rele começando desativado
digitalWrite(relay, HIGH);
// Conecta WiFi
setupWiFi();
// Conecta com o servidor
if(connect())
Serial.println("Conectado com o servidor Go");
else
Serial.println("Erro ao conectar com o servidor Go");
delay(500);
}
Loop
void loop()
{
// Envia uma requisição para o servidor
client.print("GET /index.html HTTP/1.1\n\n");
// Aguarda resposta
for (int maxloops = 0; !client.available() && maxloops < 1000; maxloops++)
delay(1);
// Se recebeu a tempo
if (client.available() > 0)
{
//read back one line from the server
String line = client.readStringUntil('\r');
Serial.println(line);
// Atua no relé, conforme mensagem (lógica inversa)
if(line == "ON")
digitalWrite(relay, LOW);
else
if(line == "OFF")
digitalWrite(relay, HIGH);
}
else
Serial.println("Sem resposta...");
// Verifica se a conexão está ativa verifyConnection(); delay(1000); }
SetupWiFi
// Função que inicia o WiFi
void setupWiFi()
{
// Modo Access Point
wiFiMulti.addAP(SSID, PASSWORD);
Serial.println();
Serial.print("Waiting for WiFi... ");
while(wiFiMulti.run() != WL_CONNECTED)
{
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
Connect
// Função que conecta com o Servidor Go
bool connect()
{
Serial.print("Connecting to ");
Serial.println(host);
return client.connect(host, port);
}
VerifyConnection
// Função que verifica se caiu a conexão com o servidor, se sim, efetua a reconexão
void verifyConnection()
{
if(!client.connected())
{
client.stop();
Serial.println("Desconectado, reconectando...");
if(connect())
Serial.println("Conectado com o servidor Go");
else
Serial.println("Erro ao conectar com o servidor Go");
}
}



















3 Comentários
https://gobot.io/
ResponderExcluirBoa noite ! links quebrados : INO e PDF. Teria como reparar ? Desde já agradeço a gentileza. Abraços de Eng. Maurício Pereira.
ResponderExcluirBom dia. Muito bom o video, Link quebrado INO e PDF.
ResponderExcluir