Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't connect to a device via tinytuya while it is available via tuya smart #567

Open
rdmitry0911 opened this issue Dec 3, 2024 · 11 comments
Labels
tuya_device Support for specific Tuya Devices

Comments

@rdmitry0911
Copy link

I have a smart energy monitor device ("product_name": "三相重合闸") that worked fairy well in the past, but recently I noticed, that I can't connect to it via tinytuya. In the past it worked fine, but now I'm getting this when I'm trying to get device status

DEBUG:TinyTuya [1.15.1]

DEBUG:Python 3.13.0 (main, Oct 25 2024, 16:23:57) [Clang 14.0.0 (clang-1400.0.29.202)] on darwin
DEBUG:Using pyca/cryptography 44.0.0 for crypto, GCM is supported
DEBUG:status() entry (dev_type is default)
DEBUG:final payload_dict for 'bfa5775d7c4ed89aabxqml' ('v3.4'/'default'): {1: {'command': {'gwId': '', 'devId': '', 'uid': '', 't': ''}}, 7: {'command': {'protocol': 5, 't': 'int', 'data': {}}, 'command_override': 13}, 8: {'command': {'gwId': '', 'devId': ''}}, 9: {'command': {'gwId': '', 'devId': ''}}, 10: {'command': {}, 'command_override': 16}, 13: {'command': {'protocol': 5, 't': 'int', 'data': {}}}, 16: {'command': {}}, 18: {'command': {'dpId': [18, 19, 20]}}, 64: {'command': {'reqType': '', 'data': {}}}}
DEBUG:building command 10 payload=b'{}'
DEBUG:sending payload quick
DEBUG:final payload: b'0123456789abcdef'
DEBUG:payload encrypted=b'000055aa000000010000000300000044343e997b3510ddd1bcbe891319668c1b9490ddc4c873e2790edf2dd3c682fee1bc9378e554f900b271b3bd05eb37871d6f36348976239ef9f6d264c669d5abee0000aa55'
DEBUG:_recv_all(): no data? b''
DEBUG:_recv_all(): no data? b''
DEBUG:received null payload (None), fetch new one - 1 retries remaining
DEBUG:_recv_all(): no data? b''
DEBUG:_recv_all(): no data? b''
DEBUG:received null payload (None) but out of recv retries, giving up
DEBUG:session key negotiation failed on step 1
DEBUG:ERROR Check device key or version - 914 - payload: null
DEBUG:status() received data={'Error': 'Check device key or version', 'Err': '914', 'Payload': None}

Meanwhile via cloud api I can connect to it without any problem. I checked and the device key remains the same. Device rebooting doesn't help.

@jasonacox
Copy link
Owner

Did the local key change? Try running wizard to get the local key.

@jasonacox jasonacox added the tuya_device Support for specific Tuya Devices label Dec 5, 2024
@CheAhMeD
Copy link
Contributor

CheAhMeD commented Dec 5, 2024

I recently had a similar issue with one of my Colorful-X7 (Some sort of SP107E like led controller) the only difference was I had a Network Error: Unable to Connect (901). Silly me, it turned out I swapped the IP and local key vars (I had a python snippet that looks for all the devices with the model Colorful-X7 in my local network and returns a list of tinytuya.Device()) so I couldn't connect to the devices anymore...
I hope your issue is as simple as a typo (maybe you swapped the local key with the wrong var?)

@grosjo
Copy link

grosjo commented Dec 6, 2024

I have the same issue, key has not changed, Ip has not changed, connection is available locally (ping works) and available from the cloud / app, but suddently getting "Error": "Check device key or version", "Err": "914"

@jasonacox
Copy link
Owner

Tuya devices are by default cloud devices. The local API is a afterthought and appears to have been added to allow the SmartLife app to initial configure and control them locally if the cloud is unavailable. Unfortunately, the stability of the local API varies greatly from device to device. I wish we knew why they get in a bad state.

Some suggestions:

  • Power cycle the device
  • Power cycle workstation or run tinytuya from another host
  • Restart network router or dhcp lease to get a new IP assigned to device in case it is an arp issue
  • Run scanner in debug mode python -m tinytuya scan -d
  • Run wizard to ensure local key didn't change python -m tinytuya wizard
  • Force a local key change by re-pairing the device with SmartLife and run Wizard to get the new key

@rdmitry0911
Copy link
Author

Tuya devices are by default cloud devices. The local API is a afterthought and appears to have been added to allow the SmartLife app to initial configure and control them locally if the cloud is unavailable. Unfortunately, the stability of the local API varies greatly from device to device. I wish we knew why they get in a bad state.

Some suggestions:

  • Power cycle the device
  • Power cycle workstation or run tinytuya from another host
  • Restart network router or dhcp lease to get a new IP assigned to device in case it is an arp issue
  • Run scanner in debug mode python -m tinytuya scan -d
  • Run wizard to ensure local key didn't change python -m tinytuya wizard
  • Force a local key change by re-pairing the device with SmartLife and run Wizard to get the new key

Here is output of python -m tinytuya scan -d

DEBUG:TinyTuya [1.15.1]

DEBUG:Python 3.13.0 (main, Oct 25 2024, 16:23:57) [Clang 14.0.0 (clang-1400.0.29.202)] on darwin
DEBUG:Using pyca/cryptography 44.0.0 for crypto, GCM is supported

TinyTuya (Tuya device scanner) [1.15.1]

Scanning on UDP ports 6666 and 6667 and 7000 for devices for 18 seconds...

DEBUG:Listening for Tuya devices on UDP ports 6666, 6667 and 7000
DEBUG:Sending discovery broadcast from '172.16.66.196' to '255.255.255.255' on port 7000
DEBUG:Received valid UDP packet: {'from': 'app', 'ip': '172.16.66.196'}
New Broadcast from App at 172.16.66.196 - {'from': 'app', 'ip': '172.16.66.196'}
DEBUG:Received valid UDP packet: {'from': 'app', 'ip': '172.16.66.196'}
DEBUG:Received valid UDP packet: {'ip': '172.16.66.129', 'gwId': 'bfa5775d7c4ed89aabxqml', 'active': 2, 'ablilty': 0, 'encrypt': True, 'productKey': 'o0etlvokdvycltay', 'version': '3.4', 'token': True, 'wf_cfg': True}
Unknown v3.4 Device   Product ID = o0etlvokdvycltay  [Valid Broadcast]:
    Address = 172.16.66.129   Device ID = bfa5775d7c4ed89aabxqml (len:22)  Local Key =   Version = 3.4  Type = default, MAC = 
    No Stats for 172.16.66.129: DEVICE KEY required to poll for status
DEBUG:Received valid UDP packet: {'ip': '172.16.66.236', 'gwId': 'bf6719e9e16685ea81jcz7', 'active': 2, 'ablilty': 0, 'encrypt': True, 'productKey': 'keyjup78v54myhan', 'version': '3.4', 'token': True, 'wf_cfg': True}
Unknown v3.4 Device   Product ID = keyjup78v54myhan  [Valid Broadcast]:
    Address = 172.16.66.236   Device ID = bf6719e9e16685ea81jcz7 (len:22)  Local Key =   Version = 3.4  Type = default, MAC = 
    No Stats for 172.16.66.236: DEVICE KEY required to poll for status
DEBUG:Received valid UDP packet: {'ip': '172.16.66.133', 'gwId': 'bfeedfcafec47da41329cz', 'active': 2, 'ablilty': 0, 'encrypt': True, 'productKey': 'gw173aldekvpzalg', 'version': '3.3'}
Unknown v3.3 Device   Product ID = gw173aldekvpzalg  [Valid Broadcast]:
    Address = 172.16.66.133   Device ID = bfeedfcafec47da41329cz (len:22)  Local Key =   Version = 3.3  Type = default, MAC = 
    No Stats for 172.16.66.133: DEVICE KEY required to poll for status
DEBUG:Received valid UDP packet: {'ip': '172.16.66.129', 'gwId': 'bfa5775d7c4ed89aabxqml', 'active': 2, 'ablilty': 0, 'encrypt': True, 'productKey': 'o0etlvokdvycltay', 'version': '3.4', 'token': True, 'wf_cfg': True}
DEBUG:Sending discovery broadcast from '172.16.66.196' to '255.255.255.255' on port 7000
DEBUG:Received valid UDP packet: {'from': 'app', 'ip': '172.16.66.196'}
DEBUG:Received valid UDP packet: {'from': 'app', 'ip': '172.16.66.196'}
DEBUG:Received valid UDP packet: {'ip': '172.16.66.236', 'gwId': 'bf6719e9e16685ea81jcz7', 'active': 2, 'ablilty': 0, 'encrypt': True, 'productKey': 'keyjup78v54myhan', 'version': '3.4', 'token': True, 'wf_cfg': True}
DEBUG:Received valid UDP packet: {'ip': '172.16.66.133', 'gwId': 'bfeedfcafec47da41329cz', 'active': 2, 'ablilty': 0, 'encrypt': True, 'productKey': 'gw173aldekvpzalg', 'version': '3.3'}
DEBUG:Received valid UDP packet: {'ip': '172.16.66.129', 'gwId': 'bfa5775d7c4ed89aabxqml', 'active': 2, 'ablilty': 0, 'encrypt': True, 'productKey': 'o0etlvokdvycltay', 'version': '3.4', 'token': True, 'wf_cfg': True}
DEBUG:Sending discovery broadcast from '172.16.66.196' to '255.255.255.255' on port 7000
DEBUG:Received valid UDP packet: {'from': 'app', 'ip': '172.16.66.196'}
DEBUG:Received valid UDP packet: {'from': 'app', 'ip': '172.16.66.196'}
DEBUG:Received valid UDP packet: {'ip': '172.16.66.236', 'gwId': 'bf6719e9e16685ea81jcz7', 'active': 2, 'ablilty': 0, 'encrypt': True, 'productKey': 'keyjup78v54myhan', 'version': '3.4', 'token': True, 'wf_cfg': True}
DEBUG:Received valid UDP packet: {'ip': '172.16.66.133', 'gwId': 'bfeedfcafec47da41329cz', 'active': 2, 'ablilty': 0, 'encrypt': True, 'productKey': 'gw173aldekvpzalg', 'version': '3.3'}
DEBUG:Received valid UDP packet: {'ip': '172.16.66.129', 'gwId': 'bfa5775d7c4ed89aabxqml', 'active': 2, 'ablilty': 0, 'encrypt': True, 'productKey': 'o0etlvokdvycltay', 'version': '3.4', 'token': True, 'wf_cfg': True}
Scan completed in 18.0516 seconds                 
                    
Scan Complete!  Found 3 devices.
Broadcasted: 3
Versions: 3.3: 1, 3.4: 2
Unknown Devices: 3

>> Saving device snapshot data to snapshot.json

DEBUG:Scan complete with 3 devices found

Here is output of python -m tinytuya wizard


Scanning local network for Tuya devices...
    3 local devices discovered                     

Polling local devices...
    [Garden bedroom floor     ] Error: No IP found
    [Green House Heat Pump    ] Error: No IP found
    [Main Energy Meter        ] 172.16.66.129      - No Response
    [Master bedroom floor     ] Error: No IP found
    [Pool bathroom floor      ] 172.16.66.133      - [Off] - DPS: {'1': False, '2': 220, '3': 201, '4': 'hot', '5': '0', '8': False, '13': True, '16': 0, '20': -20, '21': 60, '25': '1', '26': False, '31': False, '41': '3', '42': '1', '101': False, '105': 10, '107': 35}
    [Temperature Humidity Sens] Error: No IP found
    [удлинитель 1             ] 172.16.66.236      - [On]  - DPS: {'1': True, '2': True, '3': True, '4': True, '5': True, '9': 0, '10': 0, '11': 0, '12': 0, '13': 0, '38': 'memory'}
    [удлинитель 2             ] Error: No IP found

>> Saving device snapshot data to snapshot.json


>> Saving IP addresses to devices.json
    3 device IP addresses found


Here is part of devices.json related to problematic device 172.16.66.129

    {
        "name": "Main Energy Meter",
        "id": "bfa5775d7c4es89aabxqml",
        "key": "Bd-L$RakbM_0zI*#",
        "mac": "d8:d6:68:cc:67:f4",
        "uuid": "7d3aecd6bd7750c7",
        "sn": "10013637500CB7",
        "category": "dlq",
        "product_name": "Energy meter",
        "product_id": "o0etlvokdvycltay",
        "biz_type": 0,
        "model": "",
        "sub": false,
        "icon": "https://images.tuyaeu.com/smart/icon/bay1668649074167YlMo/57fa28aca902461e652fb85a769e7897.png",
        "mapping": {
            "1": {
                "code": "total_forward_energy",
                "type": "Integer",
                "values": {
                    "unit": "kW\u00b7h",
                    "min": 0,
                    "max": 99999999,
                    "scale": 2,
                    "step": 1
                }
            },
            "6": {
                "code": "phase_a",
                "type": "Raw",
                "values": {}
            },
            "7": {
                "code": "phase_b",
                "type": "Raw",
                "values": {}
            },
            "8": {
                "code": "phase_c",
                "type": "Raw",
                "values": {}
            },
            "9": {
                "code": "fault",
                "type": "Bitmap",
                "values": {
                    "label": [
                        "short_circuit_alarm",
                        "surge_alarm",
                        "overload_alarm",
                        "leakagecurr_alarm",
                        "temp_dif_fault",
                        "fire_alarm",
                        "high_power_alarm",
                        "self_test_alarm",
                        "ov_cr",
                        "unbalance_alarm",
                        "ov_vol",
                        "undervoltage_alarm",
                        "miss_phase_alarm",
                        "outage_alarm",
                        "magnetism_alarm",
                        "credit_alarm",
                        "no_balance_alarm",
                        "phase_seq_err_alarm",
                        "vol_unbalance_alarm",
                        "low_current_alarm"
                    ],
                    "maxlen": 20
                }
            },
            "11": {
                "code": "switch_prepayment",
                "type": "Boolean",
                "values": {}
            },
            "12": {
                "code": "clear_energy",
                "type": "Boolean",
                "values": {}
            },
            "13": {
                "code": "balance_energy",
                "type": "Integer",
                "values": {
                    "unit": "kW\u00b7h",
                    "min": 0,
                    "max": 99999999,
                    "scale": 2,
                    "step": 1
                }
            },
            "14": {
                "code": "charge_energy",
                "type": "Integer",
                "values": {
                    "unit": "kW\u00b7h",
                    "min": 0,
                    "max": 999999,
                    "scale": 2,
                    "step": 1
                }
            },
            "15": {
                "code": "leakage_current",
                "type": "Integer",
                "values": {
                    "unit": "mA",
                    "min": 0,
                    "max": 1000,
                    "scale": 0,
                    "step": 1
                }
            },
            "16": {
                "code": "switch",
                "type": "Boolean",
                "values": {}
            },
            "17": {
                "code": "alarm_set_1",
                "type": "Raw",
                "values": {}
            },
            "18": {
                "code": "alarm_set_2",
                "type": "Raw",
                "values": {}
            },
            "101": {
                "code": "recover_sec",
                "type": "Integer",
                "values": {
                    "unit": "s",
                    "min": 1,
                    "max": 99,
                    "scale": 0,
                    "step": 1
                }
            },
            "102": {
                "code": "recover_cnt",
                "type": "Integer",
                "values": {
                    "unit": "\u6b21",
                    "min": 1,
                    "max": 30,
                    "scale": 0,
                    "step": 1
                }
            },
            "103": {
                "code": "temp_current",
                "type": "Integer",
                "values": {
                    "unit": "\u00b0C",
                    "min": -20,
                    "max": 200,
                    "scale": 0,
                    "step": 1
                }
            },
            "104": {
                "code": "recover_enable",
                "type": "Boolean",
                "values": {}
            },
            "105": {
                "code": "countdown_1",
                "type": "Integer",
                "values": {
                    "unit": "s",
                    "min": 0,
                    "max": 86400,
                    "scale": 0,
                    "step": 1
                }
            },
            "106": {
                "code": "cycle_time",
                "type": "String",
                "values": "{\"maxlen\":255}"
            },
            "107": {
                "code": "leak_delay",
                "type": "Integer",
                "values": {
                    "unit": "s",
                    "min": 1,
                    "max": 99,
                    "scale": 0,
                    "step": 1
                }
            },
            "108": {
                "code": "random_time",
                "type": "String",
                "values": "{\"maxlen\":255}"
            },
            "109": {
                "code": "switch_inching",
                "type": "String",
                "values": "{\"maxlen\":255}"
            },
            "110": {
                "code": "reverse_energy_total",
                "type": "Integer",
                "values": {
                    "unit": "kW\u00b7h",
                    "min": 0,
                    "max": 99999999,
                    "scale": 2,
                    "step": 1
                }
            },
            "111": {
                "code": "power_total",
                "type": "Integer",
                "values": {
                    "unit": "kW",
                    "min": 0,
                    "max": 900000,
                    "scale": 3,
                    "step": 1
                }
            },
            "112": {
                "code": "power_reactive",
                "type": "Integer",
                "values": {
                    "unit": "Kvar",
                    "min": 1,
                    "max": 9999,
                    "scale": 1,
                    "step": 1
                }
            },
            "113": {
                "code": "pa_instant",
                "type": "Raw",
                "values": {}
            },
            "114": {
                "code": "pb_instant",
                "type": "Raw",
                "values": {}
            },
            "115": {
                "code": "pc_instant",
                "type": "Raw",
                "values": {}
            },
            "116": {
                "code": "energy_total",
                "type": "Integer",
                "values": {
                    "unit": "kwh",
                    "min": 1,
                    "max": 999999,
                    "scale": 3,
                    "step": 1
                }
            },
            "117": {
                "code": "energy_all",
                "type": "Raw",
                "values": {}
            },
            "118": {
                "code": "power_factor",
                "type": "Integer",
                "values": {
                    "unit": "p\u00b0F",
                    "min": 1,
                    "max": 1000,
                    "scale": 3,
                    "step": 1
                }
            },
            "119": {
                "code": "power_on_delay",
                "type": "Integer",
                "values": {
                    "unit": "s",
                    "min": 1,
                    "max": 9999,
                    "scale": 0,
                    "step": 1
                }
            },
            "120": {
                "code": "alarm_v_delay",
                "type": "Integer",
                "values": {
                    "unit": "s",
                    "min": 1,
                    "max": 9999,
                    "scale": 0,
                    "step": 1
                }
            },
            "121": {
                "code": "alarm_over_c_delay",
                "type": "Integer",
                "values": {
                    "unit": "s",
                    "min": 1,
                    "max": 9999,
                    "scale": 0,
                    "step": 1
                }
            },
            "122": {
                "code": "alarm_low_c_delay",
                "type": "Integer",
                "values": {
                    "unit": "s",
                    "min": 1,
                    "max": 9999,
                    "scale": 0,
                    "step": 1
                }
            },
            "123": {
                "code": "alam_v_cnt",
                "type": "Integer",
                "values": {
                    "unit": "s",
                    "min": 1,
                    "max": 9999,
                    "scale": 0,
                    "step": 1
                }
            },
            "124": {
                "code": "alarm_over_c_cnt",
                "type": "Integer",
                "values": {
                    "unit": "s",
                    "min": 1,
                    "max": 999,
                    "scale": 0,
                    "step": 1
                }
            },
            "125": {
                "code": "alarm_low_c_cnt",
                "type": "Integer",
                "values": {
                    "unit": "s",
                    "min": 1,
                    "max": 999,
                    "scale": 0,
                    "step": 1
                }
            },
            "126": {
                "code": "alarm_set3",
                "type": "Raw",
                "values": {}
            },
            "127": {
                "code": "status",
                "type": "Enum",
                "values": {
                    "range": [
                        "0",
                        "1",
                        "2"
                    ]
                }
            },
            "128": {
                "code": "status_b",
                "type": "Enum",
                "values": {
                    "range": [
                        "0",
                        "1",
                        "2"
                    ]
                }
            },
            "129": {
                "code": "status_c",
                "type": "Enum",
                "values": {
                    "range": [
                        "0",
                        "1",
                        "2"
                    ]
                }
            }
        },
        "ip": "172.16.66.129",
        "version": "3.4"
    },

@grosjo
Copy link

grosjo commented Dec 7, 2024

Tuya devices are by default cloud devices. The local API is a afterthought and appears to have been added to allow the SmartLife app to initial configure and control them locally if the cloud is unavailable. Unfortunately, the stability of the local API varies greatly from device to device. I wish we knew why they get in a bad state.

Some suggestions:

  • Power cycle the device
  • Power cycle workstation or run tinytuya from another host
  • Restart network router or dhcp lease to get a new IP assigned to device in case it is an arp issue
  • Run scanner in debug mode python -m tinytuya scan -d
  • Run wizard to ensure local key didn't change python -m tinytuya wizard
  • Force a local key change by re-pairing the device with SmartLife and run Wizard to get the new key

@jasonacox is there a method to reboot the device from tinytuya ?

@uzlonewolf
Copy link
Collaborator

Sadly no, there is no way to reboot the device. I've disassembled a few firmware images and the only path to a reboot I've found is while factory defaulting the device.

@grosjo
Copy link

grosjo commented Dec 8, 2024

Maybe a second device to switch off/on the first one ;)

I am curious how did you manage to extract the firmware ?

@uzlonewolf
Copy link
Collaborator

There are several ways you can get the firmware.

  1. If the device has a firmware update available, use TuyAPI to get the upgrade URL and then just wget the binary.
api.loginEx({ email: "<app email here>", password: "<app password here>" }).then(async sid => {
    console.log(sid);
    api.request({
        action: "tuya.m.device.check.for.updates",
        data: {
                "devId": "<device id here>",
        },
    }).then(async data => {
        console.log('F/W data:');
        console.log(data);
});
  1. A lot of devices use Beken chips which can be read out using a USB-serial converter and some publicly-available tools (look into OpenBeken).

  2. Older devices can be dumped wirelessly with Cloudcutter Lightleak.

@grosjo
Copy link

grosjo commented Dec 8, 2024

What language is that ?

@uzlonewolf
Copy link
Collaborator

Javascript (Node.js) using TuyAPI. My full script is actually:

const Cloud = require('@tuyapi/cloud');
const debug = require('debug');

debug.enable("@tuyapi/cloud");

let api = new Cloud({
        key: "ekmnwp9f5pnh3trdtpgy",
        secret: "r3me7ghmxjevrvnpemwmhw3fxtacphyg",
        secret2: "jfg5rs5kkmrj5mxahugvucrsvw43t48x",
    certSign: "0F:C3:61:99:9C:C0:C3:5B:A8:AC:A5:7D:AA:55:93:A2:0C:F5:57:27:70:2E:A8:5A:D7:B3:22:89:49:F8:88:FE",
        apiEtVersion: '0.0.1',
        region: 'AZ', // replace with EU if appropriate                                                                                                                                                                               
        endpoint: "https://a1.tuyaus.com/api.json", // replace with tuyaeu.com if appropriate                                                                                                                                         
        // sid: "",                                                                                                                                                                                                                   
});

api.loginEx({ email: "<smartlife app email here>", password: "<password here>" }).then(async sid => {
    console.log(sid);
    api.request({
        action: "tuya.m.device.check.for.updates",
        data: {
                "devId": "<device id here>",
        },
    }).then(async data => {
        console.log('F/W data:');
        console.log(data);
    });
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tuya_device Support for specific Tuya Devices
Projects
None yet
Development

No branches or pull requests

5 participants