我试图为ESP32板编写一个简单的程序。我的主程序相当简单,它必须在循环中运行。另一方面,设备还需要能够以非常简单的响应响应HTTP请求。
这是我的尝试(https://randomnerdtutorials.com/micropython-esp32-esp8266-bme280-web-server/的重做):
try:
import usocket as socket
except:
import socket
from micropython import const
import time
REFRESH_DELAY = const(60000) #millisecondi
def do_connect():
import network
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('connecting to network...')
wlan.config(dhcp_hostname=HOST)
wlan.connect('SSID', 'PSWD')
while not wlan.isconnected():
pass
print('network config:', wlan.ifconfig())
import json
import esp
esp.osdebug(None)
import gc
gc.collect()
do_connect()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, SENSOR_SCKT_PORT))
s.listen(5)
prevRun = 0
i = 0
while True:
print("iteration #"+str(i))
i += 1
# run every 60 seconds
curRun = int(round(time.time() * 1000))
if curRun - prevRun >= REFRESH_DELAY:
prevRun = curRun
# MAIN PROGRAM
# ......
# whole bunch of code
# ....
# run continuously:
try:
if gc.mem_free() < 102000:
gc.collect()
conn, addr = s.accept()
conn.settimeout(3.0)
print('Got a connection from %s' % str(addr))
request = conn.recv(1024)
conn.settimeout(None)
request = str(request)
#print('Content = %s' % request)
measurements = 'some json stuff'
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.send(measurements)
conn.close()
except OSError as e:
conn.close()
print('Connection closed')所发生的情况是,我只得到迭代#0,然后while True循环停止。如果我用HTTP请求来平这个服务器,我就会得到一个正确的响应,循环前进到迭代#1和#2 (不知道为什么它认为我用2个请求来点击它)。因此,socket.listen(5)似乎停止了while循环。
有什么办法可以避免这种情况吗?还有其他解决办法吗?我不认为线程是一种选择。
发布于 2021-01-09 19:57:04
问题是,s.accept()是一个阻塞的call...it,它在接收到连接之前不会返回。这就是为什么它暂停你的循环。
最简单的解决方案可能是在调用s.accept()之前检查连接是否在等待;您可以使用select.select或select.poll来完成这一任务。我更喜欢select.poll API,它最终看起来如下所示:
import esp
import gc
import json
import machine
import network
import select
import socket
import time
from micropython import const
HOST = '0.0.0.0'
SENSOR_SCKT_PORT = const(1234)
REFRESH_DELAY = const(60000) # milliseconds
def wait_for_connection():
print('waiting for connection...')
wlan = network.WLAN(network.STA_IF)
while not wlan.isconnected():
machine.idle()
print('...connected. network config:', wlan.ifconfig())
esp.osdebug(None)
gc.collect()
wait_for_connection()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, SENSOR_SCKT_PORT))
s.listen(5)
poll = select.poll()
poll.register(s, select.POLLIN)
prevRun = 0
i = 0
while True:
print("iteration #"+str(i))
i += 1
# run every 60 seconds
curRun = int(round(time.time() * 1000))
if curRun - prevRun >= REFRESH_DELAY:
prevRun = curRun
# MAIN PROGRAM
# ......
# whole bunch of code
# ....
# run continuously:
try:
if gc.mem_free() < 102000:
gc.collect()
events = poll.poll(100)
if events:
conn, addr = s.accept()
conn.settimeout(3.0)
print('Got a connection from %s' % str(addr))
request = conn.recv(1024)
conn.settimeout(None)
request = str(request)
# print('Content = %s' % request)
measurements = 'some json stuff'
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.send(measurements)
conn.close()
except OSError:
conn.close()
print('Connection closed')您将注意到,我已经对您的代码进行了一些处理,以便在我的设备上运行它,并满足我的风格感;首先,我已经删除了您的大部分do_connect方法,并将所有的import放在文件的顶部。
真正的变化是:
select.poll()对象:民意测验= select.poll()
POLLIN事件的s变量:select.POLLIN) (s,poll.register)
事件= poll.poll(100)如果事件: conn,addr = s.accept() conn.settimeout(3.0) .
在进行了这些更改之后,运行代码并发出请求如下所示:
iteration #0
iteration #1
iteration #2
iteration #3
iteration #4
iteration #5
iteration #6
Got a connection from ('192.168.1.169', 54392)
iteration #7
iteration #8
iteration #9
iteration #10注意,正如这里所写的,您的循环将至少每100 as迭代一次(您可以通过在调用poll.poll()时更改超时来控制这一点)。
注意:上面的测试是在运行esp8266 v1.13-268-gf7aafc062的一个MicroPython设备( Wemos D1克隆)上进行的。
https://stackoverflow.com/questions/65646815
复制相似问题