Servidor Raspberry – Comunicação com ESPs

Neste artigo iremos finalizar o servidor para Home Automation desenvolvido com o nosso Raspberry Pi. Para acompanhar este artigo irá necessita dos seguintes componentes:


Imagem Produto Comprar
 

 

 

NodeMcu Esp8266

 


 

 

 

Relé 5v 1 Canal

 


 

 

 

Cabos Jumper Femêa-Femêa

 


 

 

 

Kit Raspberry Pi 4

 


Atenção

Relembramos que as quantidades a adquirir devem coincidir com a quantidade de elementos que pretende controlar através do seu servidor.

Preview Servidor
Sobre o Projeto

Relembramos que este artigo é uma continuação dos artigos anteriores, aconselhamos fortemente a que consulte os posts anteriores para estar atualizado.

  1. Como Hospedar um Servidor Local com Raspberry Pi e Flask
  2. Página de Noticias Atualizada
  3. Servidor Raspberry Pi com Flask – Final da Estrutra

Neste artigo iremos elaborar a comunicação entre o nosso servidor e Esp/Nodemcu.

Código – Lado Servidor
Servidor – Casa

Iremos começar por efetuar algumas alterações ao código anterior

routes.py

from flask import render_template, url_for, request
from servidor import app
from servidor.getNoticias import getNoticias
from servidor.sendRequest import sendRequest
from servidor.getCuriosidade import getCuriosidade
from servidor.getTempo import getMetereologia
from servidor.config import userData

userData()

@app.route("/")
def homepage():
username = userData.user
dadosTempo = getMetereologia()
randomFact = getCuriosidade()
return render_template("home.html", username = username, 
dadosTempo = dadosTempo, randomFact = randomFact)

@app.route("/noticias")
def noticias():
noticias = getNoticias()
return render_template("noticias.html", noticias = noticias)

@app.route("/sensores")
def sensores():
return render_template("sensores.html")

#Interpretar Requests
#Quarto
#Quarto Luz Principal
#Ligar
@app.route("/ligar_Luz", methods=['POST'])
def ligar_LuzQuarto ():
if request.method == "POST":
requestType = "a"
target = "IP"
sendRequest(target, requestType)
return render_template("sensores.html")
#Desligar
@app.route("/desligar_Luz", methods=['POST'])
def desligar_LuzQuarto ():
if request.method == "POST":
requestType = "b"
target = "IP"
sendRequest(target, requestType)
return render_template("sensores.html")

#Quarto Luz Candeeiro
#Ligar
@app.route("/ligar_LuzCandeeiro", methods=['POST'])
def ligar_LuzCandeeiro():
if request.method == "POST":
requestType = "c"
target = "IP"
sendRequest(target, requestType)
return render_template("sensores.html") 
#Desligar
@app.route("/desligar_LuzCandeeiro", methods=['POST'])
def desligar_LuzCandeeiro():
if request.method == "POST":
requestType = "d"
target = "IP"
sendRequest(target, requestType)
return render_template("sensores.html")

#Sala
#Luz Sala de Estar
#Ligar
@app.route("/ligar_LuzSaladeEstar", methods=['POST'])
def ligar_LuzSaladeEstar():
if request.method == "POST":
requestType = "e"
target = "IP"
sendRequest(target, requestType)
return render_template("sensores.html")
#Desligar
@app.route("/desligar_LuzSaladeEstar", methods=['POST'])
def desligar_LuzSaladeEstar():
if request.method == "POST":
requestType = "f"
target = "IP"
sendRequest(target, requestType)
return render_template("sensores.html")

#Luz Sala de Jantar
#Ligar
@app.route("/ligar_LuzSaladeJantar", methods=['POST'])
def ligar_LuzSaladeJantar():
if request.method == "POST":
requestType = "g"
target = "IP"
sendRequest(target, requestType)
return render_template("sensores.html")

@app.route("/desligar_LuzSaladeJantar", methods=['POST'])
def desligar_LuzSaladeJantar():
if request.method == "POST":
requestType = "h"
target = "IP"
sendRequest(target, requestType)
return render_template("sensores.html")

@app.route("/ligar_FichaCarregamento", methods=['POST'])
def ligar_FichaCarregamento():
if request.method == "POST":
requestType = "i"
target = "IP"
sendRequest(target, requestType)
return render_template("sensores.html")

@app.route("/desligar_FichadeCarregamento", methods=['POST'])
def desligar_FichadeCarregamento():
if request.method == "POST":
requestType = "j"
target = "IP"
sendRequest(target, requestType)
return render_template("sensores.html")

sensores.html

{% extends "base.html" %}

{% block title %}
Sensores Locais
{% endblock %}

{% block sensoresActive %} active {% endblock %}

{% block content %}
<div style ="padding-top:2%;color:#e7b851; padding-left:5%;">
<h3>Quarto Principal</h3>
</div>
<div class="row" style ="padding-top:2%; padding-left:5%; padding-right:5%;">
<div class="col-sm-3">
<div class="card border-0">
<div class="card-body">
<form class="text-center" method = "post">
<h5 class="card-title">Luz Principal</h5>
<input type = "submit" class="btn btn-secondary" value = "Ligar" formaction="/ligar_Luz">
<input type = "submit" class="btn btn-secondary" value = "Desligar" formaction="/desligar_Luz">
</form>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="card border-0">
<div class="card-body">
<form class="text-center" method = "post">
<h5 class="card-title">Luz Candeeiro</h5>
<input type = "submit" class="btn btn-secondary" value = "Ligar" formaction="/ligar_LuzCandeeiro">
<input type = "submit" class="btn btn-secondary" value = "Desligar" formaction="/desligar_LuzCandeeiro">
</form>
</div>
</div>
</div>
</div>

<div style ="padding-top:2%;color:#e7b851; padding-left:5%;">
<h3>Sala</h3>
</div>
<div class="row" style ="padding-top:2%; padding-left:5%; padding-right:5%;">
<div class="col-sm-3">
<div class="card border-0">
<div class="card-body">
<form class="text-center" method = "post">
<h5 class="card-title">Luz Sala de Estar</h5>
<input type = "submit" class="btn btn-secondary" value = "Ligar" formaction="/ligar_LuzSaladeEstar">
<input type = "submit" class="btn btn-secondary" value = "Desligar" formaction="/desligar_LuzSaladeEstar">
</form>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="card border-0">
<div class="card-body">
<form class="text-center" method = "post">
<h5 class="card-title">Luz Sala de Jantar</h5>
<input type = "submit" class="btn btn-secondary " value = "Ligar" formaction="/ligar_LuzSaladeJantar">
<input type = "submit" class="btn btn-secondary" value = "Desligar" formaction="/desligar_LuzSaladeJantar">
</form>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="card border-0">
<div class="card-body">
<form class="text-center" method = "post">
<h5 class="card-title">Ficha Sala</h5>
<input type = "submit" class="btn btn-secondary" value = "Ligar" formaction="/ligar_FichaCarregamento">
<input type = "submit" class="btn btn-secondary" value = "Desligar" formaction="/desligar_FichadeCarregamento">
</form>
</div>
</div>
</div>
</div>

<style>
.card-body{
background-color: #343a40;
color:rgb(236, 236, 236);
}

.btn-secondary:hover{
background-color:#c0a469!important;
}

</style>

{% endblock %}

sendRequest.py

import socket
from time import sleep

def sendRequest(target, requestType):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((target, 80))

s.sendall(requestType.encode('UTF-8'))

sleep(1)
Explicação Código Servidor

Na pagina sensores é criado um formulário com método POST:

<form class="text-center" method = "post">
          <h5 class="card-title">Luz Principal</h5>
          <input type = "submit" class="btn btn-secondary" value = "Ligar" formaction="/ligar_Luz">
          <input type = "submit" class="btn btn-secondary" value = "Desligar" formaction="/desligar_Luz">
</form>

Sempre que o botão é pressionado é enviado um POST-Request formaction=”/XXXX” que dependendo do conteúdo enviará um socket para o nosso controlador especificado pelo IP correspondente acionando o script sendRequest.py

if request.method == “POST”:
        requestType = “a”
        target = “IP_CONTROLADOR”
        sendRequest(target, requestType)
return render_template(“sensores.html”)

No sendRequest.py é responsavel por efetivamente efetuar a comunicação com o seu controlador – requestType é uma variável usada como flag para ser interpretada pelo controlador, desta forma deve ser única e não deve ser repetida. A variável target deve ser substituido pelo IP do seu controlador.

Relembramos que todo este código pode ser copiado as vezes que pretender para acrescentar mais sensores ou controladores.

Código Lado Cliente

Este é o código que deve ser inserido no seu controlador. Iremos partilhar apenas o fundamental para que a comunicação e o controlo de um relé seja possível.

#include <ESP8266WiFi.h>

//Outputs
#define luz_principal_quarto 2

const char* ssid = "SSID";
const char* password = "PASSWORD";

WiFiServer wifiServer(80);

void setup() {
pinMode(luz_principal_quarto, OUTPUT);
Serial.begin(115200);

delay(1000);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting..");
}

Serial.print("Connected to WiFi. IP:");
Serial.println(WiFi.localIP());

wifiServer.begin();
}

void loop() {
WiFiClient client = wifiServer.available();

if (client) {
while (client.connected()) {
while (client.available() > 0) {
char c = client.read();
processReceivedValue(c);
Serial.write(c);
}

delay(10);
}

client.stop();
Serial.println("Client disconnected");
}
}

//Descodifica array para string
void processReceivedValue(char command) {
if (command == 'a') {
digitalWrite(luz_principal_quarto, HIGH);
Serial.write("Ligado");
}
else if (command == 'b') {
digitalWrite(luz_principal_quarto, LOW);
Serial.write("Desligado");
}
return;
}

Como funciona

Inicialmente deverá substituir SSID e PASSWORD pelos dados correspondentes a sua rede.

Assim que carregar o código, deverá aceder a consola de serial para obter o endereço de ip do seu controlador para ser substituído no target no routes.py

@app.route("/ligar_Luz", methods=['POST'])
def ligar_LuzQuarto ():
if request.method == "POST":
requestType = "a"
target = "IP"
sendRequest(target, requestType)
return render_template("sensores.html")

Finalmente temos que interpretar o socket enviado pelo servidor

void processReceivedValue(char command) {
if (command == 'a') {
digitalWrite(luz_principal_quarto, HIGH);
Serial.write("Ligado");
}
else if (command == 'b') {
digitalWrite(luz_principal_quarto, LOW);
Serial.write("Desligado");
}
return;
}

Caso pretenda adicionar mais deverá adicionar mais condições para interpretar os socket recebidos e variáveis para controlar o respetivo GPIO.

Esquema de Montagem – Sugerido
Esquema de Montagem

Para mais projetos, percorram o nosso blog, onde podem encontrar vários artigos interessantes relacionados com eletrónica, robótica e muito mais! Visitem também o nosso site, onde encontram tudo para eletrónica e robótica!