mileperhour / localtuya-homeassistant

local handling for Tuya devices
GNU General Public License v3.0
147 stars 667 forks source link

switch turns off at random times after being added to HA #8

Open aleqx opened 4 years ago

aleqx commented 4 years ago

First, thanks for this custom component. I got it working (HA 0.104.3 running on a RPi 3B) and it appeared to work fine while configuring it in HA. I have a bunch of Tuya smart plugs. I'm seeing a consistent problem in that a plug that is used (by a dehumidifier, washing machine etc), turns off after a few minutes after it turned on ... but only those which have some non-negligible power draw! I have 4 identical Tuya smartplugs, and although all are turned on, the ones which have 0 W power draw are not turned off when this problem happens. This stumps me.

As you know, tuya devices don't allow polling from multiple sources, so if for example the official Tuya Android app is polling the smart plug, HA cannot poll or control the smartplug and gives an error. Still, it should not ever turn it off without me explicitly telling it to.

It only happens when HA is running with the particular smart plug. If I remove the smart plug from configuration.yaml or if I shut down HA then the smartplug remains on.

Any thoughts? Are you aware of anything in HA or your code that could trigger a "toggle" or "off" command after regaining control of the device (I can't think of any other cause)? Logs didn't show anything like that (edit: even when running with --verbose). The fact that only smartplugs with non-zero power draw are turned off is weird ... it's as if there was some scenario defined with conditionals (there isn't any, and logs don't show anything).

Could be that this is a hardware behavior of the device itself ... and in that case I could get rid of the Tuya mobile app and only control them via HA (installing the HA app on the phone) though I didn't want to lose that safety net in case my RPi croaks ...

Cheers

When the device is controled by the Tuya mobile app, HA reports this error:

2020-02-05 21:15:50 ERROR (MainThread) [homeassistant.helpers.entity] Update for switch.spareplug fails
Traceback (most recent call last):
  File "/home/pi/.homeassistant/custom_components/localtuya/switch.py", line 93, in __get_status
    status = self._device.status()
  File "/home/pi/homeassistant/lib/python3.7/site-packages/pytuya/__init__.py", line 281, in status
    data = self._send_receive(payload)
  File "/home/pi/homeassistant/lib/python3.7/site-packages/pytuya/__init__.py", line 179, in _send_receive
    data = s.recv(1024)
ConnectionResetError: [Errno 104] Connection reset by peer

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/pi/homeassistant/lib/python3.7/site-packages/homeassistant/helpers/entity.py", line 279, in async_update_ha_state
    await self.async_device_update()
  File "/home/pi/homeassistant/lib/python3.7/site-packages/homeassistant/helpers/entity.py", line 461, in async_device_update
    await self.hass.async_add_executor_job(self.update)
  File "/usr/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/pi/.homeassistant/custom_components/localtuya/switch.py", line 165, in update
    status = self._device.status()
  File "/home/pi/.homeassistant/custom_components/localtuya/switch.py", line 111, in status
    self._cached_status = self.__get_status()
  File "/home/pi/.homeassistant/custom_components/localtuya/switch.py", line 97, in __get_status
    raise ConnectionError("Failed to update status.")
ConnectionError: Failed to update status.
aleqx commented 4 years ago

Ok, it seems it happens right after it regains control of the device (which can be taken away by the Tuya mobile app, or by the Tuya API server which can also control and poll the device) ... almost always! I can see the smartplug going off quickly after the above error shows up in the log and after I quit the mobile app, but once it happened when there was no app running but got a 2020-02-05 22:13:09 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection.1745793328] [Errno 104] Connection reset by peer int he HA log ... so it kind of hints that when it regains control of the device then it gets shut off ... and again, only if it has some non-negligible power draw at the time (which really stumps me to be honest).

Could be that this is a hardware behavior of the device itself

I can answer that: No. I tested by using the tuyapi code directly in nodejs (the pytuya library you are using is based on the tuyapi code) by connecting to the device and polling/controlling it and preventing the mobile app from doing that, and also tried vice versa, i.e. had the mobile app start first then polled the device continuously using tuyapi until I closed the app: tuyapi then connected and the smartplug did not turn off.

Hence there is something somewhere in the code chain between your component and HA core which is causing an off or toggle to be sent to the device once it regains control.

nijave commented 4 years ago

I see tuyapi looks to be caching the tcp connection for up to 10 seconds whereas this is creating a new one for each command. Otherwise, I didn't have much luck figuring it out. Could also be something really low-level the socket options node uses are different and something about them the tuya device doesn't like. It looks like there's also some newer protocol versions that have mandatory encryption on all messages instead of just some of them (3.3 instead of 3.1) so maybe that'd make a difference?

nijave commented 4 years ago

This post has a packet capture https://github.com/clach04/python-tuya/issues/2#issuecomment-355158212

Based on that, it looks like the connection gets reset after the TCP connection has been established and the code sends a request to the device so perhaps there's something about sending this first request to the device that it doesn't like

aleqx commented 4 years ago

Thanks for looking at this. That tcp RST is evil. That said, I still can't explain the turn-off. The RST would be sent by the device regardless of how I poll it so I expect I would have seen some turning off when fiddling with tuyapi from nodejs as well if the RST was the culprit. But I agree with you that something must be different that the device doesn't like.

Are you aware of any code that can fetch attributes (e.g. current, power, energy values) from the Tuya cloud API rather than polling it directly? That's what the mobile app is doing.

I know there is a HA component for the Tuya cloud API (the official HA component) but only knows of on/off/toggle and not of attributes - I need the energy monitoring bits to automate things. I would be willing to extend this official HA component if I find some reverse engineered code that can fetch attributes (i have little time to do that bit as well).

p.s. For now I ordered some smartplugs with energy monitoring that work with SmartThings rather than Tuya, to test if they are easier to work with. The TP-link HS110 is expensive and bulky, but has such an easy and reliable local API. If you're aware of other smartplugs with energy monitoring that are affordable and have a reliable API then I'm interested.

aleqx commented 4 years ago

I know there is a HA component for the Tuya cloud API (the official HA component) but only knows of on/off/toggle and not of attributes - I need the energy monitoring bits to automate things. I would be willing to extend this official HA component if I find some reverse engineered code that can fetch attributes (i have little time to do that bit as well).

Hmm, I just had a look to see what code HA uses for that, and it's the tuyaha package from here: https://github.com/PaulAnnekov/tuyaha/ and just glancing at the code for the wrapper and switch, I think it should be possible to extend it to query further dps parameters, unless I'm mistaken, see:

https://github.com/PaulAnnekov/tuyaha/blob/master/tuyaha/devices/switch.py

https://github.com/PaulAnnekov/tuyaha/blob/master/tuyaha/tuyaapi.py

If yes, then this should be more reliable as it won't collide with the app (or API) since it won't connect to the device. The disadvantage, of course, is that you need an internet connection even when at home.

ghost commented 4 years ago

I had a lot of errors with localtuya too. I wrote a tuya to mqtt thingy, here https://github.com/TradeFace/tuyamqtt/ and did a extensive rewrite of python-tuya, here https://github.com/TradeFace/tuya/ At this point it doesn't support the older devices, but anything v3.3 should work fine. hth

RXM307 commented 4 years ago

@TradeFace That's very cool, I might give it a try.

currently I'm using a mix of localtuya and cloud tuya (while I migrate then to localtuya) interesting some RGB globes I have disappear from tuya cloud when switching from White to RGB.

MQTT always scared me because I don't understand it but your doco looks great.

On Fri, 7 Feb 2020 at 17:52, TradeFace notifications@github.com wrote:

I had a lot of errors with localtuya too. I wrote a tuya to mqtt thingy, here https://github.com/TradeFace/tuyamqtt/ and a extensive rewrite of python-tuya, here https://github.com/TradeFace/tuya/ At this point it doesn't support the older devices, but anything v3.3 should work fine. hth

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/mileperhour/localtuya-homeassistant/issues/8?email_source=notifications&email_token=AALJQCYZLMAE7BJ2GL5WRILRBUHLLA5CNFSM4KQSN3F2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOELCBCXA#issuecomment-583274844, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALJQC3PPIK3PGMAY7F6K4TRBUHLLANCNFSM4KQSN3FQ .

aleqx commented 4 years ago

@TradeFace That looks awesome and very promising (after so much hassle and wasted time any alternative looks super promising). Thanks for this work!

@RXM307 Tuya devices don't allow more than one tcp connection, so whichever connects to it first will "own" the connection, and all other connection attempts will fail. There are many aspects about Tuya that are just badly designed ...

aleqx commented 4 years ago

@TradeFace I'm new to MQTT and I'm trying to make your code to see my Tuya smartplug before integrating into HA. I'm running an RPi 3B. I installed mosquitto and it's listening on port 1823 (no auth). I changed your config file to connect to 127.0.0.1 port 1823, then pip installed bitstring and paho_mqtt, then started your stuff with python3 -u main.py which said MQTT Connection state: Connection successful for tuya. I also installed mosquitto-clients and wanted to first check that I can see/control the smartplug from the cli, so I tried mosquitto_sub -v -t tuya/3.3/55327730.../4e7798d2.../192.168.1.43/1/attributes and tried switching the smartplug on and off which should generate some messages, but I get nothing

Where am I going wrong? What's a quick way to test if the device support version the tuya 3.3 protocol? I tried my tuyapi code and set "version":3.3 for the options object and i get a data format error int he data listener, but I'm not sure that actually means 3.3. is unsupported

ghost commented 4 years ago

@aleqx, your question is a bit of topic in this repo. But I'll try to answer. TuyaMQTT "learns" from the topics you request which device it should talk to. It listens on (is subscribed to) the topic root tuya/ by default. Mosquitto is "just" a message broker. It doesn't call any other service, it accepts and replies to messages. When you subscribe to a topic the subscriber just waits for a new message to come available. Thus when you publish on the tuya/ topic to mosquitto, TuyaMQTT will pickup the message and process the request and send the reply. (The first request might be lost for initialization)

So to do your test. Setup one terminal with mosquitto_sub active on the topic and in another terminal send a mosquitto_pub on the same topic.

aleqx commented 4 years ago

@TradeFace I posted here before I saw your reply above: https://github.com/TradeFace/tuyamqtt/issues/1 ... I figured out I had to publish first but your server says Data must be aligned to block boundary in ECB mode status for tuya/3.3/55327730840d8e... let's continue over in your repo issues