Skip to content

Commit 01095a1

Browse files
authored
Merge pull request #617 from uzlonewolf/bulb-rewrite
Rewrite BulbDevice and rework set_multiple_values(), again
2 parents 9935b5c + c5c02a4 commit 01095a1

File tree

13 files changed

+1654
-1033
lines changed

13 files changed

+1654
-1033
lines changed

RELEASE.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,57 @@
11
# RELEASE NOTES
22

3+
## v1.17.0 - BulbDevice Rewrite
4+
5+
* Rewrite BulbDevice and rework set_multiple_values() @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/617
6+
* Tool updates: pcap parse fix, new broadcast relay by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/612
7+
* Fix initialization bug with python2 (embedded devices) by @Ircama in https://github.com/jasonacox/tinytuya/pull/615
8+
9+
BulbDevice Example Usage
10+
11+
```python
12+
import time
13+
import random
14+
import tinytuya
15+
16+
d = tinytuya.BulbDevice(DEVICEID, address=DEVICEIP, local_key=DEVICEKEY, version=DEVICEVERS, persist=True)
17+
18+
# BASIC FUNCTIONS
19+
print('Basic Tests')
20+
d.set_colour(255,127,63) # Set to orange
21+
d.set_white_percentage(100.0, 0.0) # 100% brightness, 0% colour temperature
22+
d.set_brightness_percentage(100) # 100% brightness
23+
24+
# MUSIC MODE
25+
print("Music Mode")
26+
d.set_mode('music')
27+
d.set_socketPersistent( True )
28+
# Devices respond with a command ACK, but do not send DP updates.
29+
# Setting the 2 options below causes it to wait for a response but
30+
# return immediately after an ACK.
31+
d.set_sendWait( None )
32+
d.set_retry( False )
33+
for x in range(100):
34+
red = random.randint(0,255)
35+
green = random.randint(0,255)
36+
blue = random.randint(0,255)
37+
if (x % 6 == 0):
38+
# extend every 6 beat
39+
d.set_music_colour( d.MUSIC_TRANSITION_FADE, red, green, blue )
40+
time.sleep(2)
41+
else:
42+
# Jump!
43+
d.set_music_colour( d.MUSIC_TRANSITION_JUMP, red, green, blue )
44+
time.sleep(0.1) # the bulbs seem to get upset if updates are faster than 0.1s (100ms)
45+
46+
# SCENE MODE
47+
if d.bulb_has_capability(d.BULB_FEATURE_SCENE_DATA):
48+
d.set_mode('scene')
49+
print('String based scenes compatible smartbulb detected.')
50+
# Example: Color rotation
51+
print('Switch to Scene 7 - Color Rotation')
52+
d.set_scene( 7, '464602000003e803e800000000464602007803e803e80000000046460200f003e803e800000000464602003d03e803e80000000046460200ae03e803e800000000464602011303e803e800000000')
53+
```
54+
355
## v1.16.3 - Cloud Error Handling
456

557
* Add error handling in Cloud getdevices() function for edge case where old devices.json has corrupt or malformed device entries.

examples/bulb-music.py

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,38 @@
33
"""
44
TinyTuya - Smart Bulb RGB Music Test
55
6-
TODO: Figure out what strings to send to the bulb to
7-
represent real music data, beats, note, fades, etc.
8-
96
Author: Jason A. Cox
107
For more information see https://github.com/jasonacox/tinytuya
118
129
"""
1310
import tinytuya
1411
import time
1512
import random
13+
import os
1614

1715
#tinytuya.set_debug()
1816

19-
# SmartBulb
2017
DEVICEID = "01234567891234567890"
21-
DEVICEIP = "10.0.1.99"
22-
DEVICEKEY = "0123456789abcdef"
23-
DEVICEVERS = "3.3"
18+
DEVICEIP = "Auto" # Will try to discover the bulb on the network
19+
DEVICEKEY = "" # Leave blank to read from devices.json
20+
DEVICEVERS = 3.3 # Must be set correctly unless IP=Auto
21+
22+
# Check for environmental variables and always use those if available
23+
DEVICEID = os.getenv("DEVICEID", DEVICEID)
24+
DEVICEIP = os.getenv("DEVICEIP", DEVICEIP)
25+
DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY)
26+
DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS)
2427

2528
print("TinyTuya - Smart Bulb Music Test [%s]\n" % tinytuya.__version__)
2629
print('TESTING: Device %s at %s with key %s version %s' %
2730
(DEVICEID, DEVICEIP, DEVICEKEY, DEVICEVERS))
2831

2932
# Connect to Tuya BulbDevice
30-
d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
31-
d.set_version(float(DEVICEVERS)) # IMPORTANT to always set version
32-
# Keep socket connection open between commands
33-
d.set_socketPersistent(True)
33+
d = tinytuya.BulbDevice(DEVICEID, address=DEVICEIP, local_key=DEVICEKEY, version=DEVICEVERS, persist=True)
34+
35+
if (not DEVICEIP) or (DEVICEIP == 'Auto') or (not DEVICEKEY) or (not DEVICEVERS):
36+
print('Device %s found at %s with key %r version %s' %
37+
(d.id, d.address, d.local_key, d.version))
3438

3539
# Show status of device
3640
data = d.status()
@@ -41,25 +45,30 @@
4145
d.set_mode('music')
4246
data = d.status()
4347

44-
x = 0
45-
while (x<20):
48+
d.set_socketPersistent( True )
49+
50+
# Devices respond with a command ACK, but do not send DP updates.
51+
# Setting the 2 options below causes it to wait for a response but
52+
# return immediately after an ACK.
53+
d.set_sendWait( None )
54+
d.set_retry( False )
55+
56+
for x in range(100):
4657
# Value is 0 1111 2222 3333 4444 5555
4758
# see: https://developer.tuya.com/en/docs/iot/solarlight-function-definition?id=K9tp16f086d5h#title-10-DP27(8)%3A%20music
48-
mode = 0 # 0 - hard transitions (jumping), 1 - smooth transitions (gradient)
49-
hue = random.randint(0,360) # 1111 (hue: 0–360, 0X0000–0X0168)
50-
saturation = random.randint(0,1000) # 2222 (saturation: 0–1000, 0X0000–0X03E8)
51-
brightness = random.randint(0,1000) # 3333 (brightness: 0–1000, 0X0000–0X03E8)
52-
white_brightness = 0 # 4444: indicates brightness. It ranges from 0 to 1,000.
53-
temperature = 0 # 5555: the temperature value (0–1000)
54-
value = f"{mode:01X}{hue:04X}{saturation:04X}{brightness:04X}{white_brightness:04X}{temperature:04X}"
55-
print (" > Sending %s" % value)
56-
payload = d.generate_payload(tinytuya.CONTROL, {"27": value})
57-
d.send(payload)
58-
if (x % 3):
59-
time.sleep(1) # extend every 3 beat
60-
time.sleep(0.2)
61-
x = x + 1
59+
red = random.randint(0,255)
60+
green = random.randint(0,255)
61+
blue = random.randint(0,255)
62+
63+
if (x % 6 == 0):
64+
# extend every 6 beat
65+
d.set_music_colour( d.MUSIC_TRANSITION_FADE, red, green, blue )
66+
time.sleep(2)
67+
else:
68+
# Jump!
69+
d.set_music_colour( d.MUSIC_TRANSITION_JUMP, red, green, blue )
70+
time.sleep(0.1) # the bulbs seem to get upset if updates are faster than 0.1s (100ms)
6271

6372
# Done
6473
print('\nDone')
65-
d.set_white()
74+
d.turn_off()

examples/bulb-scenes.py

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,38 @@
11
# TinyTuya Example
22
# -*- coding: utf-8 -*-
33
"""
4-
TinyTuya - RGB SmartBulb - Scene Test for Bulbs with DPS Index 25
4+
TinyTuya - RGB SmartBulb - Scene Test for Bulbs
55
66
Author: Jason A. Cox
77
For more information see https://github.com/jasonacox/tinytuya
88
99
"""
1010
import tinytuya
1111
import time
12+
import os
13+
1214

1315
DEVICEID = "01234567891234567890"
14-
DEVICEIP = "10.0.1.99"
15-
DEVICEKEY = "0123456789abcdef"
16-
DEVICEVERS = "3.3"
16+
DEVICEIP = "Auto" # Will try to discover the bulb on the network
17+
DEVICEKEY = "" # Leave blank to read from devices.json
18+
DEVICEVERS = 3.3 # Must be set correctly unless IP=Auto
19+
20+
# Check for environmental variables and always use those if available
21+
DEVICEID = os.getenv("DEVICEID", DEVICEID)
22+
DEVICEIP = os.getenv("DEVICEIP", DEVICEIP)
23+
DEVICEKEY = os.getenv("DEVICEKEY", DEVICEKEY)
24+
DEVICEVERS = os.getenv("DEVICEVERS", DEVICEVERS)
1725

1826
print("TinyTuya - Smart Bulb String Scenes Test [%s]\n" % tinytuya.__version__)
1927
print('TESTING: Device %s at %s with key %s version %s' %
2028
(DEVICEID, DEVICEIP, DEVICEKEY, DEVICEVERS))
2129

2230
# Connect to Tuya BulbDevice
23-
d = tinytuya.BulbDevice(DEVICEID, DEVICEIP, DEVICEKEY)
24-
d.set_version(float(DEVICEVERS)) # IMPORTANT to always set version
25-
# Keep socket connection open between commands
26-
d.set_socketPersistent(True)
31+
d = tinytuya.BulbDevice(DEVICEID, address=DEVICEIP, local_key=DEVICEKEY, version=DEVICEVERS, persist=True)
32+
33+
if (not DEVICEIP) or (DEVICEIP == 'Auto') or (not DEVICEKEY) or (not DEVICEVERS):
34+
print('Device %s found at %s with key %r version %s' %
35+
(d.id, d.address, d.local_key, d.version))
2736

2837
# Show status of device
2938
data = d.status()
@@ -33,33 +42,28 @@
3342
print('\nSetting bulb mode to Scenes')
3443
d.set_mode('scene')
3544

36-
# Determine bulb type - if it has index 25 it uses strings to set scene
37-
if("dps" in data):
38-
if("25" in data["dps"]):
39-
print('\n [Bulb Type B] String based scenes compatible smartbulb detected.')
45+
if d.bulb_has_capability(d.BULB_FEATURE_SCENE_DATA):
46+
print('\n String based scenes compatible smartbulb detected.')
47+
# Example: Color rotation
48+
print(' Switch to Scene 7 - Color Rotation')
49+
d.set_scene( 7, '464602000003e803e800000000464602007803e803e80000000046460200f003e803e800000000464602003d03e803e80000000046460200ae03e803e800000000464602011303e803e800000000')
50+
time.sleep(10)
4051

41-
# Example: Color rotation
42-
print(' Scene - Color Rotation')
43-
d.set_value(25, '07464602000003e803e800000000464602007803e803e80000000046460200f003e803e800000000464602003d03e803e80000000046460200ae03e803e800000000464602011303e803e800000000')
44-
time.sleep(10)
52+
# Example: Read scene
53+
print(' Switch to Scene 1 - Reading Light')
54+
d.set_scene( 1, '0e0d0000000000000003e803e8')
55+
time.sleep(5)
4556

46-
# Example: Read scene
47-
print(' Scene - Reading Light')
48-
d.set_value(25, '010e0d0000000000000003e803e8')
57+
# You can pull the scene strings from your smartbulb by running the async_send_receive.py script
58+
# and using the SmartLife app to change between scenes.
59+
else:
60+
print('\n Your smartbulb does not appear to support string based scenes.')
61+
# Rotate through numeric scenes
62+
for n in range(1, 5):
63+
print(' Scene - %d' % n)
64+
d.set_scene(n)
4965
time.sleep(5)
5066

51-
# You can pull the scene strings from your smartbulb by running the async_send_receive.py script
52-
# and using the SmartLife app to change between scenes.
53-
54-
else:
55-
print('\n [Bulb Type A] Your smartbulb does not appear to support string based scenes.')
56-
57-
# Rotate through numeric scenes
58-
for n in range(1, 4):
59-
print(' Scene - %d' % n)
60-
d.set_scene(n)
61-
time.sleep(5)
62-
6367
# Done
6468
print('\nDone')
65-
d.set_white()
69+
d.turn_off()

0 commit comments

Comments
 (0)