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
      
    

Cerrar