Added Teams code to uC

This commit is contained in:
Jarrad Ashton Brown 2026-02-28 14:38:36 -06:00
parent 5eece1a2b6
commit 1e96d05660
4 changed files with 258 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

258
main.py Normal file
View file

@ -0,0 +1,258 @@
# MicroPython ESP32 - Guardián Fénix
# Sensores: BME680 + ADXL345
# Servidor web para mostrar datos y registros
import machine, time, ujson, network, socket, math
from machine import Pin, I2C
import bme680 # Asegúrate de tener la librería BME680 para MicroPython
import adxl345
# -------------------
# CONFIGURACIÓN SENSORES
# -------------------
i2c = I2C(scl=Pin(5), sda=Pin(4))
# BME680
bme = bme680.BME680(i2c)
# ADXL345
acc = adxl345.ADXL345(i2c)
# -------------------
# CONFIGURACIÓN WIFI (HOTSPOT)
# -------------------
ssid = "GuardianFenix"
password = "12345678"
ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid=ssid, password=password)
print("Hotspot activo:", ssid)
# -------------------
# VARIABLES
# -------------------
registros = [] # Lista de registros
aceptar_vib = False
alerta_activa = False
# -------------------
# FUNCIONES DE SENSORES
# -------------------
def leer_bme680():
bme.measure(gas=False)
temp = bme.temperature()
hum = bme.humidity()
pres = bme.pressure()
return {"temp": round(temp,1), "hum": round(hum,1), "pres": round(pres,1)}
def leer_adxl345():
x, y, z = acc.read_g() # m/s²
vib = abs((x*2 + y*2 + z*2) * 2)
estado = "Estable"
global alerta_activa
if vib > 6:
estado = "Inestable"
alerta_activa = True
else:
alerta_activa = False
return {"vib": round(vib,2), "estado": estado}
# -------------------
# REGISTRO AUTOMÁTICO
# -------------------
def registrar():
datos = leer_bme680()
vib = leer_adxl345()
datos["vib"] = vib["vib"]
datos["estado"] = vib["estado"]
datos["hora"] = time.localtime()[3:6] # HH:MM:SS
registros.append(datos)
# Mantener solo últimos 100 registros
if len(registros) > 100:
registros.pop(0)
return datos
# -------------------
# SERVIDOR WEB
# -------------------
def web_page():
return """<!doctype html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Guardián Fénix</title>
<style>
body{font-family:Arial,sans-serif;background:#fdf2f2;color:#333;margin:16px}
h1{margin:8px 0 16px 0}
.card{background:#fff;padding:16px;margin:12px 0;border-radius:12px;box-shadow:0 4px 10px rgba(0,0,0,.12);}
button{background:#c62828;color:#fff;border:none;padding:10px 14px;border-radius:8px;cursor:pointer;margin:6px 6px 0 0;}
.row{display:flex;flex-wrap:wrap;gap:12px}
.stat{min-width:160px}
.big{font-size:28px;font-weight:700}
table{width:100%;border-collapse:collapse;font-size:.9em;margin-top:10px}
th,td{border:1px solid #ccc;padding:6px;text-align:center}
th{background:#f3d6d6}
.mono{font-family:ui-monospace,Menlo,Consolas,monospace}
</style>
</head>
<body>
<h1>🛡 Guardián Fénix 🔥</h1>
<div class="card">
<h2>🌿 Sensor Ambiental (BME680)</h2>
<div class="row">
<div class="stat"><div>Temp</div><div class="big"><span id="temp">--</span> °C</div></div>
<div class="stat"><div>Hum</div><div class="big"><span id="hum">--</span> %</div></div>
<div class="stat"><div>Pres</div><div class="big"><span id="pres">--</span> hPa</div></div>
<div class="stat"><div>Gas</div><div class="big"><span id="gas">--</span> Ω</div></div>
</div>
</div>
<div class="card">
<h2>📳 Vibración (ADXL345)</h2>
<div class="row">
<div class="stat"><div>Shake</div><div class="big"><span id="shake">--</span></div></div>
<div class="stat mono">ax=<span id="ax">--</span>g</div>
<div class="stat mono">ay=<span id="ay">--</span>g</div>
<div class="stat mono">az=<span id="az">--</span>g</div>
</div>
</div>
<div class="card">
<h2>📝 Registros</h2>
<button id="btnNow">Leer ahora</button>
<button id="btnLog">Guardar registro</button>
<button id="btnClear">Borrar último</button>
<table>
<thead>
<tr>
<th>#</th><th>Hora</th><th>Temp</th><th>Hum</th><th>Pres</th><th>Gas</th><th>Shake</th>
</tr>
</thead>
<tbody id="tabla"></tbody>
</table>
</div>
<script>
const el = (id)=>document.getElementById(id);
function setText(id, v) {
el(id).textContent = (v===null || v===undefined) ? "--" : v;
}
function drawTable(list) {
const tb = el("tabla");
tb.innerHTML = "";
const last = list.slice(-20); // show last 20
last.forEach((r, i) => {
const hora = Array.isArray(r.hora) ? `${r.hora[0]}:${r.hora[1]}:${r.hora[2]}` : "--";
tb.innerHTML += `
<tr>
<td>${list.length - last.length + i + 1}</td>
<td>${hora}</td>
<td>${r.temp ?? "--"}</td>
<td>${r.hum ?? "--"}</td>
<td>${r.pres ?? "--"}</td>
<td>${r.gas ?? "--"}</td>
<td>${r.shake ?? r.vib ?? "--"}</td>
</tr>`;
});
}
async function refresh() {
try {
const r = await fetch("/data");
const d = await r.json();
// If /data returns a single object:
if (!Array.isArray(d)) {
setText("temp", d.temp ?? d.t_c);
setText("hum", d.hum ?? d.h_pct);
setText("pres", d.pres ?? d.p_hpa);
setText("gas", d.gas ?? d.gas_ohms);
setText("ax", d.ax);
setText("ay", d.ay);
setText("az", d.az);
setText("shake", d.shake ?? d.vib);
return;
}
// If /data returns the whole registros list:
drawTable(d);
const last = d[d.length-1];
if (last) {
setText("temp", last.temp);
setText("hum", last.hum);
setText("pres", last.pres);
setText("gas", last.gas);
setText("shake", last.shake ?? last.vib);
}
} catch (e) {
console.log("refresh error", e);
}
}
// Buttons call your endpoints AND then refresh screen
el("btnNow").onclick = async () => { await fetch("/leer"); await refresh(); };
el("btnLog").onclick = async () => { await fetch("/guardar"); await refresh(); };
el("btnClear").onclick = async () => { await fetch("/borrar"); await refresh(); };
setInterval(refresh, 1000);
refresh();
</script>
</body>
</html>"""
# -------------------
# SERVIDOR
# -------------------
addr = socket.getaddrinfo('192.168.4.1',80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(5)
print('Servidor escuchando en', addr)
def handle_client(cl):
try:
req = cl.recv(1024)
req = str(req)
if 'GET /data' in req:
res = ujson.dumps(registros)
cl.send('HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n\r\n')
cl.send(res)
elif 'GET /leer' in req:
d = registrar()
cl.send('HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n\r\n')
cl.send(ujson.dumps(d))
elif 'GET /guardar' in req:
d = registrar()
cl.send('HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n\r\n')
cl.send(ujson.dumps(d))
elif 'GET /borrar' in req:
if registros:
registros.pop()
cl.send('HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n\r\n')
cl.send(ujson.dumps(registros))
elif 'GET /toggle' in req:
global aceptar_vib
aceptar_vib = not aceptar_vib
cl.send('HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n\r\n')
cl.send(ujson.dumps({"aceptar_vib":aceptar_vib}))
else:
cl.send('HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n')
cl.send(web_page())
except Exception as e:
print("Error:", e)
cl.close()
# Loop principal
while True:
registrar()
cl, addr = s.accept()
handle_client(cl)

BIN
uC/.DS_Store vendored Normal file

Binary file not shown.

BIN
uC/main_uC/.DS_Store vendored Normal file

Binary file not shown.