Webserver med esp32

Målet er å implementere en webserver på en esp32 som presenterer en nettside som viser verdien på den interne hall effekt sensoren.

Utstyr

  • Esp32 wroom 32
  • Kabel USB-A til USB micro

Kode

Sensor.py

Data objektet inneholder sensor verdiene. Timer objektet er satt opp til å hente data hvert sekund og kaller getNewSensorValue metoden. Når 300 verdier er lagt inn i listen så fjerner vi det første objektet i listen.

getSensorValues metoden returnerer sensorverdiene til webserver koden.

import esp32
from machine import Timer

class Sensor:

    data = []
    timer: Timer = Timer(0)

    def __init__(self):
        self.timer.init(period=1000, mode=Timer.PERIODIC, callback=lambda t:self.getNewSensorValue() )

    def getSensorValues(self):
        return self.data

    def getNewSensorValue(self):
        val = esp32.hall_sensor()
        self.data.append(val)
        if len(self.data) > 300:
            self.data.pop(0)

Webserver.py

app objektet initialiserer Microdot som jeg har brukt for å sette opp stiene for å returnere data, chart.js koden og index.html filen.

I konstruktoren så kobles det opp mot WIFI og så startes microdot webserveren på port 80.

import json
import network
from microdot import Microdot, Response, send_file
from sensor import Sensor
from props import Properties

app = Microdot()
sensor = Sensor()

class Webserver:

    properties = None

    def __init__(self, properties: Properties) -> None:
        self.properties = properties
        wifi = network.WLAN(network.STA_IF)
        wifi.active(True)
        wifi.connect(properties.getSsid(), properties.getPassword())
        while wifi.isconnected() is False:
            pass
        print(wifi.ifconfig())
        app.run(port="80")

@app.route('/', methods=['GET'])
def indexRoute(request):
    return send_file("/index.html")

@app.route('/data', methods=['GET'])
def dataRoute(request):
    response = Response(json.dumps(sensor.getSensorValues()))
    return response

@app.route('/chart.js', methods=['GET'])
def staticChartjs(request):
    return send_file("/chart.js")

Props.py

Her lastes egenskap filen inn og dataene gjøres tilgjengelig. Egenskap filen er lagret i properties/application.properties og ligger ikke i github kodenbasen fordi den inneholder passord og ssid til wifi nettverket mitt. Filen skal se slik ut

ssid:<SSID>

passwd:<Passord>

class Properties:
    SSID_PROPERTY_NAME = "ssid"
    PASSWD_PROPERTY_NAME = "passwd"
    ENCODING = "utf8"
    PROP_SEPARATOR = ":"

    properties = {}

    def __init__(self) -> None:
        with open('properties/application.properties', 'r', encoding=self.ENCODING) as file:
            for line in file:
                vals = line.split(self.PROP_SEPARATOR)
                self.properties[vals[0]] = vals[1].replace('\n', ' ').replace('\r', '').replace(' ','')
        print(self.properties)

    def getProperty(self, propertyName):
        return self.properties[propertyName]

    def getSsid(self):
        return self.getProperty(self.SSID_PROPERTY_NAME)

    def getPassword(self):
        return self.getProperty(self.PASSWD_PROPERTY_NAME)

Main.py

Her initialiseres prosjektet. Dette er koden som startes opp. I micropython så kjøres boot.py først og så main.py. I dette prosjektet så er det ikke noe kode i boot.py

from props import Properties
from webserver import Webserver

print("Read properties")

properties = Properties()

webServer = Webserver(properties)

while True:
    pass

Index.html

Dette er html filen som returneres på roten. Her hentes chart.js bibloteket på /chart.js og data fra /data stiene.

Her kjører vi en timer som henter data hvert andre sekund og oppdaterer linjediagrammet.

<!DOCTYPE html>
<html lang="en">
  <head>
     <meta charset="utf-8">
     <title>Hall effecct sensor values</title>  
  </head>
  /chart.js
  <body>
     <h1>Hall effect sensor values</h1>
     <div id="chart" style="max-width:100%;max-height:700px">
      <canvas id="chartCanvas"></canvas>
      </div>
      <script>
        
        function getData() {
          var xhttp = new XMLHttpRequest();
          xhttp.onreadystatechange = function () {
            if (this.readyState == 4 && this.status == 200) {
              var json = JSON.parse(this.response);        
              updateChart(json); 
            }
          };
          xhttp.open("GET", "/data", false);
          xhttp.send();     
        }   

        const ctx = document.getElementById('chartCanvas');

        var chart = new Chart(ctx, {
            type: 'line',
            data: {
              labels: Array.from({ length: 300 }, (value, index) => index),
              datasets: [{
                label: 'Value',
                data: [],
                borderWidth: 1,
                fill: false,
                borderColor: 'rgb(75, 192, 192)',
                tension: 0.1                
              }]
            },
            options: {
              scales: {
                y: {
                  beginAtZero: true
                }
              },
              animation: {
                duration: 0
              },
              hover: {
                animationDuration: 0
              },
              responsiveAnimationDuration: 0
            }
          });

        window.setInterval(getData, 2000);

        function updateChart(values) {
          chart.data.datasets[0].data = values;
          chart.update();
        }

    </script>
  </body>
 </html>

Resultat

På min PC starter den opp på ip 192.168.10.129 og her er resultatet. Har kjørt en magnet over for å se at hall effekt sensoren fungerer. Dette er alle relative verdier, ikke i noen enhet.

Konklusjon

Relativt enkelt å utvikle, liker micropython selv om det ikke er alt med python jeg liker. Skal lage en beskrivelse for å sette opp utviklingsmiljøet i visual studio code, men det blir senere.