如何防止基于ESP8266的温度传感器wifi网络服务器挂起?

时间:2020-04-27 20:11:58

标签: python esp8266 micropython

我正在尝试构建一个供暖控制系统,其中房屋中的每个房间都将DHT22温度传感器连接到ESP8266具有wifi功能的板上,并运行micropython 1.2“ stable”。

板子为“适用于Arduino IDE / Micropython新版本的MakerHawk ESP8266 NodeMCU LUA CP2102 ESP-12F WiFi Internet开发板串行无线模块” from Amazon

该项目的初始阶段涉及ESP8266板通过内置的Web服务器显示温度,以及在我的Ubuntu文件服务器上的一项工作,查询网页并将结果推送到本地graphite数据库中。我选择这种方法是因为ESP8266开发板不需要可靠的时间戳。 (下面所有与时间有关的代码都是发出准确的调试信息,而不是收集实际数据)。

从我的石墨数据库的grafana读数中,我每隔几秒钟就从Web服务器获取数据。但是,每隔两三天,ESP8266板之一将脱机几个小时。有时它们会自己回来,但通常停机时间足够长,以至于我注意到并继续运行,然后重新启动有问题的电路板。

ESP8266开发板正在相当繁忙的家用wifi环境中运行,周围有精通技术的青少年,因此可以预期nmap端口扫描等。我需要处理潜在的DOS情况(鉴于ESP8266的内存非常有限),并且仍然每分钟左右返回一个温度。

随后是ESP8266 micropython的代码(从互联网上的各种来源中拼凑而成);

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()

0 个答案:

没有答案