繁体   English   中英

使用请求从NodeMCU上的micropython进行开机自检时进行ECONNABORTED

[英]ECONNABORTED when POSTing from micropython on NodeMCU using requests

我有一个小型的Python服务器,可以对其发布命令,以控制我的LIFX灯。 我可以从Postman尽可能多地发送垃圾邮件,而不会看到错误,但是我试图做的是使用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()

这解决了我的问题,尽管我无法解释的是为什么在文章结尾时套接字没有关闭,这似乎是库的功能。

好的,垃圾回收解决了它。 现在,我可以按该按钮,并且每次都能使用! 我可能会调整延迟,以使其尽可能紧凑。 查询urequests是否很忙,而不是仅是短暂的延迟,将是很好的选择,但是...

这是发出请求的my循环:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM