jasonacox / tinytuya

Python API for Tuya WiFi smart devices using a direct local area network (LAN) connection or the cloud (TuyaCloud API).
MIT License
999 stars 177 forks source link

Status() only returning one dps #190

Closed AntoineGS closed 1 year ago

AntoineGS commented 2 years ago

A bit of context, I am attempting to integrate with a Yakry C2 (Petfeeder with Camera) to get feeding schedules done locally and hence removing a point of failure (connection to Tuya servers, though the argument could be made that whatever machine runs the new code becomes the new point of failure... lol). So while I managed to find the dps to trigger the feeder (201) I found myself hoping to expand the integration a bit.

Here's where I run into issues, there are 6 dps that return data when requested individually, however when requesting all 6 at the same time I only the first one is returned. The detect_available_dps also ends up returning one dps, and I have a feeling the issues are related.

Here is my code:

import tinytuya

d = tinytuya.Device('someid', 'someip', somekey')
d.set_version(3.3)
d.dev_type = "device22"  # I noticed that the device gets auto-upgraded to this
d.add_dps_to_request(101)
d.add_dps_to_request(103)
d.add_dps_to_request(104)
d.add_dps_to_request(106)
d.add_dps_to_request(108)
d.add_dps_to_request(134)
data = d.status()
print('Device status: %r' % data)

Here is the output: Device status: {'dps': {'101': False}, 't': 1664918965} If I remove the dps 101 then the output becomes: Device status: {'dps': {'103': False}, 't': 1664919001}, etc.

I traced the received payload and it does seem to come from the device itself as it only contains one dps coming out of payload = cipher.decrypt(payload, False).

Has anyone run into a similar problem?

jasonacox commented 2 years ago

Hi @AntoineGS, thanks for opening this issue. What version of TinyTuya are you running? If it is 1.7.0, can you also run a scan to see if this device is actually a 3.3 or 3.2 device?

python3 -m tinytuya version

python3 -m tinytuya scan

I also recommend setting up a monitoring loop to see if the device emits anything differently over time:

import tinytuya

d = tinytuya.Device('someid', 'someip', 'somekey')
d.set_version(3.3)
d.dev_type = "device22" 
d.set_socketPersistent(True)
d.detect_available_dps()

print(" > Send Request for Status < ")
payload = d.generate_payload(tinytuya.DP_QUERY)
d.send(payload)

print(" > Begin Monitor Loop <")
while(True):
    # See if any data is available
    data = d.receive()
    print('Received Payload: %r' % data)

    # Send keyalive heartbeat
    print(" > Send Heartbeat Ping < ")
    payload = d.generate_payload(tinytuya.HEART_BEAT)
    d.send(payload)

    # NOTE If you are not seeing updates, you can force them - uncomment:
    # print(" > Send Request for Status < ")
    # payload = d.generate_payload(tinytuya.DP_QUERY)
    # d.send(payload)

    # NOTE Some smart plugs require an UPDATEDPS command to update power data
    # print(" > Send DPS Update Request < ")
    # payload = d.generate_payload(tinytuya.UPDATEDPS)
    # d.send(payload)    
AntoineGS commented 2 years ago

Thanks for the quick and insightful response! I am running 1.7.0 (cloned the repo recently, using master). Scan does confirm it is a 3.3 device.

The monitoring loop does return more data! I am seeing DPs 101, 103, 104, 106, 108, 134, 202, 207 with it so that's awesome. Even though the payload only includes 101, so maybe received payloads are not triggered by my requests but it's just broadcasting them. image

So it would seem that it does not send back all DPs at once but one per payload, interesting. Do you know if that's common for some Tuya devices? (So that I may have some references of some other integrations that might be more common for when I get stuck again).

I don't have time tonight to play more with this but that's some good progress, thank you!!

jasonacox commented 2 years ago

I still haven't been able to figure out why device22 devices behave differently than the rest of 3.3 devices. They seem to use protocol 3.2 but identify as 3.3 which is the reason for the device22 setting... I feel like they were an "in between" variant. In any case, I only have one of those devices and it does seem to be stingy about responding with more than 1 DP. In my case, it is a plug so I really only care about DP 1 for the switch function, but it did strike me as odd.

In the loop I sent you, it may be interesting to see if you get any different results by sending the UPDATEDPS command.

# NOTE Some smart plugs require an UPDATEDPS command to update power data
print(" > Send DPS Update Request < ")
payload = d.generate_payload(tinytuya.UPDATEDPS)
d.send(payload)   

For your particular device, would you provide a description of what the DPS mean? Others with this device may like to know. @fhempy , @uzlonewolf and I have been discussing how best to represent community discovered DPS for various Tuya devices (e.g. more or expanded https://github.com/jasonacox/tinytuya#tuya-data-points---dps-table with mapping to product_id).

AntoineGS commented 1 year ago

Thanks for all the info! I am closing the Issue since I am finding very little time to work on this so there's no point polluting the Issues' list.

uzlonewolf commented 1 year ago

I know I'm a bit late to this party, but just wanted to chime in about the device22 thing. I don't think the length of the id string actually means anything; of the 25 different types of devices I have, 17 have a 22-digit-long device id, and of those all but 1 act like normal v3.3 devices. I suspect the quirks come from which platform/chip library the device was built around. I know the doorbell cameras use a rather powerful SoC and run Linux, and it wouldn't surprise me if this pet feeder does too.

jasonacox commented 1 year ago

That's a great point @uzlonewolf. I believe you are right and in hindsight, I wish we had picked something besides "device22" to identify these oddities. 😞