import time
import network
import ujson
import urequests
import machine
from machine import Pin, ADC, SoftI2C
import dht
from umqtt.simple import MQTTClient
WIFI_SSID = "Wokwi-GUEST"
WIFI_PASS = ""
MQTT_BROKER = "broker.hivemq.com"
MQTT_PORT = 1883
MQTT_TOPIC = "trabalho/estacao/dados"
API_KEY = "1c2f741b6226a42a0d30b7f085a914ed"
SHEETS_URL = "https://script.google.com/macros/s/AKfycbw_QUEROQGgE3UJEf-m_Wc8R-jKwFKAnKfW_ndEXiy6WBnwZuD8Mq-R8mLv1Onj5Ugh/exec"
EMAIL_DEST = "[email protected]"
sensor = dht.DHT22(Pin(4 ))
ldr = ADC(Pin(34)); ldr.atten(ADC.ATTN_11DB)
mq2 = ADC(Pin(35)); mq2.atten(ADC.ATTN_11DB)
btn = Pin(15, Pin.IN, Pin.PULL_UP)
i2c = SoftI2C(scl=Pin(22), sda=Pin(21))
try:
import ssd1306
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
OLED_OK = True
except:
OLED_OK = False
tela = 0
previsao_ceu = "Buscando..."
temp_rua = 0.0
last_api = 0
last_btn = time.ticks_ms()
last_mqtt = 0
last_sheets = 0
soma_temp = 0.0
soma_umid = 0.0
num_leituras = 0
email_enviado = False
mqtt_client = None
GAS_ALERTA = 2800
def oled_print(msg):
if not OLED_OK: return
oled.fill(0)
oled.text(msg, 0, 0)
oled.show()
def oled_linha(txt, y):
if not OLED_OK: return
oled.text(txt[:21], 0, y)
def conectar_wifi():
oled_print("Conectando WiFi...")
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(WIFI_SSID, WIFI_PASS)
for _ in range(40):
if wlan.isconnected():
oled_print("WiFi Conectado!")
return True
time.sleep(0.5)
return False
def conectar_mqtt():
global mqtt_client
try:
import urandom
cid = "ESP32_Mogi_{:04x}".format(urandom.getrandbits(16))
mqtt_client = MQTTClient(cid, MQTT_BROKER, MQTT_PORT)
mqtt_client.connect()
return True
except:
mqtt_client = None
return False
def buscar_previsao():
global previsao_ceu, temp_rua
try:
url = "http://api.openweathermap.org/data/2.5/weather?q=Mogi%20das%20Cruzes,BR&APPID=" + API_KEY + "&units=metric&lang=pt_br"
r = urequests.get(url, timeout=10 )
if r.status_code == 200:
d = r.json()
temp_rua = d["main"]["temp"]
previsao_ceu = d["weather"][0]["description"]
r.close()
except: pass
def enviar_email(media_temp, media_umid, total):
try:
assunto = "[Estacao Mogi] Relatorio Diario - {{DATA}}"
sep, sep2 = "=" * 52, "-" * 52
corpo = (
sep + "\n"
" ESTACAO METEOROLOGICA - MOGI DAS CRUZES / SP\n"
" Relatorio Diario Automatico\n"
+ sep + "\n\n"
" Data do relatorio : {{DATA}}\n"
" Hora de emissao : {{HORA}} (Brasilia)\n\n"
+ sep2 + "\n"
" RESUMO DAS LEITURAS\n"
+ sep2 + "\n\n"
" Media da temperatura: " + str(media_temp) + " C\n"
" Media da umidade : " + str(media_umid) + " %\n"
" Total de leituras : " + str(total) + " registros\n\n"
+ sep2 + "\n"
" CONDICOES EXTERNAS (OpenWeather)\n"
+ sep2 + "\n\n"
" Ceu em Mogi : " + previsao_ceu + "\n"
" Temp. externa : " + str(round(temp_rua, 1)) + " C\n\n"
+ sep + "\n"
" Mensagem gerada automaticamente pelo ESP32.\n"
+ sep + "\n"
)
payload = ujson.dumps({"action": "email", "destinatario": EMAIL_DEST, "assunto": assunto, "corpo": corpo})
r = urequests.post(SHEETS_URL, data=payload, headers={'Content-Type': 'application/json'}, timeout=30)
res = r.text
r.close()
return "Email enviado" in res
except: return False
def gravar_sheets(temp, umid):
try:
url = SHEETS_URL + "?temp=" + str(temp) + "&umid=" + str(umid)
r = urequests.get(url, timeout=15)
r.close()
except: pass
def publicar_mqtt(temp, umid, luz, gas):
global mqtt_client
try:
payload = ujson.dumps({"temperatura": round(temp, 1), "umidade": round(umid, 1), "luminosidade": luz, "gas": gas, "previsao_ceu": previsao_ceu, "temp_rua": temp_rua})
if mqtt_client is None: conectar_mqtt()
mqtt_client.publish(MQTT_TOPIC, payload)
except: mqtt_client = None
def mostrar_tela0(temp, umid):
oled.fill(0)
oled_linha("== MOGI - LOCAL ==", 0)
oled.hline(0, 9, 128, 1)
oled_linha("Temp: " + str(round(temp,1)) + " C", 12)
oled_linha("Umidade: " + str(round(umid,1)) + " %", 22)
oled.hline(0, 54, 128, 1)
oled_linha("1/4 Btn p/ trocar", 56)
oled.show()
def mostrar_tela1(gas, luz):
oled.fill(0)
oled_linha("== SEGURANCA ==", 0)
oled.hline(0, 9, 128, 1)
oled_linha("Gas/Fumaca: " + str(gas), 12)
oled_linha("Luz Solar: " + str(luz), 22)
bar = int(gas / 4095 * 14)
oled_linha("Nivel:[" + "#"*bar + "-"*(14-bar) + "]", 32)
if gas > GAS_ALERTA: oled_linha("!! ALERTA CRITICO !!", 42)
else: oled_linha("Ar: Normal", 42)
oled.hline(0, 54, 128, 1)
oled_linha("2/4 Btn p/ trocar", 56)
oled.show()
def mostrar_tela2():
oled.fill(0)
oled_linha("== PREVISAO REAL ==", 0)
oled.hline(0, 9, 128, 1)
oled_linha("Mogi das Cruzes", 12)
oled_linha("Ceu: " + previsao_ceu[:16], 22)
oled_linha("Temp rua: " + str(round(temp_rua,1)) + " C", 32)
oled.hline(0, 54, 128, 1)
oled_linha("3/4 Btn p/ trocar", 56)
oled.show()
def mostrar_tela3(w_ok, mqtt_ok):
oled.fill(0)
oled_linha("== CONEXOES ==", 0)
oled.hline(0, 9, 128, 1)
oled_linha("WiFi: " + ("OK" if w_ok else "ERRO"), 12)
oled_linha("MQTT: " + ("OK" if mqtt_ok else "ERRO"), 22)
oled.hline(0, 54, 128, 1)
oled_linha("4/4 Btn p/ trocar", 56)
oled.show()
print("\n=== Estacao Mogi - Iniciando ===")
if conectar_wifi():
conectar_mqtt()
buscar_previsao()
oled_print("Enviando Relatorio...")
if enviar_email(25.4, 62.8, 150): oled_print("Relatorio OK!")
else: oled_print("Erro no Email")
time.sleep(2)
while True:
agora = time.time()
agora_ms = time.ticks_ms()
if btn.value() == 0 and time.ticks_diff(agora_ms, last_btn) > 300:
tela = (tela + 1) % 4
last_btn = agora_ms
try:
sensor.measure()
temp, umid = sensor.temperature(), sensor.humidity()
except: temp, umid = 0, 0
luz, gas = ldr.read(), mq2.read()
if OLED_OK:
if tela == 0: mostrar_tela0(temp, umid)
elif tela == 1: mostrar_tela1(gas, luz)
elif tela == 2: mostrar_tela2()
elif tela == 3: mostrar_tela3(network.WLAN(network.STA_IF).isconnected(), mqtt_client is not None)
if agora - last_sheets > 30:
gravar_sheets(temp, umid)
soma_temp += temp
soma_umid += umid
num_leituras += 1
last_sheets = agora
if agora - last_mqtt > 5:
publicar_mqtt(temp, umid, luz, gas)
last_mqtt = agora
time.sleep(0.01)