rospogrigio / localtuya

local handling for Tuya devices
GNU General Public License v3.0
3k stars 565 forks source link

Problem with setting up LED light and cover #105

Closed darth-aragoth closed 4 years ago

darth-aragoth commented 4 years ago

Hi, I have some problems with my Tuya devices, that work normally in SmartLife.

  1. First one is LED light. I use two or even three kinds of lights, most of them work normally with localtuya (configured via YAML). One kind causes problem, It's all the time offline. It's defined like other devices:
  - host: some_ip
    device_id: some_id
    local_key: some_key
    friendly_name: some_name
    protocol_version: "3.3"
    entities:
      - platform: light
        friendly_name: name
        id: 1

It's DPS (below) is differend from other devices, so I changed ID from 20 to 1, but it didn't change anything. IP, key and ID are correct.

        "dps":{
          "1":false,
          "10":"ffff2e0600fff24d00ff16ff00008affff0000ffac00",
          "2":"white",
          "3":91,
          "4":178,
          "5":"6e3c000021ff6c",
          "6":"bd76000168ffff",
          "7":"ffff500100ff00",
          "8":"ffff80040000ff58ff00ff0000ffd400000000000000",
          "9":"ffff5001ff0000"
        }
  1. Second device - blind curtain switch (https://a.aliexpress.com/_BU4g2c). I even don't know how to configure it :) I have IP, ID and local key, but in DPS I see only this:
        "dps":{
          "1":"3"
        }

In Tuya app, this device has three control buttons (up, down and pause). is it possible to control it via localtuya?

3) All my LED lamps are RGB, what have I to add to YAML configuration to see dimming, color and temperature controls? Now I can only turn them on and off.

Thank you in advance for support.

postlund commented 4 years ago

I'll try to answer:

  1. Looks right to me, can you check the log and see if there are any reports there?
  2. It will be supported once #103 is merged. You can try that if you like to see if it works.
  3. Colored lights are not yet supported, I am however working on that. If your bulbs use HSV encoding for the color, they will be supported when #90 is merged. RGB encoded colors haven't I started working on yet. Brightness is also supported, only for white mode though (in #90 it is supported for color as well). Color temperature is also supported, but the temperature range is hardcoded so it's likely that you can't set the entire color temperature range of your lights. An issue to add custom a custom range is in #91, which I guess I will be doing soon too.
darth-aragoth commented 4 years ago

Thank you for help :)

  1. Indeed, there's an error in log:
Logger: custom_components.localtuya.common
Source: custom_components/localtuya/pytuya/__init__.py:163
Integration: LocalTuya integration (documentation)
First occurred: 0:15:25 (1026 occurrences)
Last logged: 23:10:09

Connect to xxx.xxx.xxx.xxx failed
Traceback (most recent call last):
  File "/config/custom_components/localtuya/common.py", line 151, in _make_connection
    status = await self._interface.status()
  File "/config/custom_components/localtuya/pytuya/__init__.py", line 428, in status
    status = await self.exchange(STATUS)
  File "/config/custom_components/localtuya/pytuya/__init__.py", line 413, in exchange
    payload = self._decode_payload(msg.payload)
  File "/config/custom_components/localtuya/pytuya/__init__.py", line 500, in _decode_payload
    payload = self.cipher.decrypt(payload, False)
  File "/config/custom_components/localtuya/pytuya/__init__.py", line 163, in decrypt
    return self._unpad(decryptor.update(enc) + decryptor.finalize()).decode()
  File "/usr/local/lib/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/base.py", line 159, in finalize
    data = self._ctx.finalize()
  File "/usr/local/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/ciphers.py", line 178, in finalize
    raise ValueError(
ValueError: The length of the provided data is not a multiple of the block length.
  1. Thank you. it works :) but something's weird with positioning, or I don't know, how to use it. I set positioning to fake and span time to 21s. After opening device, position slider is always at 50%. When I move e.g. to 40, curtain goes down for some time, but after that slider returns to 50. When I again move to 40, curtain goes down one more time and again returns to 50. When I move full-open from 50 to 75, curtain remains open, looks like values above 50 causes curtain to go up. So I can't see current position and can't set desired position.

  2. Sounds great :)

postlund commented 4 years ago
  1. I'm not sure which version of localtuya you are using, but this should be fixed by #92, which happens to be merged to master. So maybe you can try master and see if it works?
  2. I think "fake" will always set to 50%, but I will have this part over to @rospogrigio.
  3. Hope so!
darth-aragoth commented 4 years ago
  1. Updated to latest master, lights are still offline, but there are new errors:
Logger: custom_components.localtuya.common
Source: custom_components/localtuya/pytuya/__init__.py:406
Integration: LocalTuya integration (documentation, issues)
First occurred: 9:45:14 (1 occurrences)
Last logged: 9:45:14

Connect to xxxxxxxx failed
Traceback (most recent call last):
  File "/config/custom_components/localtuya/common.py", line 151, in _make_connection
    status = await self._interface.status()
  File "/config/custom_components/localtuya/pytuya/__init__.py", line 428, in status
    status = await self.exchange(STATUS)
  File "/config/custom_components/localtuya/pytuya/__init__.py", line 406, in exchange
    self.transport.write(payload)
AttributeError: 'NoneType' object has no attribute 'write'
Logger: custom_components.localtuya.common
Source: custom_components/localtuya/pytuya/__init__.py:429
Integration: LocalTuya integration (documentation, issues)
First occurred: 9:39:46 (2 occurrences)
Last logged: 9:46:32

Connect to xxxxxxxx failed
Traceback (most recent call last):
  File "/config/custom_components/localtuya/common.py", line 151, in _make_connection
    status = await self._interface.status()
  File "/config/custom_components/localtuya/pytuya/__init__.py", line 429, in status
    if "dps" in status:
TypeError: argument of type 'NoneType' is not iterable
Logger: custom_components.localtuya.common
Source: custom_components/localtuya/pytuya/__init__.py:163
Integration: LocalTuya integration (documentation, issues)
First occurred: 9:38:46 (52 occurrences)
Last logged: 10:05:52

Connect to xxxxxxxx failed
Traceback (most recent call last):
  File "/config/custom_components/localtuya/common.py", line 151, in _make_connection
    status = await self._interface.status()
  File "/config/custom_components/localtuya/pytuya/__init__.py", line 428, in status
    status = await self.exchange(STATUS)
  File "/config/custom_components/localtuya/pytuya/__init__.py", line 413, in exchange
    payload = self._decode_payload(msg.payload)
  File "/config/custom_components/localtuya/pytuya/__init__.py", line 500, in _decode_payload
    payload = self.cipher.decrypt(payload, False)
  File "/config/custom_components/localtuya/pytuya/__init__.py", line 163, in decrypt
    return self._unpad(decryptor.update(enc) + decryptor.finalize()).decode()
  File "/usr/local/lib/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/base.py", line 159, in finalize
    data = self._ctx.finalize()
  File "/usr/local/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/ciphers.py", line 178, in finalize
    raise ValueError(
ValueError: The length of the provided data is not a multiple of the block length.
  1. Ok so how to use it? How to set curtains to e.t. 75%, 25% etc? Now when I move to 75%, curtain always wants to go up, no matter if it's open or closed.
rospogrigio commented 4 years ago
  1. Ok so how to use it? How to set curtains to e.t. 75%, 25% etc? Now when I move to 75%, curtain always wants to go up, no matter if it's open or closed.

Well, it's a kind of a hack actually. The idea behind it is to allow a partial opening or closing of a desired amount, regardless of the current position, which shall be known a priori by the user. It just doubles the posDiff and sends it as a positioning command. To better explain, the cover believes it is always at 50, and you can give positioning commands like 100 (fully open) or 0 (fully close). Setting 75 would open half way, 25 would close it half way (the 25 difference from 50 is doubled). Obviously this movement is effective only if the user is aware of the current position. I just added it because if I wanted, let's say, to open it just a 10% more than it is now, I just needed to set 55, instead of issuing an open+stop series of commands.

I am planning to improve this behavior since from 3.0.0 we have push updates also for manual operation of the device, so we can actually have quite an accurate knowledge of the current position. The only problem that has to be handled in some way is the fact that at the startup we don't know the current position so probably this "50%" behavior will need to stay, but the slider might change accordingly to the position. Hope the above explains it better, bye

postlund commented 4 years ago

Do you use the regular tuya integration or the smart life app?

darth-aragoth commented 4 years ago
  1. Ok so how to use it? How to set curtains to e.t. 75%, 25% etc? Now when I move to 75%, curtain always wants to go up, no matter if it's open or closed.

Well, it's a kind of a hack actually. The idea behind it is to allow a partial opening or closing of a desired amount, regardless of the current position, which shall be known a priori by the user. It just doubles the posDiff and sends it as a positioning command. To better explain, the cover believes it is always at 50, and you can give positioning commands like 100 (fully open) or 0 (fully close). Setting 75 would open half way, 25 would close it half way (the 25 difference from 50 is doubled). Obviously this movement is effective only if the user is aware of the current position. I just added it because if I wanted, let's say, to open it just a 10% more than it is now, I just needed to set 55, instead of issuing an open+stop series of commands.

I am planning to improve this behavior since from 3.0.0 we have push updates also for manual operation of the device, so we can actually have quite an accurate knowledge of the current position. The only problem that has to be handled in some way is the fact that at the startup we don't know the current position so probably this "50%" behavior will need to stay, but the slider might change accordingly to the position. Hope the above explains it better, bye

Thank you, I understand. Could you please consider adding another 'fake' time-based positioning mode with 'real' curtain position? I realize that HA doesn't know initial position, but assuming that curtain is open at start, it could be much easier to set desired position.

darth-aragoth commented 4 years ago

Do you use the regular tuya integration or the smart life app?

Smart Life app.

rospogrigio commented 4 years ago

Thank you, I understand. Could you please consider adding another 'fake' time-based positioning mode with 'real' curtain position? I realize that HA doesn't know initial position, but assuming that curtain is open at start, it could be much easier to set desired position.

I don't get what you mean, I think it is exactly what I wrote in my last sentence. And curtain being open at startup is a weak assumption (I reboot automatically my system each day at 6.00 am, so my covers are all closed at startup) so I'd not make this general. Another idea could be to allow to set it as an option and also provide a service that allows to reset the current position. Let me work on it.

postlund commented 4 years ago

Do you use the regular tuya integration or the smart life app?

Smart Life app.

You will likely get this error when using the app because most devices only support one connection at the time. It will be quieter in the log when #107 is merged, but the connection will still be lost. Try quitting the app and see if it works better.

darth-aragoth commented 4 years ago

Do you use the regular tuya integration or the smart life app?

Smart Life app.

You will likely get this error when using the app because most devices only support one connection at the time. It will be quieter in the log when #107 is merged, but the connection will still be lost. Try quitting the app and see if it works better.

Actually app is closed almost all the time, and this issue occurs only with one type of lights. But I checked that, I disabled Internet gateway, rebooted HA and lights (disconnected from power for a while), app was closed, but lights are still offline and the same errors.

postlund commented 4 years ago

Do you use the regular tuya integration or the smart life app?

Smart Life app.

You will likely get this error when using the app because most devices only support one connection at the time. It will be quieter in the log when #107 is merged, but the connection will still be lost. Try quitting the app and see if it works better.

Actually app is closed almost all the time, and this issue occurs only with one type of lights. But I checked that, I disabled Internet gateway, rebooted HA and lights (disconnected from power for a while), app was closed, but lights are still offline and the same errors.

Then we should troubleshoot further. Please enable logging and attach logs here:

https://github.com/rospogrigio/localtuya#debugging

darth-aragoth commented 4 years ago

OK i enabled logging, Can I send you zipped log via e-mail?

postlund commented 4 years ago

Sure, that's ok!

darth-aragoth commented 4 years ago

Log sent :) Thanks.

postlund commented 4 years ago

So, I've taken a quick look in the log and I found this which is quite interesting:

2020-10-21 16:33:10 DEBUG (MainThread) [custom_components.localtuya.pytuya] Dispatching message TuyaMessage(seqno=1, cmd=10, retcode=1, payload=b'data format error', crc=1908367780)

The payload is data format error, which isn't good. Found it mentioned in this issue https://github.com/AMoo-Miki/homebridge-tuya-lan/issues/83 as well, not sure if we can conclude it to be a bug in tuya firmware or not. But something doesn't work when fetching the initial state from the device, which is likely also why you get a few warnings about "unknown DPS index". Would possibly be interesting to try fetching the state twice and see if the second one succeeds.

darth-aragoth commented 4 years ago

Actually it could be a bug. I hope you'll find workaround. I don't know the details of communication with Tuya devices, maybe localtuya could ignore initial state and try to force switching the device on or off? I don't know anything about it :) so maybe it's pointless... SmartLife app shomehow communicates with this bulbs. Anyway, I'd be happy to check any possible solution.

postlund commented 4 years ago

I created #112, can your try that and see if it makes any difference?

darth-aragoth commented 4 years ago

Lights are still offline, I sent new log via e-mail.

postlund commented 4 years ago

Ok, so, I found this now:

https://github.com/codetheweb/tuyapi/issues/338

If I understand correctly, some devices reply like this (probably firmware bug) and there doesn't seem to be any good way around that. What I did in #112 won't work. One thing that supposedly works is to send "set" command to change the value of a datapoint, but set the value to null/none. This will trigger the device to return the value of that datapoint. If a datapoint that doesn't exist is specified, there's no response though. So that's a pickle. But I'm gonna make a try to work around this, just need some time.

darth-aragoth commented 4 years ago

I just found another error in log:

Logger: homeassistant.util.logging
Source: util/logging.py:108
First occurred: 22:40:23 (2 occurrences)
Last logged: 22:40:23

Exception in _update_handler when dispatching 'localtuya_devid_37': ({'4': 606, '5': 1472},) Traceback (most recent call last): File "/config/custom_components/localtuya/common.py", line 226, in _update_handler self.status_updated() File "/config/custom_components/localtuya/sensor.py", line 67, in status_updated state = round(state * scale_factor, DEFAULT_PRECISION) TypeError: unsupported operand type(s) for *: 'NoneType' and 'float'
Exception in _update_handler when dispatching 'localtuya_devid_34': ({'4': 314, '6': 2403},) Traceback (most recent call last): File "/config/custom_components/localtuya/common.py", line 226, in _update_handler self.status_updated() File "/config/custom_components/localtuya/sensor.py", line 67, in status_updated state = round(state * scale_factor, DEFAULT_PRECISION) TypeError: unsupported operand type(s) for *: 'NoneType' and 'float'

I didn't see it before, what is interesting - devices mentioned in log seem to be working ok. I just rebooted HA and error happened again, but for other devices.

postlund commented 4 years ago

Looks like the sensor state is None so the scaling fails. Can be considered a bug.

On another note... Can you check out #114, open custom_components/pytuya/__init__.py, scroll down to the bottom and replace the the parameters at the bottom (IP, device id and local key - they currently have some of my values). Then run the script:

python custom_components/localtuya/pytuya/__init__.py

It will take time, about 2,5min or so. Do you get a list of datapoints at the end?

darth-aragoth commented 4 years ago

I checked script with two devices (out1 with non-working light, out2 with working switch), logs in attachment. logs.zip

postlund commented 4 years ago

That did not work very well. Will have to get back to the drawing table. I assume you did not have the app open or anything when doing this?

darth-aragoth commented 4 years ago

Yes, app was closed.

postlund commented 4 years ago

One question: is it correct assumed that switch 2 was added to localtuya at the time and thus already in use? Devices normally act like that (connection reset) when being used by someone else.

postlund commented 4 years ago

And maybe I should increase the timeouts a bit just to be safe. It will take longer but hopefully work better.

postlund commented 4 years ago

Ok, increased the timeouts, please try again (also remove the working device from localtuya before testing).

darth-aragoth commented 4 years ago

OK now I have dps in output (for switch, for light still nothing). logs.zip

postlund commented 4 years ago

Hmm, interesting. When I compare the switch and light, they both seem to close the connection when trying to set a non-existing DP. So it would suggest that the light might use very exotic datapoints or not support this method at all. Let's do another attempt and brute-force all 255 datapoints. It's gonna take a long time, but would be interesting to see the result.

postlund commented 4 years ago

Pushed an update now, please try it with the light.

darth-aragoth commented 4 years ago

Log in attachment. logs.zip

postlund commented 4 years ago

Seems like it doesn't respond with anything useful at all. I don't quite understand it. Would it be possible to set up so I can get ssh access to the bulb somehow, so I can tinkle with it myself for an evening? It's a bit tedious to test like we are doing right now.

postlund commented 4 years ago

Maybe something like this with my public key:

https://blog.tinned-software.net/restrict-ssh-access-to-port-forwarding-to-one-specific-port/

darth-aragoth commented 4 years ago

If you have static public IP, I can redirect specific port (6668/TCP?) for some time, that should grant you access to my light directly via my public IP. If it will be ok, please e-mail me your IP.

postlund commented 4 years ago

Sure, that will work fine too. I assume you lock it to my IP? It's static in the sense that it hasn't changed in six years m, so we should be fine. Don't see your email on GitHub? You can send an email to me and I'll respond to it.

darth-aragoth commented 4 years ago

Please check you email. Yes, I'll make a rule only for your IP.

postlund commented 4 years ago

Good news, the connection worked and after playing around a bit I figured out that your device uses version 3.1 of the tuya protocol. Log for obtaining status:

2020-10-29 22:09:33 DEBUG: Using selector: EpollSelector
connected
2020-10-29 22:09:33 DEBUG: [08778066cc50e358067c] Started heartbeat loop
2020-10-29 22:09:33 DEBUG: [08778066cc50e358067c] Sending command status (device type: type_0a)
2020-10-29 22:09:33 DEBUG: [08778066cc50e358067c] Send payload: b'{"gwId":"08778066cc50e358067c","devId":"08778066cc50e358067c"}'
2020-10-29 22:09:33 DEBUG: [08778066cc50e358067c] Waiting for sequence number 0
2020-10-29 22:09:33 DEBUG: Dispatching message TuyaMessage(seqno=0, cmd=10, retcode=0, payload=b'{"devId":"08778066cc50e358067c","dps":{"1":true,"2":"white","3":126,"4":37,"5":"6e3c000021ff6c","6":"bd76000168ffff","7":"ffff500100ff00","8":"ffff80040000ff58ff00ff0000ffd400000000000000","9":"ffff5001ff0000","10":"ffff2e0600fff24d00ff16ff00008affff0000ffac00"}}', crc=1285395449)
2020-10-29 22:09:33 DEBUG: [08778066cc50e358067c] Dispatching sequence number 0
2020-10-29 22:09:33 DEBUG: [08778066cc50e358067c] Decrypted payload: {"devId":"08778066cc50e358067c","dps":{"1":true,"2":"white","3":126,"4":37,"5":"6e3c000021ff6c","6":"bd76000168ffff","7":"ffff500100ff00","8":"ffff80040000ff58ff00ff0000ffd400000000000000","9":"ffff5001ff0000","10":"ffff2e0600fff24d00ff16ff00008affff0000ffac00"}}
{'1': True, '2': 'white', '3': 126, '4': 37, '5': '6e3c000021ff6c', '6': 'bd76000168ffff', '7': 'ffff500100ff00', '8': 'ffff80040000ff58ff00ff0000ffd400000000000000', '9': 'ffff5001ff0000', '10': 'ffff2e0600fff24d00ff16ff00008affff0000ffac00'}
2020-10-29 22:09:33 DEBUG: [08778066cc50e358067c] Closing connection
2020-10-29 22:09:33 DEBUG: [08778066cc50e358067c] Connection lost: None
2020-10-29 22:09:33 DEBUG: [08778066cc50e358067c] Closing connection

So try changing to version 3.1 and see if it works better. Are you manually entering details or did discovery pick the wrong version? If the latter, can you have a look at the debug logs? You can grep for localtuya.discovery and look for your device. Should be some json output.

darth-aragoth commented 4 years ago

Thank you, it works !!! That's really good news :) I configured all my devices in yaml, copy-pasted config from other lights. Great, now all my lights are functional! Thank you once again.

postlund commented 4 years ago

Great, config error we can conclude. It's a good thing to keep track of 👍 I will close this now.