python - 当使用请求从 NodeMCU 上的 micropython 进行 POST 时,ECONNABORTED

标签 python python-requests nodemcu arduino-esp8266 micropython

我有一个小型 Python 服务器,我可以向其 POST 命令来控制我的 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虚假重传

我已经订购了一 block ESP32 板,这应该可以让我测试我的理论。

编辑:我终于发现问题是 urequests 使套接字到处都处于打开状态。因此我们需要正确关闭响应:

response = urequests.post(url, ...)

... 

response.close()

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

关于python - 当使用请求从 NodeMCU 上的 micropython 进行 POST 时,ECONNABORTED,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52430188/

相关文章:

python - 使用python音频处理的音符检测

node.js - 使用 Node 和 Python 对页面源进行哈希处理时的差异

azure - HTTPS 到 HTTP Azure IoT 中心

python - 用python从图像中提取裙子

python - 如何使setsockopt IP_ADD_MEMBERSHIP接受本地接口(interface)地址以仅在一个特定接口(interface)上接收多播数据包?

Python请求,PUT空数据

java - HttpURLConnection 应用程序因 ESP8266 而崩溃

lua - ESP8266、NodeMCU、软AP - UDP服务器类软AP、独立接入点

python - Django的objects.filter, "expensive"怎么会是这样?

ssl - 通过 HTTPS 通过其 IP 使用 Python 请求访问主机时出现问题