我正在尝试构建一个供暖控制系统,其中房屋中的每个房间都将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()