Open clach04 opened 6 years ago
@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.
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
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
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
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: https://github.com/home-assistant/home-assistant/pull/11000#issuecomment-354833205
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.
Opened issue #6 for the issue I'm seeing/
Idea to reproduce error:
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host
open socket and send garbage?
I observed the same error when I tried to connect while the eFamilyCloud was opened. Might that be related?
Linking Issue #11, exception handling for both will be the same
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
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.
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
I'm seeing this as well. My experience is with hassbian (Home Assistant)
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.
@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%
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.
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 https://github.com/clach04/python-tuya/commit/01c123f899e0ded10554fb0a6fc5e64d20176d30
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.
@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.
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 :
I'm a beginner in Python, but if i can help you, it's a pleasure 👍
Any update on this?
Need more info., see issue #1
Original reported issue by @nijave:
Under Linux Python 3
@clach04 saw:
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.