jasonacox / tinytuya

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

How to get power status of light bulb, Py noob #25

Closed Electrik-rich546456 closed 1 year ago

Electrik-rich546456 commented 3 years ago

Hello I would like to know how make a script that checks status of lights before switching strate. Looking at how the code is made it should be possible but i cannot figure it out as i'm still learning python DPS_2_STATE = does not end at 24 in this file

my output from print('\nCurrent Status of Bulb: %r' % data) is Current Status of Bulb: {'dps': {'20': True, '21': 'white', '22': 1000, '23': 1000, '24': '000003e803e8', '25': '000e0d0000000000000000c80000', '26': 0}} Is that why I cant see the power state ?

jasonacox commented 3 years ago

It looks like you have an RGB light bulb you are wanting to control? These data points match what is expected for a bulb: https://github.com/jasonacox/tinytuya#version-33---light-type-rgb

Here is an example that gets the status of the light before turning it on and off.

import tinytuya
import time

# Connect to Tuya BulbDevice
print('\nConnecting to Tuya Bulb')
d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
d.set_version(3.3)

# Show status of device
data = d.status()
print('\nCurrent Status of Bulb: %r' % data)

# Check to see if the bulb is on and get state of device
data = d.state()
print('\nStatus of Bulb: %r and the Bulb is: ' % data)
if (data['is_on']==True):
    print('ON')
else:
    print('OFF')

# Power Control Test
print('\nPower Control Test')
print('    Turn off lamp')
d.turn_off()
time.sleep(2)
print('    Turn on lamp')
d.turn_on()

Also, you may want to look at this example code for RGB lights: https://github.com/jasonacox/tinytuya/blob/master/examples/bulb.py#L1-L118

Electrik-rich546456 commented 3 years ago

Thanks for the reply but i get Undefined name 'DEVICEID'. as i just pasted that code snippet into my IDE and so is it possible to refer to devid and ip and key just by name that devices.json file contains. Also how do i create code that controls a group of bulbs at same time by name reference?

Electrik-rich546456 commented 3 years ago

I got it working using this

if(data['dps']['20'] == True):
    print("its on Turning off")
    d.turn_off()
elif(data['dps']['20'] == False):
    print("its off Turing on")
    d.turn_on()

Inside the example bulb.py file with all lines below 44 commented out

jasonacox commented 3 years ago

Yes, you will need to replace those DEVICE placeholders with the actual values or prefix the code with the device details setting the variables like this:

DEVICEID = "01234567891234567890"
DEVICEIP = "10.0.1.99"
DEVICEKEY = "0123456789abcdef"

You can indeed pull this data from the generated devices.json for DEVICEID and DEVICEKEY. Set DEVICEIP = "0.0.0.0" to have tinytuya scan for the device (warning: autoIP lookup requires scanning the network and is slow and can timeout).

My challenge to you is to use this as a great opportunity to learn Python. Look up JSON file parsing and see if you can figure out how to look up the device details by name. Have fun! :-)

Electrik-rich546456 commented 3 years ago

Would it not be better to use the snapshot.json file as it contains what is needed?

jasonacox commented 3 years ago

Go for it! Keep in mind that if you use DHCP on your network, the IP address of the devices can change over time.

Electrik-rich546456 commented 3 years ago

Hi @jasonacox I managed to get this code but i am getting this error so I have a few questions about the code.

#!/usr/bin/env python3

import json

with open('/home/pi/cloudtuya/snapshot.json') as json_file:
    data_dict = json.load(json_file)
    #data_dict = json.loads(json_file.read())
    print(data_dict)
#    print(data_dict["name"])
    print(data_dict["ip"])
    print(data_dict["id"])
    print(data_dict["key"])

    #for p in data['devices']:
    #    print(['name']['ip']["id"]["key"])

If i want to keep a connection open to control the lights how do i make that happen? You should see the monstro code i've made.... I would appreciate your help . Error

Traceback (most recent call last):
  File "./home-work.py", line 9, in <module>
    print(data_dict[["name"]])
Electrik-rich546456 commented 3 years ago

This code is not related to yours but I may help someone doing the same.

#!/usr/bin/env python3
import argparse
import signal
import sys
import time
import logging
import my_room
#import living_room
#import all_rooms
from rpi_rf import RFDevice
rfdevice = None
debounce = 10
# pylint: disable=unused-argument
def exithandler(signal, frame):
    rfdevice.cleanup()
    sys.exit(0)

logging.basicConfig(level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S',
                    format='%(asctime)-15s - [%(levelname)s] %(module)s: %(message)s', )

parser = argparse.ArgumentParser(description='Receives a decimal code via a 433/315MHz GPIO device')
parser.add_argument('-g', dest='gpio', type=int, default=27,
                    help="GPIO pin (Default: 27)")
args = parser.parse_args()

signal.signal(signal.SIGINT, exithandler)
rfdevice = RFDevice(args.gpio)
rfdevice.enable_rx()
timestamp = None
oldtime = time.perf_counter()
oldtime1 = time.perf_counter()
oldtime2 = time.perf_counter()
oldtime3 = time.perf_counter()

#Received code 835186. is L Switch near entrance
#Received code 818562. is L Switch in hall way
#-------
#Received code 3764961. is big button on car remote <---- Living Room
#Received code 3764962. is next button on car remote <----Leo
#Received code 3764964. is next button on car remote <----My room
#Received code 3764968. is small button on car remote <--- all off
while True:
    dt = (time.strftime("%I:%M:%S %p"))
    if rfdevice.rx_code_timestamp != timestamp:
        timestamp = rfdevice.rx_code_timestamp
        now = time.perf_counter()
        if ((str(rfdevice.rx_code) == '3764961')) or  ((str(rfdevice.rx_code) == '818562')) or ((str(rfdevice.rx_code) == '835186')) :
            elapsed = now - oldtime
            if elapsed < debounce:
                #print("Ignoring Duplicate Button Press")
                pass
            else:
                oldtime = now
                print("Front Room Lights Pressed" ,  dt)
                my_room.living()
##--------------------------------------leo-------------------------------------------------------------------------
        elif ((str(rfdevice.rx_code) == '3764962')):
            now1 = time.perf_counter()
            elapsed1 = now1 - oldtime1
            if elapsed1 < debounce:
                #print("Ignoring Duplicate Button Press")
                pass
            else:
                oldtime1 = now1
                print("Leo's Room Lights Pressed" ,  dt)
                my_room.leo()
##--------------------------------My Room-------------------------------------------------------------------------------
        elif ((str(rfdevice.rx_code) == '3764964')):
            now2 = time.perf_counter()
            elapsed2 = now2 - oldtime2
            if elapsed2 < debounce:
                #print("Ignoring Duplicate Button Press")
                pass
            else:
                oldtime2 = now2
                print("My Room Lights Pressed" ,  dt)
                my_room.main()
##--------------------------------------------------------------------------------------------------------
        elif ((str(rfdevice.rx_code) == '3764968')):
            now3 = time.perf_counter()
            elapsed3 = now3 - oldtime3
            if elapsed3 < debounce:
                #print("Ignoring Duplicate Button Press")
                pass
            else:
                oldtime3 = now3
                print("All Room's Lights Off" ,  dt)
                my_room.all_off()
#-----------------------------------------------------------------------------------------------------------

    time.sleep(0.01)
rfdevice.cleanup()

This code listens for the 432mhz from wireless switches so is running all the time n the background. When it picks up the remote press it runs your code se below. I know I've repeated the code lots but couldn't work out how to reuse code and one point i tried to call a function like this my_room.all_off.payload() but apparently 'function' object has no attribute 'payload'

#!/usr/bin/env python3

# TinyTuya Example
# -*- coding: utf-8 -*-
from threading import Thread

import tinytuya
import os

#Leos Light
def lr1():

    DEVICEID = "<Fake_Data>"
    DEVICEIP = "<Fake_Data>"
    DEVICEKEY = "<Fake_Data>"
    DEVICEVERS = "<Fake_Data>"

    # Check for environmental variables and always use those if available
    DEVICEID = os.getenv("DEVICEID", DEVICEID)
    DEVICEIP = os.getenv("DEVICEIP", DEVICEIP)
    DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY)
    DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS)

    # Connect to Tuya BulbDevice
    d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
    if(DEVICEVERS == '3.3'):    # IMPORTANT to always set version 
        d.set_version(3.3)
    else:
        d.set_version(3.1)
    # Keep socket connection open between commands
    d.set_socketPersistent(True)  

    ##print('    Turn off lamp 1')
    data = d.status()
    if(data['dps']['20'] == True):
        #print("its on Turning off")
        d.turn_off()
    elif(data['dps']['20'] == False):
        #print("its off Turing on")
        d.turn_on()

#Smart Light 1
def sm1():

    DEVICEID = "<Fake_Data>"
    DEVICEIP = "<Fake_Data>"
    DEVICEKEY = "<Fake_Data>"
    DEVICEVERS = "<Fake_Data>"

    # Check for environmental variables and always use those if available
    DEVICEID = os.getenv("DEVICEID", DEVICEID)
    DEVICEIP = os.getenv("DEVICEIP", DEVICEIP)
    DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY)
    DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS)

    # Connect to Tuya BulbDevice
    d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
    if(DEVICEVERS == '3.3'):    # IMPORTANT to always set version 
        d.set_version(3.3)
    else:
        d.set_version(3.1)
    # Keep socket connection open between commands
    d.set_socketPersistent(True)  

    ##print('    Turn off lamp 1')
    data = d.status()
    if(data['dps']['20'] == True):
        ##print("its on Turning off")
        d.turn_off()
    elif(data['dps']['20'] == False):
        ##print("its off Turing on")
        d.turn_on()

#Smart Light 2
def sm2():

    DEVICEID = "<Fake_Data>"
    DEVICEIP = "<Fake_Data>"
    DEVICEKEY = "<Fake_Data>"
    DEVICEVERS = "3.3"

    # Check for environmental variables and always use those if available
    DEVICEID = os.getenv("DEVICEID", DEVICEID)
    DEVICEIP = os.getenv("DEVICEIP", DEVICEIP)
    DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY)
    DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS)

    # Connect to Tuya BulbDevice
    d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
    if(DEVICEVERS == '3.3'):    # IMPORTANT to always set version 
        d.set_version(3.3)
    else:
        d.set_version(3.1)
    # Keep socket connection open between commands
    d.set_socketPersistent(True)  

    ##print('    Turn off lamp 2')
    data = d.status()
    if(data['dps']['20'] == True):
        ##print("its on Turning off")
        d.turn_off()
    elif(data['dps']['20'] == False):
        ##print("its off Turing on")
        d.turn_on()

#Smart Light 3
def sm3():
    DEVICEID = <Fake_Data>"
    DEVICEIP = "<Fake_Data>"
    DEVICEKEY = "<Fake_Data>"
    DEVICEVERS = "3.3"

    # Check for environmental variables and always use those if available
    DEVICEID = os.getenv("DEVICEID", DEVICEID)
    DEVICEIP = os.getenv("DEVICEIP", DEVICEIP)
    DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY)
    DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS)

    # Connect to Tuya BulbDevice
    d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
    if(DEVICEVERS == '3.3'):    # IMPORTANT to always set version 
        d.set_version(3.3)
    else:
        d.set_version(3.1)
    # Keep socket connection open between commands
    d.set_socketPersistent(True)  

    ##print('    Turn off lamp 3')
    data = d.status()
    if(data['dps']['20'] == True):
        ##print("its on Turning off")
        d.turn_off()
    elif(data['dps']['20'] == False):
        ##print("its off Turing on")
        d.turn_on()

#My BedRoom Light
def br1():
    DEVICEID = "<Fake_Data>"
    DEVICEIP = "<Fake_Data>"
    DEVICEKEY = "<Fake_Data>"
    DEVICEVERS = ""

    # Check for environmental variables and always use those if available
    DEVICEID = os.getenv("DEVICEID", DEVICEID)
    DEVICEIP = os.getenv("DEVICEIP", DEVICEIP)
    DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY)
    DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS)

    # Connect to Tuya BulbDevice
    d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
    if(DEVICEVERS == '3.3'):    # IMPORTANT to always set version 
        d.set_version(3.3)
    else:
        d.set_version(3.1)
    # Keep socket connection open between commands
    d.set_socketPersistent(True)  

    ##print('    Turn off lamp 3')
    data = d.status()
    if(data['dps']['1'] == True):
        #print("its on Turning off")
        d.turn_off()
    elif(data['dps']['1'] == False):
        #print("its off Turing on")
#    #print(data)
        d.turn_on()
def main():
    Thread(target = br1).start() #My Room
def leo():
    Thread(target = lr1).start() #Leos room
def living():
    Thread(target = sm1).start() #Living Room
    Thread(target = sm2).start() #Living Room
    Thread(target = sm3).start() #Living Room
#---------------------------------------------------------------------------------------all off ctrl---------------------
def all_off():
    #Leos Light
    def lr1():
        DEVICEID = "<Fake_Data>"
        DEVICEIP = "<Fake_Data>"
        DEVICEKEY = "<Fake_Data>"
        DEVICEVERS = "<Fake_Data>"
        # Check for environmental variables and always use those if available
        DEVICEID = os.getenv("DEVICEID", DEVICEID)
        DEVICEIP = os.getenv("DEVICEIP", DEVICEIP)
        DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY)
        DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS)
        # Connect to Tuya BulbDevice
        d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
        if(DEVICEVERS == '3.3'):    # IMPORTANT to always set version 
            d.set_version(3.3)
        else:
            d.set_version(3.1)
        # Keep socket connection open between commands
        d.set_socketPersistent(True)  
        d.turn_off()
    #Smart Light 1
    def sm1():
        DEVICEID = "<Fake_Data>"
        DEVICEIP = "<Fake_Data>"
        DEVICEKEY = "<Fake_Data>"
        DEVICEVERS = "3.3"
        # Check for environmental variables and always use those if available
        DEVICEID = os.getenv("DEVICEID", DEVICEID)
        DEVICEIP = os.getenv("DEVICEIP", DEVICEIP)
        DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY)
        DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS)
        # Connect to Tuya BulbDevice
        d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
        if(DEVICEVERS == '3.3'):    # IMPORTANT to always set version 
            d.set_version(3.3)
        else:
            d.set_version(3.1)
        # Keep socket connection open between commands
        d.set_socketPersistent(True)  
        d.turn_off()    
    #Smart Light 2
    def sm2():
        DEVICEID = "<Fake_Data>"
        DEVICEIP = "<Fake_Data>"
        DEVICEKEY = "<Fake_Data>"
        DEVICEVERS = "3.3"
        # Check for environmental variables and always use those if available
        DEVICEID = os.getenv("DEVICEID", DEVICEID)
        DEVICEIP = os.getenv("DEVICEIP", DEVICEIP)
        DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY)
        DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS)
        # Connect to Tuya BulbDevice
        d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
        if(DEVICEVERS == '3.3'):    # IMPORTANT to always set version 
            d.set_version(3.3)
        else:
            d.set_version(3.1)
        # Keep socket connection open between commands
        d.set_socketPersistent(True)  
        d.turn_off()
    #Smart Light 3
    def sm3():
        DEVICEID = "<Fake_Data>"
        DEVICEIP = "<Fake_Data>"
        DEVICEKEY = "<Fake_Data>"
        DEVICEVERS = "3.3"
        # Check for environmental variables and always use those if available
        DEVICEID = os.getenv("DEVICEID", DEVICEID)
        DEVICEIP = os.getenv("DEVICEIP", DEVICEIP)
        DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY)
        DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS)
        # Connect to Tuya BulbDevice
        d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
        if(DEVICEVERS == '3.3'):    # IMPORTANT to always set version 
            d.set_version(3.3)
        else:
            d.set_version(3.1)
        # Keep socket connection open between commands
        d.set_socketPersistent(True)
        d.turn_off()
    #My BedRoom Light
    def br1():
        DEVICEID = "<Fake_Data>"
        DEVICEIP = "<Fake_Data>"
        DEVICEKEY = "<Fake_Data>"
        DEVICEVERS = ""
        # Check for environmental variables and always use those if available
        DEVICEID = os.getenv("DEVICEID", DEVICEID)
        DEVICEIP = os.getenv("DEVICEIP", DEVICEIP)
        DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY)
        DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS)
        # Connect to Tuya BulbDevice
        d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
        if(DEVICEVERS == '3.3'):    # IMPORTANT to always set version 
            d.set_version(3.3)
        else:
            d.set_version(3.1)
        # Keep socket connection open between commands
        d.set_socketPersistent(True)  
        d.turn_off()
#    def payload():
    Thread(target = lr1).start() #Leos room
    Thread(target = sm1).start() #Living Room
    Thread(target = sm2).start() #Living Room
    Thread(target = sm3).start() #Living Room
    Thread(target = br1).start() #My Room

#---------------------------------------------------------------------------------------------------------------------------

if __name__ == '__main__':
    main()
Electrik-rich546456 commented 3 years ago

Would something like this work ?

#at top of file----
global ALLOFFVAR
ALLOFFVAR = ""
-------snipped -----------
def all_pof():
    global ALLOFFVAR
    ALLOFFVAR = "1"
    main()
    leo()
    living()
    ALLOFFVAR = "0"

If i put this in each light bulb definition

 if (ALLOFFVAR == '1'):
        d.turn_off()
jasonacox commented 3 years ago

First for the JSON reading, you can use something like this to print out everything in the snapshot:

import json

with open('snapshot.json') as json_file:
     data = json.load(json_file)

print("%-25s %-24s %-16s %-17s %-5s" % ("Name","ID", "IP","Key","Version"))
for item in data["devices"]:
    print("%-25.25s %-24s %-16s %-17s %-5s" % (
        item["name"],
        item["id"],
        item["ip"],
        item["key"],
        item["ver"]))

If you wanted to get the status of all the devices listed in snapshot, you would do this:

import tinytuya
import json

with open('snapshot.json') as json_file:
     data = json.load(json_file)

# print status
for item in data["devices"]:
    print("\nDevice: %s" % item["name"])
    d = tinytuya.OutletDevice(item["id"], item["ip"], item["key"])
    d.set_version(float(item["ver"]))
    status = d.status()  
    print(status)

You could edit the above to have it turn on everything in that JSON file. Or you could write a function that turns on/off a light based on the name:

import tinytuya
import json
import time

with open('snapshot.json') as json_file:
     data = json.load(json_file)

# Turn on a device by name
def turn_on(name):
    # find the right item that matches name
    for item in data["devices"]:
        if item["name"] == name:
            break
    print("\nTurning On: %s" % item["name"])
    d = tinytuya.OutletDevice(item["id"], item["ip"], item["key"])
    d.set_version(float(item["ver"]))
    d.set_status(True)

# Turn off a device by name
def turn_off(name):
    # find the right item that matches name
    for item in data["devices"]:
        if item["name"] == name:
            break
    print("\nTurning Off: %s" % item["name"])
    d = tinytuya.OutletDevice(item["id"], item["ip"], item["key"])
    d.set_version(float(item["ver"]))
    d.set_status(False)

# Test it
turn_off('Dining Room')
time.sleep(2)
turn_on('Dining Room')
Electrik-rich546456 commented 3 years ago

Ok i tried the above bit of code out and it just spits out this error after a long wait .

./name_ctrl.py

Turning Off: Smart Light 2
Exceeded tinytuya retry limit (5)
Traceback (most recent call last):
  File "/home/pi/.local/lib/python3.7/site-packages/tinytuya/__init__.py", line 353, in _send_receive
    data = self.socket.recv(1024)  # try again
socket.timeout: timed out
Traceback (most recent call last):
  File "./name_ctrl.py", line 33, in <module>
    turn_off('Smart Light 2')
  File "./name_ctrl.py", line 30, in turn_off
    d.set_status(False)
  File "/home/pi/.local/lib/python3.7/site-packages/tinytuya/__init__.py", line 608, in set_status
    data = self._send_receive(payload)
  File "/home/pi/.local/lib/python3.7/site-packages/tinytuya/__init__.py", line 353, in _send_receive
    data = self.socket.recv(1024)  # try again
socket.timeout: timed out
Electrik-rich546456 commented 3 years ago

How do i recreate the .json files just incase i broke them ...

Electrik-rich546456 commented 3 years ago

I've just discovered that one of the light bulbs does not have any info for

"ip": 0,
"ver": 0,
jasonacox commented 3 years ago

You can create snapshot.json:

python -m tinytuya scan

Can you run this script and see if the "Smart Light 2" actually has all the correct values?

import json

with open('snapshot.json') as json_file:
     data = json.load(json_file)

print("%-25s %-24s %-16s %-17s %-5s" % ("Name","ID", "IP","Key","Version"))
for item in data["devices"]:
    print("%-25.25s %-24s %-16s %-17s %-5s" % (
        item["name"],
        item["id"],
        item["ip"],
        item["key"],
        item["ver"]))
Electrik-rich546456 commented 3 years ago

I'm not sure but i think the problem it has, Is the ver of that light bulb is different to the rest as the dps is at 1 not 20. I ran the status and received this info

Name                      ID                       IP               Key               Version
Smart Light 2             <  fake       data   >   < fake data >    <fake   data   >   3.3  
Bedside Light             <  fake       data   >   < fake data >    <fake   data   >      
Smart Light 1             <  fake       data   >   < fake data >    <fake   data   >   3.3  
Side Light                <  fake       data   >   < fake data >    <fake   data   >   3.3  
Smart Light 3             <  fake       data   >   < fake data >    <fake   data   >   3.3  

Device: Smart Light 2
{'dps': {'20': True, '21': 'white', '22': 400, '23': 400, '24': '<fake data > ', '25': '<fake data > ', '26': 0}}

Device: Bedside Light
{'devId': '<fake data > ', 'dps': {'1': True, '2': 'white', '3': 25, '4': 255, '5': '<fake data > ', '6': '<fake data > ', '7': '<fake data > ', '8': '<fake data > ', '9': '<fake data > ', '10': '<fake data > '}}

Device: Smart Light 1
{'dps': {'20': True, '21': 'white', '22': 400, '23': 400, '24': '<fake data > ', '25': '<fake data > ', '26': 0}}

Device: Side Light
{'dps': {'20': False, '21': 'white', '22': 500, '23': 500, '24': '<fake data > ', '25': '<fake data > ', '26': 0}}

Device: Smart Light 3
{'dps': {'20': True, '21': 'white', '22': 400, '23': 400, '24': '<fake data > ', '25': '<fake data > ', '26': 0}}

Turning Off: Smart Light 2
Exceeded tinytuya retry limit (5)
Traceback (most recent call last):
  File "/home/pi/.local/lib/python3.7/site-packages/tinytuya/__init__.py", line 353, in _send_receive
    data = self.socket.recv(1024)  # try again
socket.timeout: timed out
Traceback (most recent call last):
  File "./name_ctrl.py", line 58, in <module>
    turn_off('Smart Light 2')
  File "./name_ctrl.py", line 56, in turn_off
    d.set_status(False)
  File "/home/pi/.local/lib/python3.7/site-packages/tinytuya/__init__.py", line 608, in set_status
    data = self._send_receive(payload)
  File "/home/pi/.local/lib/python3.7/site-packages/tinytuya/__init__.py", line 353, in _send_receive
    data = self.socket.recv(1024)  # try again
socket.timeout: timed out
Electrik-rich546456 commented 3 years ago

The strange thing is it runs ok from my code modified from bulb.py as the function br1()

jasonacox commented 3 years ago

That makes sense! If these are all bulbs, not switches, update the code to use BulbDevice instead of OutletDevice as the BulbDevice class add extra handling for smart bulbs:

import tinytuya
import json
import time

with open('snapshot.json') as json_file:
     data = json.load(json_file)

# Turn on a device by name
def turn_on(name):
    # find the right item that matches name
    for item in data["devices"]:
        if item["name"] == name:
            break
    print("\nTurning On: %s" % item["name"])
    d = tinytuya.BulbDevice(item["id"], item["ip"], item["key"])
    d.set_version(float(item["ver"]))
    d.set_status(True)

# Turn off a device by name
def turn_off(name):
    # find the right item that matches name
    for item in data["devices"]:
        if item["name"] == name:
            break
    print("\nTurning Off: %s" % item["name"])
    d = tinytuya.BulbDevice(item["id"], item["ip"], item["key"])
    d.set_version(float(item["ver"]))
    d.set_status(False)

# Test it
turn_off('Dining Room')
time.sleep(2)
turn_on('Dining Room')
Electrik-rich546456 commented 3 years ago

Very strange... It offers me the same error :-(

./name_ctrl.py

Turning Off: Smart Light 2
Exceeded tinytuya retry limit (5)
Traceback (most recent call last):
  File "/home/pi/.local/lib/python3.7/site-packages/tinytuya/__init__.py", line 353, in _send_receive
    data = self.socket.recv(1024)  # try again
socket.timeout: timed out
Traceback (most recent call last):
  File "./name_ctrl.py", line 31, in <module>
    turn_off('Smart Light 2')
  File "./name_ctrl.py", line 29, in turn_off
    d.set_status(False)
  File "/home/pi/.local/lib/python3.7/site-packages/tinytuya/__init__.py", line 608, in set_status
    data = self._send_receive(payload)
  File "/home/pi/.local/lib/python3.7/site-packages/tinytuya/__init__.py", line 353, in _send_receive
    data = self.socket.recv(1024)  # try again
socket.timeout: timed out

So how do we work out why this is happening ? Have you got discord? It would be nice to try and work this out in real time.

jasonacox commented 3 years ago

Oops... I guess I keep hoping you will debug my mistakes! :-)

For BubDevices types, you need to use turn_on() and turn_off() commands. My script was written for switches, not smart bulbs and I didn't update that bit, so the right answer would be:

import tinytuya
import json
import time

tinytuya.set_debug(True)

with open('snapshot.json') as json_file:
     data = json.load(json_file)

# Turn on a device by name
def turn_on(name):
    # find the right item that matches name
    for item in data["devices"]:
        if item["name"] == name:
            break
    print("\nTurning On: %s" % item["name"])
    d = tinytuya.BulbDevice(item["id"], item["ip"], item["key"])
    d.set_version(float(item["ver"]))
    d.turn_on()

# Turn off a device by name
def turn_off(name):
    # find the right item that matches name
    for item in data["devices"]:
        if item["name"] == name:
            break
    print("\nTurning Off: %s" % item["name"])
    d = tinytuya.BulbDevice(item["id"], item["ip"], item["key"])
    d.set_version(float(item["ver"]))
    d.turn_off()

# Test it
turn_off('SmartBulb')
time.sleep(2)
turn_on('SmartBulb')
Electrik-rich546456 commented 3 years ago

Ahh I see, well still have a lot of learning by making silly mistakes like not spotting that. Thanks. Now how do i add an *args to make that function behave either as a toggle or a 'turn off only' :-)

Electrik-rich546456 commented 3 years ago

I'm not sure but i think i may have done it .. :-) with the following code.

def turn_on(name, *num):
    for item in jdata["devices"]:
        if item["name"] == name:
            break
    d = tinytuya.BulbDevice(item["id"], item["ip"], item["key"])
    d.set_version(float(item["ver"]))
    d.set_socketPersistent(True)
    data = d.status()
    for n in num:
        if n == 2:
            d.turn_off()
        else:
            if(data['dps']['20'] == True):
                ##print("its on Turning off")
                d.turn_off()
            elif(data['dps']['20'] == False):
                ##print("its off Turing on")
                d.turn_on()