HueBLE 2.2.2__tar.gz → 2.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hueble-2.2.2 → hueble-2.2.4}/HueBLE.egg-info/PKG-INFO +39 -2
- {hueble-2.2.2 → hueble-2.2.4}/HueBLE.py +116 -16
- {hueble-2.2.2 → hueble-2.2.4}/PKG-INFO +39 -2
- {hueble-2.2.2 → hueble-2.2.4}/README.md +38 -1
- {hueble-2.2.2 → hueble-2.2.4}/pyproject.toml +1 -1
- {hueble-2.2.2 → hueble-2.2.4}/tests/test_HueBLE.py +43 -0
- {hueble-2.2.2 → hueble-2.2.4}/HueBLE.egg-info/SOURCES.txt +0 -0
- {hueble-2.2.2 → hueble-2.2.4}/HueBLE.egg-info/dependency_links.txt +0 -0
- {hueble-2.2.2 → hueble-2.2.4}/HueBLE.egg-info/requires.txt +0 -0
- {hueble-2.2.2 → hueble-2.2.4}/HueBLE.egg-info/top_level.txt +0 -0
- {hueble-2.2.2 → hueble-2.2.4}/LICENSE.txt +0 -0
- {hueble-2.2.2 → hueble-2.2.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: HueBLE
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.4
|
|
4
4
|
Summary: Python module for controlling and monitoring Bluetooth Philips Hue bulbs
|
|
5
5
|
Author-email: Harvey Lelliott <harveylelliott@duck.com>
|
|
6
6
|
License: MIT License
|
|
@@ -64,7 +64,8 @@ Python module for controlling Bluetooth Philips Hue lights.
|
|
|
64
64
|
|
|
65
65
|
This Python module enables you to control Philips Hue Bluetooth lights directly
|
|
66
66
|
from your computer, without the need for a Hue bridge or ZigBee dongle.
|
|
67
|
-
It leverages the Bleak library to interact with Bluetooth Philips Hue lights
|
|
67
|
+
It leverages the Bleak library to interact with Bluetooth Philips Hue lights including
|
|
68
|
+
the smart plugs.
|
|
68
69
|
|
|
69
70
|
|
|
70
71
|
## Features
|
|
@@ -73,10 +74,13 @@ It leverages the Bleak library to interact with Bluetooth Philips Hue lights.
|
|
|
73
74
|
- 🌗 Brightness control
|
|
74
75
|
- 🌡️ Colour temp control
|
|
75
76
|
- 🌈 XY colour control
|
|
77
|
+
- ✨ Built-in effects with custom colour and speed
|
|
78
|
+
- ⏱️ Custom transitions, including instant changes
|
|
76
79
|
- ❔ Light state (power/brightness/temp/colour)
|
|
77
80
|
- ⚙️ Light configuration (name)
|
|
78
81
|
- 📊 Light metadata (manufacturer/model/zigbee address)
|
|
79
82
|
- 🤜 Supports push & polling models
|
|
83
|
+
- 🔌 Hue smart plug support
|
|
80
84
|
- 🔂 Simple structure
|
|
81
85
|
- 📜 Mediocre documentation
|
|
82
86
|
- ✔️ More emojis than strictly necessary
|
|
@@ -177,6 +181,39 @@ if __name__ == "__main__":
|
|
|
177
181
|
```
|
|
178
182
|
|
|
179
183
|
|
|
184
|
+
### Transitions
|
|
185
|
+
|
|
186
|
+
Power, brightness, colour temperature and colour changes can use a custom
|
|
187
|
+
transition time.
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
await light.set_power(True, transition_ms=0)
|
|
191
|
+
await light.set_brightness(254, transition_ms=100)
|
|
192
|
+
await light.set_colour_temp(250, transition_ms=400)
|
|
193
|
+
await light.set_colour_xy(0.3, 0.4, transition_ms=200)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
`transition_ms=0` makes the change instant. Transition times use 100 ms steps.
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
### Effects
|
|
200
|
+
|
|
201
|
+
HueBLE supports Hue effects such as Candle, Fireplace, Sunrise and Sunset.
|
|
202
|
+
Effects can use a custom colour, brightness and speed.
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
await light.set_colour_effect(
|
|
206
|
+
0.30,
|
|
207
|
+
0.14,
|
|
208
|
+
254,
|
|
209
|
+
HueBLE.EffectType.CANDLE,
|
|
210
|
+
128,
|
|
211
|
+
)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Effect speed ranges from `0` (slowest) to `255` (fastest).
|
|
215
|
+
|
|
216
|
+
|
|
180
217
|
### Demo program
|
|
181
218
|
|
|
182
219
|
A more fully featured demo program can be found in ``` examples/demo.py ``` which demonstrates all of the implemented features.
|
|
@@ -17,7 +17,6 @@ from struct import pack, unpack
|
|
|
17
17
|
from typing import Callable
|
|
18
18
|
from enum import Enum
|
|
19
19
|
|
|
20
|
-
|
|
21
20
|
#: String containing manufacturer. Handle 15.
|
|
22
21
|
UUID_MANUFACTURER = "00002a29-0000-1000-8000-00805f9b34fb"
|
|
23
22
|
|
|
@@ -130,6 +129,10 @@ UNPACK_EFFECT_API_TEMPERATURE_WITH_EFFECT = "<xxBxxBxxHxxBxxB"
|
|
|
130
129
|
#: data stream unpack format string for decoding plain temperature without effect (effect API)
|
|
131
130
|
UNPACK_EFFECT_API_TEMPERATURE_WITHOUT_EFFECT = "<xxBxxBxxH"
|
|
132
131
|
|
|
132
|
+
#: data stream unpack format string for decoding the onoff-only report (effect API),
|
|
133
|
+
#: sent by devices that only support on/off, e.g. the Hue smart plug
|
|
134
|
+
UNPACK_EFFECT_API_ONOFF_ONLY = "<xxB"
|
|
135
|
+
|
|
133
136
|
|
|
134
137
|
_LOGGER = logging.getLogger(__name__)
|
|
135
138
|
|
|
@@ -140,14 +143,23 @@ class EffectType(Enum):
|
|
|
140
143
|
CANDLE = 0x01
|
|
141
144
|
FIREPLACE = 0x02
|
|
142
145
|
PRISM = 0x03
|
|
146
|
+
SUNRISE = 0x09
|
|
143
147
|
SPARKLE = 0x0A
|
|
144
148
|
OPAL = 0x0B
|
|
145
149
|
GLISTEN = 0x0C
|
|
150
|
+
SUNSET = 0x0D
|
|
146
151
|
UNDERWATER = 0x0E
|
|
147
152
|
COSMOS = 0x0F
|
|
148
153
|
SUNBEAM = 0x10
|
|
149
154
|
ENCHANT = 0x11
|
|
150
155
|
|
|
156
|
+
@classmethod
|
|
157
|
+
def _missing_(cls, value):
|
|
158
|
+
_LOGGER.warning(
|
|
159
|
+
f"Unknown effect type: '{value}' reported by light, using default of none!"
|
|
160
|
+
)
|
|
161
|
+
return cls.NONE
|
|
162
|
+
|
|
151
163
|
|
|
152
164
|
#: EFFECT_COMMANDS (hex string) for the Effect Characteristic endpoint containing one byte id and one byte data length
|
|
153
165
|
class EffectCommands(Enum):
|
|
@@ -155,10 +167,26 @@ class EffectCommands(Enum):
|
|
|
155
167
|
BRIGHTNESS = "0201"
|
|
156
168
|
TEMPERATURE = "0302"
|
|
157
169
|
COLOURXY = "0404"
|
|
170
|
+
TRANSITION_TIME = "0502"
|
|
158
171
|
EFFECT = "0601"
|
|
159
172
|
EFFECT_SPEED = "0801"
|
|
160
173
|
|
|
161
174
|
|
|
175
|
+
def _transition_tlv(transition_ms: int) -> bytes:
|
|
176
|
+
if not isinstance(transition_ms, int):
|
|
177
|
+
raise TypeError("transition_ms must be an integer")
|
|
178
|
+
if transition_ms < 0 or transition_ms % 100 != 0:
|
|
179
|
+
raise ValueError("transition_ms must be a non-negative multiple of 100")
|
|
180
|
+
|
|
181
|
+
units = transition_ms // 100
|
|
182
|
+
if units > 0xFFFF:
|
|
183
|
+
raise ValueError("transition_ms is too large")
|
|
184
|
+
|
|
185
|
+
return bytes.fromhex(EffectCommands.TRANSITION_TIME.value) + units.to_bytes(
|
|
186
|
+
2, "little"
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
|
|
162
190
|
class HueBleError(Exception):
|
|
163
191
|
"""
|
|
164
192
|
Base exception of HueBLE.
|
|
@@ -469,10 +497,19 @@ class HueBleLight(object):
|
|
|
469
497
|
f"""Light "{self.name}" has informed us of a new"""
|
|
470
498
|
f""" colour temp state of ({self.colour_temp})"""
|
|
471
499
|
)
|
|
500
|
+
elif len(data) == 3:
|
|
501
|
+
# device only reports its onoff value (e.g. smart plug)
|
|
502
|
+
onoff = unpack(UNPACK_EFFECT_API_ONOFF_ONLY, data)[0]
|
|
503
|
+
self._power_on = bool(onoff)
|
|
504
|
+
|
|
505
|
+
_LOGGER.debug(
|
|
506
|
+
f"""Light "{self.name}" has informed us of a new"""
|
|
507
|
+
f""" power state ({self._power_on})"""
|
|
508
|
+
)
|
|
472
509
|
else:
|
|
473
510
|
# so far unkown
|
|
474
511
|
_LOGGER.warning(
|
|
475
|
-
"unrecognized effect response with length {len(data)}: {data}"
|
|
512
|
+
f"unrecognized effect response with length {len(data)}: {data}"
|
|
476
513
|
)
|
|
477
514
|
|
|
478
515
|
if effect_state_changed:
|
|
@@ -1205,6 +1242,11 @@ class HueBleLight(object):
|
|
|
1205
1242
|
if write_state:
|
|
1206
1243
|
self._colour_temp = colour_temp
|
|
1207
1244
|
self._power_on = bool(onoff)
|
|
1245
|
+
elif len(buf) == 3:
|
|
1246
|
+
# device only reports its onoff value (e.g. smart plug)
|
|
1247
|
+
onoff = unpack(UNPACK_EFFECT_API_ONOFF_ONLY, buf)[0]
|
|
1248
|
+
if write_state:
|
|
1249
|
+
self._power_on = bool(onoff)
|
|
1208
1250
|
else:
|
|
1209
1251
|
# so far unkown
|
|
1210
1252
|
_LOGGER.warning(
|
|
@@ -1217,28 +1259,77 @@ class HueBleLight(object):
|
|
|
1217
1259
|
"""Sets the name of the light. Not tested, use at own risk."""
|
|
1218
1260
|
await self._write_gatt(UUID_NAME, str.encode(name))
|
|
1219
1261
|
|
|
1220
|
-
async def set_power(self, on: bool):
|
|
1262
|
+
async def set_power(self, on: bool, transition_ms: int | None = None):
|
|
1221
1263
|
"""Sets the power state of the light."""
|
|
1222
|
-
|
|
1264
|
+
if transition_ms is None:
|
|
1265
|
+
await self._write_gatt(UUID_POWER, bytes([1 if on else 0]))
|
|
1266
|
+
return
|
|
1267
|
+
|
|
1268
|
+
buf = (
|
|
1269
|
+
bytes.fromhex(EffectCommands.ONOFF.value)
|
|
1270
|
+
+ bytes([1 if on else 0])
|
|
1271
|
+
+ _transition_tlv(transition_ms)
|
|
1272
|
+
)
|
|
1273
|
+
await self._write_gatt(UUID_EFFECTS, buf)
|
|
1223
1274
|
|
|
1224
|
-
async def set_brightness(
|
|
1275
|
+
async def set_brightness(
|
|
1276
|
+
self, brightness: int, transition_ms: int | None = None
|
|
1277
|
+
):
|
|
1225
1278
|
"""Sets the brightness from an integer between 0 and 255"""
|
|
1226
|
-
|
|
1279
|
+
brightness = max(min(brightness, 254), 1)
|
|
1280
|
+
if transition_ms is None:
|
|
1281
|
+
await self._write_gatt(UUID_BRIGHTNESS, bytes([brightness]))
|
|
1282
|
+
return
|
|
1227
1283
|
|
|
1228
|
-
|
|
1284
|
+
buf = (
|
|
1285
|
+
bytes.fromhex(EffectCommands.BRIGHTNESS.value)
|
|
1286
|
+
+ bytes([brightness])
|
|
1287
|
+
+ _transition_tlv(transition_ms)
|
|
1288
|
+
)
|
|
1289
|
+
await self._write_gatt(UUID_EFFECTS, buf)
|
|
1290
|
+
|
|
1291
|
+
async def set_colour_temp(
|
|
1292
|
+
self, colour_temp: int, transition_ms: int | None = None
|
|
1293
|
+
):
|
|
1229
1294
|
"""Sets the temperature from an int between 153 and 500.
|
|
1230
1295
|
Uses mireds."""
|
|
1231
1296
|
temp = max(min(int(colour_temp), 500), 153)
|
|
1232
|
-
|
|
1233
|
-
|
|
1297
|
+
data = temp.to_bytes(2, "little")
|
|
1298
|
+
if transition_ms is None:
|
|
1299
|
+
await self._write_gatt(UUID_TEMPERATURE, data)
|
|
1300
|
+
return
|
|
1301
|
+
|
|
1302
|
+
buf = (
|
|
1303
|
+
bytes.fromhex(EffectCommands.TEMPERATURE.value)
|
|
1304
|
+
+ data
|
|
1305
|
+
+ _transition_tlv(transition_ms)
|
|
1306
|
+
)
|
|
1307
|
+
await self._write_gatt(UUID_EFFECTS, buf)
|
|
1234
1308
|
|
|
1235
|
-
async def set_colour_xy(
|
|
1309
|
+
async def set_colour_xy(
|
|
1310
|
+
self, x: float, y: float, transition_ms: int | None = None
|
|
1311
|
+
):
|
|
1236
1312
|
"""Sets the XY colour coordinates from floats between 0.0 and 1.0."""
|
|
1237
|
-
|
|
1238
|
-
|
|
1313
|
+
data = pack("<HH", int(x * 0xFFFF), int(y * 0xFFFF))
|
|
1314
|
+
if transition_ms is None:
|
|
1315
|
+
await self._write_gatt(UUID_XY_COLOUR, data)
|
|
1316
|
+
return
|
|
1317
|
+
|
|
1318
|
+
buf = (
|
|
1319
|
+
bytes.fromhex(EffectCommands.COLOURXY.value)
|
|
1320
|
+
+ data
|
|
1321
|
+
+ _transition_tlv(transition_ms)
|
|
1322
|
+
)
|
|
1323
|
+
await self._write_gatt(UUID_EFFECTS, buf)
|
|
1239
1324
|
|
|
1240
1325
|
async def set_colour_effect(
|
|
1241
|
-
self,
|
|
1326
|
+
self,
|
|
1327
|
+
x: float,
|
|
1328
|
+
y: float,
|
|
1329
|
+
brightness: int,
|
|
1330
|
+
effect: EffectType,
|
|
1331
|
+
effect_speed: int,
|
|
1332
|
+
transition_ms: int | None = None,
|
|
1242
1333
|
):
|
|
1243
1334
|
"""
|
|
1244
1335
|
Sets XY colour, brightness, effect and effect speed.
|
|
@@ -1262,7 +1353,7 @@ class HueBleLight(object):
|
|
|
1262
1353
|
bytes.fromhex(EffectCommands.EFFECT.value),
|
|
1263
1354
|
max(min(effect.value, 254), 1),
|
|
1264
1355
|
bytes.fromhex(EffectCommands.EFFECT_SPEED.value),
|
|
1265
|
-
max(min(effect_speed,
|
|
1356
|
+
max(min(effect_speed, 255), 0),
|
|
1266
1357
|
)
|
|
1267
1358
|
else:
|
|
1268
1359
|
# if no effect is selected we can just operate in colourxy mode and ommit the effect data in the transfer
|
|
@@ -1276,10 +1367,17 @@ class HueBleLight(object):
|
|
|
1276
1367
|
int(x * 0xFFFF),
|
|
1277
1368
|
int(y * 0xFFFF),
|
|
1278
1369
|
)
|
|
1370
|
+
if transition_ms is not None:
|
|
1371
|
+
buf += _transition_tlv(transition_ms)
|
|
1279
1372
|
await self._write_gatt(UUID_EFFECTS, buf)
|
|
1280
1373
|
|
|
1281
1374
|
async def set_temperature_effect(
|
|
1282
|
-
self,
|
|
1375
|
+
self,
|
|
1376
|
+
colour_temp: int,
|
|
1377
|
+
brightness: int,
|
|
1378
|
+
effect: EffectType,
|
|
1379
|
+
effect_speed: int,
|
|
1380
|
+
transition_ms: int | None = None,
|
|
1283
1381
|
):
|
|
1284
1382
|
"""
|
|
1285
1383
|
Sets colour temperature, brightness, effect and effect speed.
|
|
@@ -1303,7 +1401,7 @@ class HueBleLight(object):
|
|
|
1303
1401
|
bytes.fromhex(EffectCommands.EFFECT.value),
|
|
1304
1402
|
max(min(effect.value, 254), 1),
|
|
1305
1403
|
bytes.fromhex(EffectCommands.EFFECT_SPEED.value),
|
|
1306
|
-
max(min(effect_speed,
|
|
1404
|
+
max(min(effect_speed, 255), 0),
|
|
1307
1405
|
)
|
|
1308
1406
|
else:
|
|
1309
1407
|
# if no effect is selected we can just operate in colourxy mode and ommit the effect data in the transfer
|
|
@@ -1316,6 +1414,8 @@ class HueBleLight(object):
|
|
|
1316
1414
|
bytes.fromhex(EffectCommands.TEMPERATURE.value),
|
|
1317
1415
|
temperature,
|
|
1318
1416
|
)
|
|
1417
|
+
if transition_ms is not None:
|
|
1418
|
+
buf += _transition_tlv(transition_ms)
|
|
1319
1419
|
await self._write_gatt(UUID_EFFECTS, buf)
|
|
1320
1420
|
|
|
1321
1421
|
@property
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: HueBLE
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.4
|
|
4
4
|
Summary: Python module for controlling and monitoring Bluetooth Philips Hue bulbs
|
|
5
5
|
Author-email: Harvey Lelliott <harveylelliott@duck.com>
|
|
6
6
|
License: MIT License
|
|
@@ -64,7 +64,8 @@ Python module for controlling Bluetooth Philips Hue lights.
|
|
|
64
64
|
|
|
65
65
|
This Python module enables you to control Philips Hue Bluetooth lights directly
|
|
66
66
|
from your computer, without the need for a Hue bridge or ZigBee dongle.
|
|
67
|
-
It leverages the Bleak library to interact with Bluetooth Philips Hue lights
|
|
67
|
+
It leverages the Bleak library to interact with Bluetooth Philips Hue lights including
|
|
68
|
+
the smart plugs.
|
|
68
69
|
|
|
69
70
|
|
|
70
71
|
## Features
|
|
@@ -73,10 +74,13 @@ It leverages the Bleak library to interact with Bluetooth Philips Hue lights.
|
|
|
73
74
|
- 🌗 Brightness control
|
|
74
75
|
- 🌡️ Colour temp control
|
|
75
76
|
- 🌈 XY colour control
|
|
77
|
+
- ✨ Built-in effects with custom colour and speed
|
|
78
|
+
- ⏱️ Custom transitions, including instant changes
|
|
76
79
|
- ❔ Light state (power/brightness/temp/colour)
|
|
77
80
|
- ⚙️ Light configuration (name)
|
|
78
81
|
- 📊 Light metadata (manufacturer/model/zigbee address)
|
|
79
82
|
- 🤜 Supports push & polling models
|
|
83
|
+
- 🔌 Hue smart plug support
|
|
80
84
|
- 🔂 Simple structure
|
|
81
85
|
- 📜 Mediocre documentation
|
|
82
86
|
- ✔️ More emojis than strictly necessary
|
|
@@ -177,6 +181,39 @@ if __name__ == "__main__":
|
|
|
177
181
|
```
|
|
178
182
|
|
|
179
183
|
|
|
184
|
+
### Transitions
|
|
185
|
+
|
|
186
|
+
Power, brightness, colour temperature and colour changes can use a custom
|
|
187
|
+
transition time.
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
await light.set_power(True, transition_ms=0)
|
|
191
|
+
await light.set_brightness(254, transition_ms=100)
|
|
192
|
+
await light.set_colour_temp(250, transition_ms=400)
|
|
193
|
+
await light.set_colour_xy(0.3, 0.4, transition_ms=200)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
`transition_ms=0` makes the change instant. Transition times use 100 ms steps.
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
### Effects
|
|
200
|
+
|
|
201
|
+
HueBLE supports Hue effects such as Candle, Fireplace, Sunrise and Sunset.
|
|
202
|
+
Effects can use a custom colour, brightness and speed.
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
await light.set_colour_effect(
|
|
206
|
+
0.30,
|
|
207
|
+
0.14,
|
|
208
|
+
254,
|
|
209
|
+
HueBLE.EffectType.CANDLE,
|
|
210
|
+
128,
|
|
211
|
+
)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Effect speed ranges from `0` (slowest) to `255` (fastest).
|
|
215
|
+
|
|
216
|
+
|
|
180
217
|
### Demo program
|
|
181
218
|
|
|
182
219
|
A more fully featured demo program can be found in ``` examples/demo.py ``` which demonstrates all of the implemented features.
|
|
@@ -15,7 +15,8 @@ Python module for controlling Bluetooth Philips Hue lights.
|
|
|
15
15
|
|
|
16
16
|
This Python module enables you to control Philips Hue Bluetooth lights directly
|
|
17
17
|
from your computer, without the need for a Hue bridge or ZigBee dongle.
|
|
18
|
-
It leverages the Bleak library to interact with Bluetooth Philips Hue lights
|
|
18
|
+
It leverages the Bleak library to interact with Bluetooth Philips Hue lights including
|
|
19
|
+
the smart plugs.
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
## Features
|
|
@@ -24,10 +25,13 @@ It leverages the Bleak library to interact with Bluetooth Philips Hue lights.
|
|
|
24
25
|
- 🌗 Brightness control
|
|
25
26
|
- 🌡️ Colour temp control
|
|
26
27
|
- 🌈 XY colour control
|
|
28
|
+
- ✨ Built-in effects with custom colour and speed
|
|
29
|
+
- ⏱️ Custom transitions, including instant changes
|
|
27
30
|
- ❔ Light state (power/brightness/temp/colour)
|
|
28
31
|
- ⚙️ Light configuration (name)
|
|
29
32
|
- 📊 Light metadata (manufacturer/model/zigbee address)
|
|
30
33
|
- 🤜 Supports push & polling models
|
|
34
|
+
- 🔌 Hue smart plug support
|
|
31
35
|
- 🔂 Simple structure
|
|
32
36
|
- 📜 Mediocre documentation
|
|
33
37
|
- ✔️ More emojis than strictly necessary
|
|
@@ -128,6 +132,39 @@ if __name__ == "__main__":
|
|
|
128
132
|
```
|
|
129
133
|
|
|
130
134
|
|
|
135
|
+
### Transitions
|
|
136
|
+
|
|
137
|
+
Power, brightness, colour temperature and colour changes can use a custom
|
|
138
|
+
transition time.
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
await light.set_power(True, transition_ms=0)
|
|
142
|
+
await light.set_brightness(254, transition_ms=100)
|
|
143
|
+
await light.set_colour_temp(250, transition_ms=400)
|
|
144
|
+
await light.set_colour_xy(0.3, 0.4, transition_ms=200)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
`transition_ms=0` makes the change instant. Transition times use 100 ms steps.
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
### Effects
|
|
151
|
+
|
|
152
|
+
HueBLE supports Hue effects such as Candle, Fireplace, Sunrise and Sunset.
|
|
153
|
+
Effects can use a custom colour, brightness and speed.
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
await light.set_colour_effect(
|
|
157
|
+
0.30,
|
|
158
|
+
0.14,
|
|
159
|
+
254,
|
|
160
|
+
HueBLE.EffectType.CANDLE,
|
|
161
|
+
128,
|
|
162
|
+
)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Effect speed ranges from `0` (slowest) to `255` (fastest).
|
|
166
|
+
|
|
167
|
+
|
|
131
168
|
### Demo program
|
|
132
169
|
|
|
133
170
|
A more fully featured demo program can be found in ``` examples/demo.py ``` which demonstrates all of the implemented features.
|
|
@@ -370,6 +370,49 @@ async def test_commands(
|
|
|
370
370
|
},
|
|
371
371
|
id="temperature_effect",
|
|
372
372
|
),
|
|
373
|
+
pytest.param(
|
|
374
|
+
{
|
|
375
|
+
HueBLE.UUID_MANUFACTURER: "Philippe Hue".encode(),
|
|
376
|
+
HueBLE.UUID_MODEL: "Fancy new light".encode(),
|
|
377
|
+
HueBLE.UUID_FW_VERSION: "1.7.10".encode(),
|
|
378
|
+
HueBLE.UUID_ZIGBEE_ADDRESS: bytes.fromhex("00010203040506070809"),
|
|
379
|
+
HueBLE.UUID_NAME: "L A M P".encode(),
|
|
380
|
+
HueBLE.UUID_EFFECTS: bytes.fromhex("01010102014503022c01060115080138"),
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"manufacturer": "Philippe Hue",
|
|
384
|
+
"model": "Fancy new light",
|
|
385
|
+
"firmware": "1.7.10",
|
|
386
|
+
"zigbee_address": "00:01:02:03:04:05:06:07:08:09",
|
|
387
|
+
"name_in_app": "L A M P",
|
|
388
|
+
"power_state": True,
|
|
389
|
+
"brightness": 69,
|
|
390
|
+
"colour_temp": 300,
|
|
391
|
+
"colour_xy": None,
|
|
392
|
+
"effect": (HueBLE.EffectType.NONE, 56),
|
|
393
|
+
},
|
|
394
|
+
id="unknown_effect",
|
|
395
|
+
),
|
|
396
|
+
pytest.param(
|
|
397
|
+
{
|
|
398
|
+
HueBLE.UUID_MANUFACTURER: "Philippe Hue".encode(),
|
|
399
|
+
HueBLE.UUID_MODEL: "Fancy new light".encode(),
|
|
400
|
+
HueBLE.UUID_FW_VERSION: "1.7.10".encode(),
|
|
401
|
+
HueBLE.UUID_ZIGBEE_ADDRESS: bytes.fromhex("00010203040506070809"),
|
|
402
|
+
HueBLE.UUID_NAME: "L A M P".encode(),
|
|
403
|
+
# on/off-only device (e.g. smart plug): only the onoff TLV is reported
|
|
404
|
+
HueBLE.UUID_EFFECTS: bytes.fromhex("010100"),
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
"manufacturer": "Philippe Hue",
|
|
408
|
+
"model": "Fancy new light",
|
|
409
|
+
"firmware": "1.7.10",
|
|
410
|
+
"zigbee_address": "00:01:02:03:04:05:06:07:08:09",
|
|
411
|
+
"name_in_app": "L A M P",
|
|
412
|
+
"power_state": False,
|
|
413
|
+
},
|
|
414
|
+
id="effect_onoff_only",
|
|
415
|
+
),
|
|
373
416
|
],
|
|
374
417
|
)
|
|
375
418
|
async def test_poll_state(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|