Construindo um Servidor Web para sua Estação Meteorológica com a Franzininho WiFi Lab01

Este post faz parte da série Franzininho WiFi com MicroPython

Introdução

Neste artigo, vamos criar um servidor web para visualizar os dados coletados pela estação meteorológica montada com a Franzininho WiFi Lab01, permitindo assim um monitoramento remoto da estação. A estação será composta por:

  • O DHT11 para medir temperatura e umidade, 
  • O BMP180 para medir pressão atmosférica e altitude, 
  • O MQ135 para avaliar a qualidade do ar,
  • O sensor de chuva para monitorar as condições climáticas.

Recursos necessários

As instruções de como montar a Franzininho WiFi Lab01 para criar uma estação meteorológica, estão no artigo Estação meteorológica com a Franzininho WiFi Lab01.

Código

Para criar um servidor web é preciso criar dois arquivos: boot e main. 

Importante: Os dois arquivos precisam ser salvos na placa.

  1. Acesse “Arquivo” > “Salvar como…” e selecione “dispositivo MicroPython”.
  1. Nomeie o arquivo e clique em OK para salvá-lo na placa.

Boot

Com a Franzininho WiFi Lab01 conectada ao seu computador, abra o Thonny e crie um novo arquivo contendo o código do boot. O nome do arquivo precisa ser boot.py para a conexão Wi-Fi ocorrer.

import socket, network
from machine import Pin, SoftI2C
import esp, gc, dht
from bmp180 import BMP180

# gerenciador de memória
esp.osdebug(None)
gc.collect()

# dados da rede
ssid = 'SUBSTITUA_PELO_SEU_SSID'
password = 'SUBSTITUA_PELA_SUA_SENHA'

# configurando como cliente
wlan = network.WLAN(network.STA_IF)
wlan.active(True)

# caso já esteja conectado
if wlan.isconnected() == False:
    wlan.connect(ssid, password)

# espere conectar
while wlan.isconnected() == False:
    pass

print('connected!')
print(wlan.ifconfig())

# atribuição de pinos da Franzininho 
i2c = SoftI2C(scl=Pin(9), sda=Pin(8))

# configurando DHT
d = dht.DHT11(Pin(15))

# configurando BMP180
bmp180 = BMP180(i2c)
bmp180.oversample_sett = 2
bmp180.baseline = 101325

# configurando pino do MQ135
mq135= Pin(5,Pin.IN)

#configurando sensor de chuva
sensor_chuva= Pin(2, Pin.IN)

Para entender como ocorre a conexão Wi-Fi no arquivo boot, consulte o artigo Web Server com a Franzininho WiFi Lab01 e MicroPython.

Além de estabelecer a conexão de rede foi necessário inserir as configurações dos sensores utilizados para compor a estação meteorológica. Para isso, incluímos as bibliotecas necessárias para o funcionamento dos sensores, como: as bibliotecas para o sensor de temperatura e umidade (DHT), para comunicação I2C e para o sensor de pressão e altitude BMP180. 

Além disso, foi preciso estabelecer a relação entre cada sensor e o respectivo pino ao qual está conectado no dispositivo.

# atribuição de pinos da Franzininho 
i2c = SoftI2C(scl=Pin(9), sda=Pin(8))

# configurando DHT
d = dht.DHT11(Pin(15))

# configurando BMP180
bmp180 = BMP180(i2c)
bmp180.oversample_sett = 2
bmp180.baseline = 101325

# configurando pino do MQ135
mq135= Pin(5,Pin.IN)

#configurando sensor de chuva
sensor_chuva= Pin(2, Pin.IN)

Por último, é preciso lembrar que o endereço IP para acessar o servidor é disponibilizado pela primeira informação que é exibida quando executamos o comando ‘ifconfig()’. Esse endereço pode variar por múltiplas razões, então é importante ter atenção ao endereço que aparecerá ao executar o comando na sua máquina.

Figura 1 – Exemplo de saída da execução do boot.

Main

O main será composto pelo script que permitirá a construção da página web, juntamente com as funções que realizam as leituras dos sensores da estação.

def read_sensor():
  global temp, hum, p, alt
  temp = p = alt = hum = 0
  try:
    # coletando umidade e temperatura
    d.measure()
    temp = d.temperature()
    hum = d.humidity()
    #coletando pressão e altitude
    p = round(bmp180.pressure, 2)
    alt = round(bmp180.altitude, 2)
    msg = (b'{0:.0f},{1:.0f},{2:3.1f},{3:3.1f}'.format(temp, hum, p, alt))
    return(msg)
  except OSError as e:
    return('Failed to read sensor.')

def odor_sensor():
    if mq135.value():
        return ("Gás tóxico: não detectado")
    else:
        return ("Gás tóxico: detectado")

def rain_sensor():
    if sensor_chuva.value():
        return("Chuva: não detectada")
    else:
        return("Chuva: detectada")
        
def web_page():
    odor = odor_sensor() # obter o valor do odor
    rain = rain_sensor() # obter o valor do sensor de chuva
    html = """<!DOCTYPE HTML><html>
        <head>
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <meta http-equiv="refresh" content="3">
          <meta charset="UTF-8">
          <script src="https://kit.fontawesome.com/ae775d017c.js" crossorigin="anonymous"></script>
          <style>
            html {
             font-family: Arial;
             display: inline-block;
             margin: 0px auto;
             text-align: center;
            }
            h2 { font-size: 3.0rem; }
            p { font-size: 3.0rem; }
            .units { font-size: 2.2rem; }
            .dht-labels{
              font-size: 1.5rem;
              vertical-align:middle;
              padding-bottom: 15px;
            }
            .left-column {
              float: left;
              width: 50%; /* Define a largura da coluna esquerda */
            }
            .right-column {
              float: right;
              width: 50%; /* Define a largura da coluna direita */
            }
            
          </style>
        </head>
        <body>
            <h2>Estação Meteorológica Franzininho</h2>
            <div class="left-column">
                <p>
                    <i class="fa-solid fa-temperature-three-quarters" style="color: #f46315;"></i> 
                    <span class="dht-labels">Temperatura</span> 
                    <span>"""+str(temp)+"""</span>
                    <sup class="units">&deg;C</sup>
                </p>
                <p>
                    <i class="fas fa-tint" style="color:#00add6;"></i> 
                    <span class="dht-labels">Umidade</span>
                    <span>"""+str(hum)+"""</span>
                    <sup class="units">%</sup>
                </p>
                <p>
                   <i class="fa-solid fa-cloud-showers-heavy" style="color: #36a3f7;"></i>
                   <span class="dht-labels"><b>"""+rain+"""</b></span>
                </p>
            </div>
            
            <div class="right-column">
                <p>
                    <i class="fa-solid fa-gauge-high" style="color: #08ba46;"></i>
                    <span class="dht-labels">Pressão</span> 
                    <span>"""+str(p)+"""</span>
                    <sup class="units">Pa</sup>
                </p>
                <p>
                    <i class="fa-solid fa-mountain-sun" style="color: #296ea3;"></i>
                    <span class="dht-labels">Altitude</span>
                    <span>"""+str(alt)+"""</span>
                    <sup class="units">m</sup>
                </p>
                <p>
                    <i class="fa-solid fa-skull-crossbones" style="color: #e60000;"></i>
                    <span class="dht-labels"><b>"""+odor+"""</span>
                </p>
            </div>
            
        </body>
    </html>"""
    return html

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', 80))
s.listen(5)
  
while True:
    conn, addr = s.accept()
    print("Got a connection from %s" % str(addr))
    request = conn.recv(1024)
    print("Content = %s" % str(request))
    sensor_readings = read_sensor()
    print(sensor_readings)
    response = web_page()
    conn.send("HTTP/1.1 200 OK\n")
    conn.send("Content-Type: text/html\n")
    conn.send("Connection: close\n\n")
    conn.sendall(response)
    conn.close()

A página da web irá mostrar os dados coletados pelos sensores, indicando a temperatura, pressão, umidade, altitude e se há ou não a detecção de chuva e gases tóxicos. Então, antes de gerar o texto HTML, precisamos coletar os dados dos sensores.

Começando pela leitura dos sensores DHT11 e BMP180, foi criada a função ‘read_sensor()’. Essa função define quatro variáveis globais: ‘temp’, ‘hum’, ‘p’ e ‘alt’, que armazenarão os dados lidos pelos sensores DHT e BMP180, respectivamente.

def read_sensor():
  global temp, hum, p, alt
  temp = p = alt = hum = 0
  try:
    # coletando umidade e temperatura
    d.measure()
    temp = d.temperature()
    hum = d.humidity()
    #coletando pressão e altitude
    p = round(bmp180.pressure, 2)
    alt = round(bmp180.altitude, 2)
    msg = (b'{0:.0f},{1:.0f},{2:3.1f},{3:3.1f}'.format(temp, hum, p, alt))
    return(msg)
  except OSError as e:
    return('Leitura do sensor falhou.')

Nessa função utilizamos o recurso ‘try’ e ‘except’ que é feito no intuito de lidar com possíveis erros durante a execução do código. Nesse caso, o erro ocorre quando há uma falha na leitura do sensor.

Se a leitura for bem sucedida, o retorno da função é ‘msg’: uma string que contém os valores de temperatura, umidade, pressão e altitude formatados. Os dois primeiros valores são ‘{0:.0f},{1:.0f}’ que definem temperatura e umidade, respectivamente, como pontos flutuantes sem casas decimais. Os dois últimos valores ‘{2:3.1f},{3:3.1f}’ definem  pressão e altitude, respectivamente, como pontos flutuantes com casas decimais.

Se houver um erro na leitura o bloco ‘except’ irá retornar uma mensagem informando que houve um erro na leitura.

Em seguida, são definidas as funções para a leitura do sensor MQ135 e do sensor de chuva. Ambos são sensores que utilizam entradas digitais para determinar a detecção de determinada substância ou condição. Para isso, foram criadas funções que utilizam uma estrutura condicional ‘if’ e ‘else’ para verificar se a detecção foi realizada. Essas funções retornam uma mensagem que será exibida no servidor web, informando se a detecção ocorreu ou não.

def odor_sensor():
    if mq135.value():
        return ("Gás tóxico: não detectado")
    else:
        return ("Gás tóxico: detectado")


def rain_sensor():
    if sensor_chuva.value():
        return("Chuva: não detectada")
    else:
        return("Chuva: detectada")

Capturados os dados dos sensores, a página web pode ser criada. Iniciamos a função do servidor web com a seguinte tag meta:

<meta name="viewport" content="width=device-width, initial-scale=1">

Ela permite que sua página web seja visualizada em qualquer navegador.

A tag <meta> instrui o navegador a atualizar automaticamente a página após um intervalo de tempo específico, neste caso, a cada 3 segundos:

<meta http-equiv="refresh" content="3">

A tag <script> é necessária para carregar os ícones usados na página da web a partir do site do Font Awesome.

<script src="https://kit.fontawesome.com/ae775d017c.js" crossorigin="anonymous"></script>

O site Font Awesome Icons contém os ícones que serão utilizados para representar os dados coletados pelos sensores. Para utilizar os ícones é simples, você precisará ir em ‘Start’ e seguir o tutorial para poder incorporar os ícones no seu html.

Figura 2 – Página Start do Font Awesome.

Entre as tags <style></style>, adicionamos código CSS para personalizar a página da web. Assim, basicamente, estamos definindo a página para exibir o texto com a fonte Arial em um bloco sem margem e alinhado ao centro. Depois, definimos o tamanho da fonte para o título (h2), parágrafo (p) e unidades (.units) das leituras. O tamanho, alinhamento e espaço dos dados lidos são definidos em ‘.dht-labels’. 

Por último, para dividir a tela em duas partes e melhorar a exibição da estação meteorológica, criamos ‘.left-column’ e ‘.right-column’.  No caso da ‘.left-column’, os elementos serão alinhados à esquerda, na ‘.right-column’, os elementos serão alinhados à direita, ambas as colunas terão 50% de largura.

  <style>
            html {
             font-family: Arial;
             display: inline-block;
             margin: 0px auto;
             text-align: center;
            }
            h2 { font-size: 3.0rem; }
            p { font-size: 3.0rem; }
            .units { font-size: 2.2rem; }
            .dht-labels{
              font-size: 1.5rem;
              vertical-align:middle;
              padding-bottom: 15px;
            }
            .left-column {
              float: left;
              width: 50%; /* Define a largura da coluna esquerda */
            }
            .right-column {
              float: right;
              width: 50%; /* Define a largura da coluna direita */
            }
            
          </style>


Nas tags <body></body> é onde adicionamos o conteúdo da página da web. Já as tags <h2></h2> adicionam um título à página da web. Neste caso, o texto “Estação Meteorológica Franzininho”.

Em seguida, dividimos o lado esquerdo da página e utilizamos parágrafos para exibir os dados de temperatura, umidade e detecção de chuva. Os parágrafos são delimitados pelas tags <p> e </p>. O parágrafo para a temperatura é o seguinte:

<p>
         <i class="fa-solid fa-temperature-three-quarters" style="color: #f46315;"></i> 
         <span class="dht-labels">Temperatura</span> 
         <span>"""+str(temp)+"""</span>
          <sup class="units">&deg;C</sup>
</p>

As tags <i> são responsáveis por exibir os ícones do Font Awesome. Para obter o ícone de sua escolha pesquise pelo nome em inglês, por exemplo ‘temp’ e selecione a opção ‘Free’ para acessar os ícones gratuitos.

Figura 3 – Pesquise ‘temp’ no Font Awesome.

Clique no ícone desejado e, se necessário, altere a cor. Depois, basta copiar o texto HTML fornecido.

Figura 4 – Seleção do ícone.

O html obtido, após alterar a cor do ícone, foi esse:

<i class="fa-solid fa-temperature-three-quarters" style="color: #f46315;"></i>

A tag <span> irá exibir ‘Temperatura’ com a fonte predefinida em ‘dht-labels’. 

<span class="dht-labels">Temperatura</span>

A variável ‘temp’ é incorporada ao texto HTML usando os sinais de “+” para concatenar strings. Por último, as tags <sup></sup> fazem com que o texto seja sobrescrito e utilizamos esse recurso para mostrar as unidades dos dados. 

Os demais parágrafos seguem a mesma lógica. Assim, a página web ficará conforme mostrado na figura abaixo. 

Figura 5 – Página web criada.

Definida a página web, é criado um servidor básico usando sockets no Python para responder às solicitações HTTP. Para entender cada detalhe do servidor, consulte o artigo Web Server com a Franzininho WiFi Lab01 e MicroPython.

Abaixo está o resultado da visualização do servidor web. Optamos por mostrar a tela na horizontal para melhor visualização no celular, no entanto, isso resultou em uma dificuldade para exibir a página inteira. Logo, na primeira imagem, você pode ver o título da página e os dados coletados pelos sensores DHT11 e BMP180. Para visualizar os outros dados, é necessário rolar a tela para baixo.

Na segunda imagem, todas as informações estão visíveis, incluindo a detecção de chuva, indicada pela presença de uma gota de água sobre o sensor de chuva. Na terceira imagem, um recipiente de acetona foi aberto e o sensor detectou a presença da substância. Na quarta imagem, o sensor de chuva foi limpo e não há mais detecção de chuva.

Na última imagem, a acetona foi retirada do alcance do sensor, então não há detecção de gases ou chuva.

Figura 6 – Resultados.

Conclusão

Neste artigo, construímos um servidor web básico para o monitoramento remoto de uma estação meteorológica. Exploramos o processo de conexão da placa ao WiFi, estabelecimento da conexão cliente-servidor e criação de uma página web simples.

É importante destacar que este projeto é apenas o ponto de partida para uma infinidade de possibilidades. Como sugestão para implementações futuras, recomenda-se a personalização da interface do servidor web e a exploração de possibilidades para adicionar mais funcionalidades ao servidor, permitindo um maior controle dos recursos na placa.

Franzininho WiFi com MicroPython

Estação meteorológica com a Franzininho WiFi Lab01 Controlador de Semáforo com a Franzininho WiFi Lab01
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
0 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Home » Software » Construindo um Servidor Web para sua Estação Meteorológica com a Franzininho WiFi Lab01

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: