banner

Automação com ESP32 e Golang


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");
  }
}





FAÇA O DOWNLOAD DOS ARQUIVOS

INO

PDF

GO



3 comentários:

  1. Boa noite ! links quebrados : INO e PDF. Teria como reparar ? Desde já agradeço a gentileza. Abraços de Eng. Maurício Pereira.

    ResponderExcluir
  2. Bom dia. Muito bom o video, Link quebrado INO e PDF.

    ResponderExcluir

Tecnologia do Blogger.