Skip to content
This repository has been archived by the owner on Sep 4, 2021. It is now read-only.

The TCP reset issue #2

Open
clach04 opened this issue Jan 3, 2018 · 20 comments
Open

The TCP reset issue #2

clach04 opened this issue Jan 3, 2018 · 20 comments

Comments

@clach04
Copy link
Owner

clach04 commented Jan 3, 2018

Need more info., see issue #1

Original reported issue by @nijave:

Traceback (most recent call last):
  File "/config/custom_components/switch/tuya.py", line 103, in update
    self._status = self._device.status()
  File "/config/deps/lib/python3.6/site-packages/pytuya/__init__.py", line 223, in status
    data = s.recv(1024)
ConnectionResetError: [Errno 104] Connection reset by peer

Under Linux Python 3

@clach04 saw:

Traceback (most recent call last):
  File "demo_status.py", line 38, in <module>
    data = d.status()
  File "C:\Users\clach04\py\python-tuya_crypt\pytuya\__init__.py", line 228, in status
    data = s.recv(1024)
socket.error: [Errno 10054] An existing connection was forcibly closed by the remote host

This is under python 2.7. Suspect this is the same thing as original report.
NOTE I've not seen this under Py3 yet on my machine but I've had long runs when this never occurs.

@clach04
Copy link
Owner Author

clach04 commented Jan 3, 2018

@nijave I think the best way forward here is to add logging to your component, in https://github.com/nijave/home-assistant/blob/component-tuya/homeassistant/components/switch/tuya.py in the except block. Dump the exception that is seen.

@nijave
Copy link
Contributor

nijave commented Jan 3, 2018

Here is a zip of a pcap (from Wireshark) that shows a successful connection followed by what appears to be the outlet/Tuya device terminating the next request with a RST,ACK (see https://stackoverflow.com/questions/1434451/what-does-connection-reset-by-peer-mean)

172.16.2.1 is home-assistant
172.16.2.4 is the outlet

Both times it's requesting the status from the device and the requests appear to be exactly the same except for the packet headers

Voion connect followed by reset.zip

@nijave
Copy link
Contributor

nijave commented Jan 4, 2018

Traceback (most recent call last):
  File "/config/custom_components/switch/tuya.py", line 103, in update
    self._status = self._device.status()
  File "/config/deps/lib/python3.6/site-packages/pytuya/__init__.py", line 223, in status
    data = s.recv(1024)
ConnectionResetError: [Errno 104] Connection reset by peer

@clach04
Copy link
Owner Author

clach04 commented Jan 4, 2018

I've not had chance to review the pcap file, sorry :(

Recommend we add an exception catch for ConnectionResetError is you are consistently seeing this. As a first step, add that to your HA component (remove the bare except there at the moment).

For a quick test I wrote a script that hammered status checks:

data = d.status()
print('Dictionary %r' % data)
switch_state = data['dps']['1']

data = d.set_status(pytuya.ON)
if data:
    print('set_status() result %r' % data)
    print('set_status() extra %r' % data[20:-8])

data = d.status()
print('Dictionary %r' % data)
switch_state = data['dps']['1']
print('switch_state %r' % switch_state)

data = d.status()
print('Dictionary %r' % data)
switch_state = data['dps']['1']
print('switch_state %r' % switch_state)

data = d.status()
print('Dictionary %r' % data)
switch_state = data['dps']['1']
print('switch_state %r' % switch_state)

data = d.status()
print('Dictionary %r' % data)
switch_state = data['dps']['1']
print('switch_state %r' % switch_state)

data = d.status()
print('Dictionary %r' % data)
switch_state = data['dps']['1']
print('switch_state %r' % switch_state)

I can't get it to fail consistently BUT I'm seeing something different. invalid json (so no severed connection error). I wonder if this is firmware related? If so, we need to deal with it BUT I want to understand any fix we use :-)

  File "demo_status.py", line 38, in <module>
    data = d.status()
  File "C:\Users\clach04\py\python-tuya_clach04\pytuya\__init__.py", line 234, in status
    result = json.loads(result)
  File "C:\ProgramData\Anaconda2\lib\json\__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "C:\ProgramData\Anaconda2\lib\json\decoder.py", line 367, in decode
    raise ValueError(errmsg("Extra data", s, end, len(s)))

I'm not going to get chance to work on this again today. I need to dump the payload I'm getting.
Continued in issue #6

@nijave
Copy link
Contributor

nijave commented Jan 4, 2018

This one isn't as important since there's a workaround--just annoying. I suspect it may be quite difficult to debug as well. It's possible it depends on the particular plug + firmware.

Someone else was having mostly success and occasional failures: home-assistant/core#11000 (comment)

@clach04
Copy link
Owner Author

clach04 commented Jan 4, 2018

Whilst experimenting I also saw:

Traceback (most recent call last):
  File "demo_status.py", line 38, in <module>
    data = d.status()
  File "C:\Users\clach04\py\python-tuya_crypt\pytuya\__init__.py", line 228, in status
    data = s.recv(1024)
socket.error: [Errno 10054] An existing connection was forcibly closed by the remote host

This is under python 2.7. Suspect this is the same thing as original report. NOTE I've not seen this under Py3 yet on my machine, super odd.

@clach04
Copy link
Owner Author

clach04 commented Jan 4, 2018

Opened issue #6 for the issue I'm seeing/

@clach04
Copy link
Owner Author

clach04 commented Jan 13, 2018

Idea to reproduce error:

ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host

open socket and send garbage?

@Exilit
Copy link
Collaborator

Exilit commented Jan 13, 2018

I observed the same error when I tried to connect while the eFamilyCloud was opened. Might that be related?

@clach04
Copy link
Owner Author

clach04 commented Jan 25, 2018

Linking Issue #11, exception handling for both will be the same

@clach04
Copy link
Owner Author

clach04 commented Jan 27, 2018

On what I think is an unstable wifi network (been experimenting, and Alexa can't always consistently turn off a device that was fine on home network, sometimes fails multiple times in a row and I have to wait) seeing errors on connect:

Windows Python 2.7:

  File ".....pytuya\__init__.py", line 167, in _send_receive
    s.connect((self.address, self.port))
  File "C:\ProgramData\Anaconda2\Lib\socket.py", line 228, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond

3.6.1

  File "....\pytuya\__init__.py", line 167, in _send_receive
    s.connect((self.address, self.port))
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond

@dadler
Copy link

dadler commented Feb 19, 2018

I believe the devices can connect to only one TCP client at a time. I see "Connection reset by peer" after controlling the device with the Smart Life app. A minute or two later python-tuya starts working again.

@Darkyputz
Copy link

Same experience here...
But i isolated my plug in my network so that it does not talk to the chineasien servers or phones anymore
Only my router is checking for my needs and is talking to it from now on...turning it off and on when my script says so
Great enhancement to my life...thx so much

@ImNightwing
Copy link

ImNightwing commented Apr 16, 2018

I'm seeing this as well. My experience is with hassbian (Home Assistant)

  1. ha will request the status every 30 seconds
  2. each status request tries 3 times
  3. first attempt USUALLY fails with connection reset then second attempt MIGHT work
  4. a failure of all 3 status requests happens about every 1-2 min.

I tried using socket.sendall with same result
Tried using socket.shutdown before closing with same result.
Even tried sleeping 2 seconds before socket.recv just in case: same result.
I'm stumped

EDIT: I tried lowering the requested status interval to 60 seconds and didn't fail for about 8 min but then it start acting up again. So limiting the amount of request to the device seems to help.

@clach04
Copy link
Owner Author

clach04 commented Apr 21, 2018

@ImNightwing reducing number of hits to device is what I ended up doing too. I also have an Amazon Echo hooked up and that talks directly to the device and even then it sometimes does not respond (and its the only thing on the network talking to it). I once had a device get lock up and I had to unplug/replug so the devices themselves whilst good are not 100%

@BillSobel
Copy link

I was having trouble with my devices resetting the connection immediately as well, but I found that (for the MS frame work) turning off data buffering had an immediate improvement in the device sending data back. The MS option is https://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.nodelay(v=vs.110).aspx I suspect there is an equivalent option in your frame work. It looks like if the device does not receive data fairly quickly after a connection it resets the connection.

clach04 added a commit that referenced this issue Apr 22, 2018
Suggestion from BillSobel in
#2 (comment)
@clach04
Copy link
Owner Author

clach04 commented Apr 22, 2018

Thanks @BillSobel, that is odd. I've not seen that under Windows but enabling no delay as there is only one send/recieve makes this a very reasonable/easy change to make. This may help if anyone tries to run under IronPython.

Posted 01c123f

I'm not using Iron Python but I ran a quick test with IronPython 2.7.7 (2.7.7.0) on .NET 4.0.30319.42000 and it runs fine:

# Demoes everything supported so far

import json
import sys
import time

import logging
log = logging.getLogger('pytuya')

log.setLevel(level=logging.INFO)

import pytuya


f = open('device_info.json')
device_info = f.read()
device_info = json.loads(device_info)
f.close()

f = open('devices.json')
devices = f.read()
devices = json.loads(devices)
f.close()

for uuid in devices:
    device_info[uuid]['ip'] = devices[uuid]['ip']


uuid = '?????'  FIXME your id here
d = pytuya.OutletDevice(uuid, device_info[uuid]['ip'], device_info[uuid]['localKey'])


print(d)

data = d.status()
print('Dictionary %r' % data)
switch_state = data['dps']['1']

data = d.set_status(not switch_state)
if data:
    print('set_status() result %r' % data)
    print('set_status() extra %r' % data[20:-8])

data = d.status()
print('Dictionary %r' % data)
switch_state = data['dps']['1']
print('switch_state %r' % switch_state)

data = d.set_timer(3)
if data:
    print('set_status() result %r' % data)
    print('set_status() extra %r' % data[20:-8])

data = d.status()
print('Dictionary %r' % data)
switch_state = data['dps']['1']
print('switch_state %r' % switch_state)

data = d.status()
print('Dictionary %r' % data)
switch_state = data['dps']['1']
print('switch_state %r' % switch_state)

data = d.status()
print('Dictionary %r' % data)
switch_state = data['dps']['1']
print('switch_state %r' % switch_state)

data = d.status()
print('Dictionary %r' % data)
switch_state = data['dps']['1']
print('switch_state %r' % switch_state)

needs config files and device id.

@jdanders
Copy link

jdanders commented Apr 27, 2018

@dadler - I can confirm that was my problem -- it appears the device can only have one open connection. While I had the app on my phone open, I couldn't make a connection with pytuya. Once I closed the app, I was able to connect again.

@guillaumecardon
Copy link

Hello,

I had recently bought HORSKY socket (https://www.amazon.fr/dp/B0774LKY3K/) and it works great !
However, sometimes, i have the TCP issue
I have the 7.0.3 version of the library.

  File "/home/pi/.local/lib/python2.7/site-packages/pytuya/__init__.py", line 260, in status
    data = self._send_receive(payload)
  File "/home/pi/.local/lib/python2.7/site-packages/pytuya/__init__.py", line 172, in _send_receive
    data = s.recv(1024)
socket.error: [Errno 104] Connection reset by peer

Some infos if it can help you :

  • In my script, i manage two socket simultaneous, but the "connection reset by peer" appear randomly on the two sockets
  • Sometimes, after a previous "reset by peer" error, a classic command "d.set_status(False)" cause a "off/on" request. I see my lamp switch off and switch on again in less a second. Same issue with a "d.set_status(True)", i see my lamp switch on and switch off.

I'm a beginner in Python, but if i can help you, it's a pleasure 👍

@mrdarrengriffin
Copy link

Any update on this?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants