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