Как предотвратить зависание веб-сервера WiFi датчика температуры на базе ESP8266? - PullRequest
1 голос
/ 27 апреля 2020

Я пытаюсь построить систему управления отоплением, в которой в каждой комнате дома установлен датчик температуры DHT22, подключенный к плате с поддержкой Wi-Fi ESP8266, с микро python 1.2 "стабильной".

плата "MakerHawk ESP8266 NodeMCU LUA CP2102 ESP-12F WiFi Inte rnet Плата разработчика Последовательный беспроводной модуль для Arduino IDE / Micro python Новая версия" от Amazon .

Начальная фаза проекта включает в себя платы ESP8266, отображающие температуру через встроенный веб-сервер, и работу на моем файловом сервере Ubuntu, которая запрашивает веб-страницы и помещает результаты в мою локальную базу данных графит . Я выбрал этот подход, потому что таким образом плата ESP8266 не должна иметь надежную временную метку. (Весь приведенный ниже код, касающийся времени, предназначен для передачи точной отладочной информации, а не для фактического сбора данных).

Из моих графанов показаний моей графитовой базы данных у меня есть данные каждые несколько секунд от веб-серверов. Однако один раз в два или три дня одна из плат ESP8266 будет go отключена на несколько часов . Иногда они возвращаются сами по себе, но обычно отключение происходит достаточно долго, и я замечаю, что go и выключение и включение питания неисправной платы.

Платы ESP8266 работают в довольно загруженной среде wifi c wifi с технически подкованных подростков, так что следует ожидать сканирования порта nmap и тому подобное. Мне нужно разобраться с потенциальными ситуациями DOS (учитывая очень ограниченную память на ESP8266) и по-прежнему возвращать температуру каждую минуту или около того.

Код для ESP8266 micro python следует (собран из разных источников на inte rnet);

boot.py:

# This file is executed on every boot (including wake-boot from deepsleep)
#import esp
#esp.osdebug(None)
import uos, machine
import uos as os
#uos.dupterm(None, 1) # disable REPL on UART(0)

import gc
gc.collect()

import webrepl
webrepl.start()

main.py:

import machine
import dht
# DHT22 compatible sensor with middle (sensor) pin
d = dht.DHT22(machine.Pin(0))

html = """<!DOCTYPE html>
<html>
    <head> <title>ESP8266 Temperature and Humidity</title> </head>
    <body> <p>
        Temperature %s
        Humidity %s
    </p> </body>
</html>
"""

access_points = {
    'home':'feedfooddeadbeef',
    'home2':'feedfooddeadbeef',
    'home3':'feedfooddeadbeef',
}

import utime
import network
sta_if = network.WLAN(network.STA_IF)

import ntptime
rtc = machine.RTC()

lifetime = 0

# Connect to list of wifi networks; based on code from https://forum.micropython.org/viewtopic.php?t=2951
def try_connection():
    t = 60
    while not sta_if.isconnected() and t > 0:
        print('.', end='')
        utime.sleep_ms(500)
        t = t - 1
    return sta_if.isconnected()

def try_to_connect():
    if sta_if.isconnected():
        print('Network connected OK')
    else:
        print('Network disconnected. Trying to connect ...', end='')
        sta_if.active(True)
        # Scan for available networks
        ap_list = sta_if.scan()
        # Sort by signal strength
        ap_list.sort(key=lambda ap: ap[3], reverse=True)
        # Filter out unknown access points
        ap_list = list(filter(lambda ap: ap[0].decode('UTF-8') in access_points.keys(), ap_list))
        for ap in ap_list:
            essid = ap[0].decode('UTF-8')
            if not sta_if.isconnected():
                print('Trying to connect to new network %s ...' % essid, end='')
                sta_if.connect(essid, access_points[essid])
                print(try_connection())
        if sta_if.isconnected():
            print('network config:', sta_if.ifconfig())
        else:
            print('Unable to connect.')

def connect():
    while True:
        try_to_connect()
        if sta_if.isconnected():
            break
        utime.sleep(60)

try:
    import usocket as socket
except:
    import socket

addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]

s = socket.socket()
s.settimeout(30)
s.bind(addr)
s.listen(5)

print('listening on', addr)
failcount = 1
while True:
    lifetime = lifetime + 1
    print("Lifetime is", lifetime)
    if failcount > 10 or lifetime > 500:
        print("Resetting due to old age")
        machine.reset()

    while True:
        try_to_connect()
        if sta_if.isconnected():
            break
        utime.sleep(60)

    print("Waiting for connection attempt %d ..." % failcount)
    try:
        cl, addr = s.accept()
    except OSError:
        failcount = failcount + 1
        continue
    failcount = 1

    try:
        ntptime.settime()
    except (OSError, OverflowError):
        pass
    print('temperature client connected from', addr, 'at ', end='')
    print(rtc.datetime())
    try:
        request=cl.recv(1024)
    except OSError:
        cl.close()
        continue

    print('Content of request:', request)
    print("Trying to measure ...")
    while True:
        try:
            d.measure()
        except OSError:
            continue
        break
    t = d.temperature()
    h = d.humidity()
    print("Got measurement Temperature %s humidity %s" % (t, h))
    response = html % (t, h)

    try:
        cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
    except OSError:
        pass

    try:
        cl.send(response)
    except OSError:
        pass

    cl.close()

...