使用请求从 NodeMCU 上的 micropython 发布时 ECONNABORTED
ECONNABORTED when POSTing from micropython on NodeMCU using requests
我有一个小型 Python 服务器,我可以 POST 命令它来控制我的 LIFX 灯。从邮递员那里,我可以随心所欲地发送垃圾邮件,而且永远不会看到错误,但是我想做的是构建几个使用 NodeMCU 板触发灯的墙壁开关,从那里,我收到了 ECONNABORTED 错误大约五分之一的请求。
我到处寻找解决方案,问题实际上要么是服务器配置错误,要么是客户端配置错误,但我想知道这里是否还有其他问题。我的服务器代码很简单,而且正如我所说,它似乎在从除我的 NodeMCU 板以外的任何地方触发时都能正常工作。
main.py:
from machine import Pin, reset
from time import sleep
import urequests
# set these two pins as required to up/down
buttonUp = Pin(4, Pin.IN, Pin.PULL_UP)
buttonDown = Pin(5, Pin.IN, Pin.PULL_UP)
light = "LightName"
# button can be pressed, held or double pressed
# press = 1x press, 1x release in .5 seconds
# hold = 1x press, 0x release
# double = 2x press, 2x release in .5 seconds
def detectPress():
pressed = False
press = 0
direction = 'up'
release = 0
if not buttonUp.value() or not buttonDown.value:
pressed = True
if not buttonDown.value():
direction = 'down'
while buttonUp.value() and buttonDown.value():
sleep(.01) # wait for a button push
for x in range(8):
if pressed == False:
if not buttonUp.value():
direction = 'up'
pressed = True
press += 1
if not buttonDown.value():
direction = 'down'
pressed = True
press += 1
else:
if direction == 'up':
if buttonUp.value():
pressed = False
release += 1
else:
if buttonDown.value():
pressed = False
release += 1
sleep(.1)
return press, release, direction
error_count = 0
while True:
if error_count >= 5:
print ("Too many errors. Resetting...")
reset()
pressed, released, direction = detectPress()
sleep_time = .1
if pressed >= released:
packet = {"light": light}
if pressed == released:
if pressed == 0:
held = True
else:
held = False
else:
held = True
if pressed > 1:
double = True
else:
double = False
if double is True:
packet["level"] = "full"
if held is True and double is False:
packet["dim"] = direction
sleep_time = 0.8 # don't spam the server/crash the board
if held is False and double is False:
if direction == 'up':
packet["level"] = 'on'
else:
packet["level"] = 'off'
print (pressed, released, direction, held, double, packet)
try:
response = urequests.post("http://192.168.1.10:7990/lights", headers={'Connection': 'Close'}, json = packet)
if error_count > 0:
error_count -= 1
urequests.usocket.reset()
except Exception as e:
error_count += 1
print ("Error sending packet {}: {} - error count is at {} retrying...".format(packet, repr(e), error_count))
urequests.usocket.reset()
sleep(1)
try:
response = urequests.post("http://192.168.1.10:7990/lights", headers={'connection': 'Close'}, json = packet)
except Exception as e:
error_count += 1
print ("retry failed")
pass
pass
print ("waiting {}".format(sleep_time))
sleep(sleep_time)
我怀疑这是一个套接字问题,但不知道还能做些什么来调试它。
在重新设置时,我几乎可以保证前 4 或 5 个传输会工作。我也几乎可以保证在 3 或 4 次传输后按住按钮(每秒触发一次命令)会失败。
有时重试有效,但更多时候无效。
大多数时候失败后,等5秒再试就可以了,但有时不行。
大多数情况下,长时间延迟(>1 分钟)后的初始按下会起作用,但有时不会。
在尝试了所有我能想到的解决方法之后,我得出的结论是 ESP8266 未能处理来自服务器的初始握手。我相信它可能只是无法管理网络上的流量,所以它卡住了。 运行 服务器上的 wireshark 当我收到失败的响应时,我看到了几个 TCP Spurious Retransmission
。
我已经订购了一块 ESP32 开发板,我可以用它来检验我的理论。
编辑:我终于发现问题是 urequests 让套接字到处都是打开的。因此我们需要正确关闭响应:
response = urequests.post(url, ...)
...
response.close()
这解决了我的问题,尽管我无法解释为什么套接字在 post 结束时没有关闭,这似乎是库的功能。
好的,垃圾回收解决了它。现在我可以按下按钮,每次都能正常工作!我可能会调整延迟以使其尽可能紧凑。如果忙而不是粗略的延迟,查询 urequests 会很好,但是嘿...
这是发送请求的我的循环:
gc.enable()
while True:
time.sleep_ms(250)
if (btn1.value() == 0):
urequests.post(url, data=json.dumps(data_play))
time.sleep_ms(650)
while (btn1.value() == 0):
time.sleep_ms(200)
pass
gc.collect()
我有一个小型 Python 服务器,我可以 POST 命令它来控制我的 LIFX 灯。从邮递员那里,我可以随心所欲地发送垃圾邮件,而且永远不会看到错误,但是我想做的是构建几个使用 NodeMCU 板触发灯的墙壁开关,从那里,我收到了 ECONNABORTED 错误大约五分之一的请求。
我到处寻找解决方案,问题实际上要么是服务器配置错误,要么是客户端配置错误,但我想知道这里是否还有其他问题。我的服务器代码很简单,而且正如我所说,它似乎在从除我的 NodeMCU 板以外的任何地方触发时都能正常工作。
main.py:
from machine import Pin, reset
from time import sleep
import urequests
# set these two pins as required to up/down
buttonUp = Pin(4, Pin.IN, Pin.PULL_UP)
buttonDown = Pin(5, Pin.IN, Pin.PULL_UP)
light = "LightName"
# button can be pressed, held or double pressed
# press = 1x press, 1x release in .5 seconds
# hold = 1x press, 0x release
# double = 2x press, 2x release in .5 seconds
def detectPress():
pressed = False
press = 0
direction = 'up'
release = 0
if not buttonUp.value() or not buttonDown.value:
pressed = True
if not buttonDown.value():
direction = 'down'
while buttonUp.value() and buttonDown.value():
sleep(.01) # wait for a button push
for x in range(8):
if pressed == False:
if not buttonUp.value():
direction = 'up'
pressed = True
press += 1
if not buttonDown.value():
direction = 'down'
pressed = True
press += 1
else:
if direction == 'up':
if buttonUp.value():
pressed = False
release += 1
else:
if buttonDown.value():
pressed = False
release += 1
sleep(.1)
return press, release, direction
error_count = 0
while True:
if error_count >= 5:
print ("Too many errors. Resetting...")
reset()
pressed, released, direction = detectPress()
sleep_time = .1
if pressed >= released:
packet = {"light": light}
if pressed == released:
if pressed == 0:
held = True
else:
held = False
else:
held = True
if pressed > 1:
double = True
else:
double = False
if double is True:
packet["level"] = "full"
if held is True and double is False:
packet["dim"] = direction
sleep_time = 0.8 # don't spam the server/crash the board
if held is False and double is False:
if direction == 'up':
packet["level"] = 'on'
else:
packet["level"] = 'off'
print (pressed, released, direction, held, double, packet)
try:
response = urequests.post("http://192.168.1.10:7990/lights", headers={'Connection': 'Close'}, json = packet)
if error_count > 0:
error_count -= 1
urequests.usocket.reset()
except Exception as e:
error_count += 1
print ("Error sending packet {}: {} - error count is at {} retrying...".format(packet, repr(e), error_count))
urequests.usocket.reset()
sleep(1)
try:
response = urequests.post("http://192.168.1.10:7990/lights", headers={'connection': 'Close'}, json = packet)
except Exception as e:
error_count += 1
print ("retry failed")
pass
pass
print ("waiting {}".format(sleep_time))
sleep(sleep_time)
我怀疑这是一个套接字问题,但不知道还能做些什么来调试它。
在重新设置时,我几乎可以保证前 4 或 5 个传输会工作。我也几乎可以保证在 3 或 4 次传输后按住按钮(每秒触发一次命令)会失败。
有时重试有效,但更多时候无效。
大多数时候失败后,等5秒再试就可以了,但有时不行。
大多数情况下,长时间延迟(>1 分钟)后的初始按下会起作用,但有时不会。
在尝试了所有我能想到的解决方法之后,我得出的结论是 ESP8266 未能处理来自服务器的初始握手。我相信它可能只是无法管理网络上的流量,所以它卡住了。 运行 服务器上的 wireshark 当我收到失败的响应时,我看到了几个 TCP Spurious Retransmission
。
我已经订购了一块 ESP32 开发板,我可以用它来检验我的理论。
编辑:我终于发现问题是 urequests 让套接字到处都是打开的。因此我们需要正确关闭响应:
response = urequests.post(url, ...)
...
response.close()
这解决了我的问题,尽管我无法解释为什么套接字在 post 结束时没有关闭,这似乎是库的功能。
好的,垃圾回收解决了它。现在我可以按下按钮,每次都能正常工作!我可能会调整延迟以使其尽可能紧凑。如果忙而不是粗略的延迟,查询 urequests 会很好,但是嘿...
这是发送请求的我的循环:
gc.enable()
while True:
time.sleep_ms(250)
if (btn1.value() == 0):
urequests.post(url, data=json.dumps(data_play))
time.sleep_ms(650)
while (btn1.value() == 0):
time.sleep_ms(200)
pass
gc.collect()