ECONNABORTED при размещении с микропифона на NodeMCU с использованием запросов - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть небольшой сервер Python, на который я могу отправлять команды POST, чтобы управлять моими лампами LIFX.От Почтальона я могу спамить столько, сколько мне нравится, и никогда не вижу ошибки, но я пытаюсь создать пару настенных переключателей, которые запускают источники света с помощью плат NodeMCU, и оттуда я получаю сообщения об ошибках ECONNABORTED.примерно на 1 из 5 запросов.

Везде, где я искал решения, проблема была либо в неверно настроенном сервере, либо в неверно настроенном клиенте, но мне интересно, есть ли здесь что-то еще.Мой серверный код прост, и, как я уже сказал, он работает, когда запускается отовсюду, кроме моих плат 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 минуты), но иногда это не так.

Ответы [ 2 ]

0 голосов
/ 09 марта 2019

Хорошо, сборщик мусора решил это.Теперь я могу нажать кнопку, и она работает каждый раз!Я могу настроить задержки, чтобы быть как можно более жестким.Было бы неплохо запросить запросы, если они заняты, а не просто грубая задержка, но эй ...

Вот цикл 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()
0 голосов
/ 09 октября 2018

Попробовав все, что я мог придумать, чтобы это исправить, я пришел к выводу, что проблема заключается в том, что ESP8266 не может обработать начальное рукопожатие с сервера.Я считаю, что он может просто не в состоянии управлять объемом трафика в сети, поэтому он захватывает.Запустив wireshark на сервере, я вижу несколько TCP Spurious Retransmission s, когда получаю неудачный ответ.

У меня есть плата ESP32 на заказ, что должно позволить мне проверить мою теорию.

ПравитьЯ наконец-то понял, что проблема была в том, что укрёсты оставляли розетки открытыми повсюду.Поэтому нам нужно правильно закрыть ответ:

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

... 

response.close()

Это решило мою проблему, хотя я не могу объяснить, почему сокеты не закрывались в конце поста, что, как представляется,функции библиотеки.

...