Servidor Web en Esp32-Cam con MicroPython escritura y lectura archivo de texto
Presentación
El presente proyecto continuando sobre modos de programacion alternativa la Esp32-Cam se desarrolla la posibilidad de escribir y leer un archivo de texto ubicado en la memoria de la placa
El proyecto consiste en montar en la placa Esp32-Cam un pequeño servidor web consistente en una pagina principal que permite el ingreso de texto que luego mediante un boton podra ser grabado en un archivo ubicado en la misma placa, y despues mediante otro boton se logra la lectura del contenido del archivo.
Una vez arrancada la placa y al ingresar a traves del navegador se ve la siguiente pantalla:
En la misma se ven dos campos que permiten el ingreso de texto, en el primero se ingresa el nombre del autor y en el segundo el texto, luego mediante el boton Escribir en el archivo se agrega el texto al archivo que esta en la placa llamado lista.txt
Mediante el botón Leer el archivo se muestra el contenido del archivo en el campo ubicado a la derecha de la pantalla
Finalmente el botón Borrar lectura de archivo vacia el campo de la derecha de la pantalla, sin afectar el contenido del archivo
Materiales
Placa Esp32-Cam
Programador Esp32-Cam
Si bien por ser mas cómodo y práctico se ha usado el adaptador el mismo puede ser remplazado por una placa FTDI y el cableado pertinente.
Montaje del proyecto en la placa Esp8266
Para utilizar la placa Esp32-Cam con MicroPython es necesario flashear primero la misma con el firmware correspondiente. En el caso de la utilizada en este modelo se utilizo el provisto por la pagina de https://github.com/lemariva/micropython-camera-driver/tree/master/firmware
Una vez instalado el firmware en la placa utilizando la utilidad que viene provista por el IDE Thonny, o por aquella que ustedes utilicen ademas del firmware quedara grabado en la placa un archivo boot.py que debe ser reemplazo por el que se incluye en el codigo desarrollado a continuacion.
Codigo
El codigo se ha escrito en tres archivos boot.py, main.py y pagina.py.
El archivo boot.py ademas de contener los datos necesarios para el arranque de la placa, contiene los datos de la red wifi a la que se va a conectar los cuales deben ser agregados en el lugar indicado.
El archivo main.py es el nucleo del servidor, el nombre elegido para el mismo es a efectos que el programa se inicie automaticamente. Este archivo contiene los llamadas y respuestas a las paginas web y las funciones correspondientes a la escritura y lectura del archivo ubicado en la placa.
El archivo pagina.py esta destinado a contener las distintas paginas html que seran servidas por el servidor conforme las llamadas que se realicen a traves de la funcion 'pagina_web(n_pag):' que se encuentra en el archivo main.py.
boot.py
from machine import Pin, reset
import network
import socket
import time
import esp
esp.osdebug(None)
#Recupera la memoria ocupada por objetos que no son necesarios para el programa
import gc
gc.collect()
#Coneccion WiFi
#completar con los datos correspondientes
red = ' '#nombre de la red
clave = ' ' #clave de la red
indicator = Pin(0, Pin.OUT)
wlan = network.WLAN(network.STA_IF)
if not wlan.isconnected():
wlan.active(True)
wlan.connect(red, clave)
print('Conectando a: %s' % red)
timeout = time.ticks_ms()
while not wlan.isconnected():
indicator.on()
time.sleep(0.15)
indicator.off()
time.sleep(0.15)
if (time.ticks_diff (time.ticks_ms(), timeout) > 10000):
break
if wlan.isconnected():
indicator.on()
print('Se conecto a: %s' % red)
print('IP: %s\nSUBNET: %s\nGATEWAY: %s\nDNS: %s' % wlan.ifconfig()[0:4])
else:
indicator.off()
wlan.active(False)
print('Fallo la conexion a: %s' % ssid)
else:
indicator.on()
print('Conectado a\nIP: %s\nSUBNET: %s\nGATEWAY: %s\nDNS: %s' % wlan.ifconfig())
main.py
import pagina
contenido = ""
#Pagina Web
def pagina_web(recibo):
html = pagina.pagina(1,recibo)
return html
#Socket Configuracion
try:
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_socket.bind(('', 80))
tcp_socket.listen(5)
time.sleep(1)
print('Configuracion de socket exitosa\n')
except OSError as e:
print('Fallo configuracion de socket. Reeinicia...\n')
time.sleep(3)
reset()
print('Listo...!\n********************************\n')
while True:
try:
if gc.mem_free() < 102000:
gc.collect()
conn, addr = tcp_socket.accept()
conn.settimeout(3.0)
print('Nueva conexion de: %s' % str(addr[0]))
request = conn.recv(1024)
conn.settimeout(None)
request = str(request)
if request.find('/pag') == 7:
pag = request[11:14]
if pag == 'esc':
ini = request.find('user_name=')
med = request.find('user_message=')
fin = request.find('user_fin=')
usuario = request[ini+10:med-1]
mensaje = request[med+13:fin-1]
usuario = usuario.replace('+', ' ')
mensaje = mensaje.replace('+', ' ')
with open('lista.txt', 'a') as f:
f.write(usuario + '\n')
f.write(mensaje + '\n')
f.close
elif pag == 'lee':
with open("lista.txt") as archivo:
contenido = ""
for linea in archivo:
contenido = contenido + linea
elif pag == 'vac':
contenido = ""
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.sendall(pagina_web(contenido))
conn.close()
except OSError as e:
conn.close()
time.sleep(0.1)
pagina.py
def pagina(ped, muestra):
if ped == 1:
pagina_html = """
<!DOCTYPE html>
<html>
<head>
<title>MicroPython</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
.nav{
box-sizing: border-box; display: inline-block;
padding: 10px 0px 10px 0px; background-color:#F8DB9C;
width: 100%; height: auto;
}
#t1{
font-family: Helvetica; font-weight: bold;
text-align: center; font-size: 50px; color: red;
}
#t2{
font-family: Helvetica; font-weight: bold;
text-align: center; font-size: 20px; color: blakc;
}
#tabla {
width:100%;
background-color:#99FF33;
}
#tabla, th, td {
border: 1px solid black;
}
#texto{
width: 95%;
height: 400px;
}
</style>
</head>
<body>
<div class='nav'>
<h1 id='t1'>Servidor Web Esp32-Cam</h1>
<h2 id='t2'>Lectura y escritura de archivo de texto</h2>
</div>
<div>
<table id=tabla>
<tr>
<td>
<center>
<form action="/pagescribe" method="post">
<br>
<label for="name">Autor:</label>
<input type="text" id="name"
name="user_name">
<br>
<label for="msg">Texto:</label>
<textarea id="msg" name="user_message"></textarea>
<input type="hidden" name="user_fin">
<br>
<button type="submit">Escribir en el archivo</button>
<br>
</form>
<br><br><br>
<form action="/pagleer" method="post">
<button type="submit">Leer el archivo</button>
</form>
<br><br><br>
<form action="/pagvaciar" method="post">
<button type="submit">Borrar lectura archivo</button>
<p> NO borra el archivo solo la lectura que se muestra</p>
</form>
</center>
</td>
<td>
<h4>Contenido del Archivo</h4>
<textarea id="texto">""" + muestra + """</textarea>
</td>
</tr>
</table>
</div>
</body>
</html>
"""
return pagina_html
if ped == 0:
pagina_html = """<html>
<head>
</head>
<body align="center">
<br>
<h1>Pagina inexistente</h1>
</body>
</html>"""
return pagina_html