mirror of
				https://github.com/python-kasa/python-kasa.git
				synced 2025-10-31 04:31:54 +00:00 
			
		
		
		
	Add effect support for light strips (#293)
* Add effect support for KL430 * KL400 supports effects * Add KL400 fixture * Comments from review * actually commit the remove
This commit is contained in:
		
							
								
								
									
										21
									
								
								kasa/cli.py
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								kasa/cli.py
									
									
									
									
									
								
							| @@ -371,6 +371,27 @@ async def temperature(dev: SmartBulb, temperature: int, transition: int): | ||||
|         return await dev.set_color_temp(temperature, transition=transition) | ||||
|  | ||||
|  | ||||
| @cli.command() | ||||
| @click.argument("effect", type=click.STRING, default=None, required=False) | ||||
| @click.pass_context | ||||
| @pass_dev | ||||
| async def effect(dev, ctx, effect): | ||||
|     """Set an effect.""" | ||||
|     if not dev.has_effects: | ||||
|         click.echo("Device does not support effects") | ||||
|         return | ||||
|     if effect is None: | ||||
|         raise click.BadArgumentUsage( | ||||
|             f"Setting an effect requires a named built-in effect: {dev.effect_list}", | ||||
|             ctx, | ||||
|         ) | ||||
|     if effect not in dev.effect_list: | ||||
|         raise click.BadArgumentUsage(f"Effect must be one of: {dev.effect_list}", ctx) | ||||
|  | ||||
|     click.echo(f"Setting Effect: {effect}") | ||||
|     return await dev.set_effect(effect) | ||||
|  | ||||
|  | ||||
| @cli.command() | ||||
| @click.argument("h", type=click.IntRange(0, 360), default=None, required=False) | ||||
| @click.argument("s", type=click.IntRange(0, 100), default=None, required=False) | ||||
|   | ||||
							
								
								
									
										296
									
								
								kasa/effects.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								kasa/effects.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,296 @@ | ||||
| """Module for light strip effects (LB*, KL*, KB*).""" | ||||
|  | ||||
| from typing import List, cast | ||||
|  | ||||
| EFFECT_AURORA = { | ||||
|     "custom": 0, | ||||
|     "id": "xqUxDhbAhNLqulcuRMyPBmVGyTOyEMEu", | ||||
|     "brightness": 100, | ||||
|     "name": "Aurora", | ||||
|     "segments": [0], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "sequence", | ||||
|     "duration": 0, | ||||
|     "transition": 1500, | ||||
|     "direction": 4, | ||||
|     "spread": 7, | ||||
|     "repeat_times": 0, | ||||
|     "sequence": [[120, 100, 100], [240, 100, 100], [260, 100, 100], [280, 100, 100]], | ||||
| } | ||||
| EFFECT_BUBBLING_CAULDRON = { | ||||
|     "custom": 0, | ||||
|     "id": "tIwTRQBqJpeNKbrtBMFCgkdPTbAQGfRP", | ||||
|     "brightness": 100, | ||||
|     "name": "Bubbling Cauldron", | ||||
|     "segments": [0], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "random", | ||||
|     "hue_range": [100, 270], | ||||
|     "saturation_range": [80, 100], | ||||
|     "brightness_range": [50, 100], | ||||
|     "duration": 0, | ||||
|     "transition": 200, | ||||
|     "init_states": [[270, 100, 100]], | ||||
|     "fadeoff": 1000, | ||||
|     "random_seed": 24, | ||||
|     "backgrounds": [[270, 40, 50]], | ||||
| } | ||||
| EFFECT_CANDY_CANE = { | ||||
|     "custom": 0, | ||||
|     "id": "HCOttllMkNffeHjEOLEgrFJjbzQHoxEJ", | ||||
|     "brightness": 100, | ||||
|     "name": "Candy Cane", | ||||
|     "segments": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "sequence", | ||||
|     "duration": 700, | ||||
|     "transition": 500, | ||||
|     "direction": 1, | ||||
|     "spread": 1, | ||||
|     "repeat_times": 0, | ||||
|     "sequence": [ | ||||
|         [0, 0, 100], | ||||
|         [0, 0, 100], | ||||
|         [360, 81, 100], | ||||
|         [0, 0, 100], | ||||
|         [0, 0, 100], | ||||
|         [360, 81, 100], | ||||
|         [360, 81, 100], | ||||
|         [0, 0, 100], | ||||
|         [0, 0, 100], | ||||
|         [360, 81, 100], | ||||
|         [360, 81, 100], | ||||
|         [360, 81, 100], | ||||
|         [360, 81, 100], | ||||
|         [0, 0, 100], | ||||
|         [0, 0, 100], | ||||
|         [360, 81, 100], | ||||
|     ], | ||||
| } | ||||
| EFFECT_CHRISTMAS = { | ||||
|     "custom": 0, | ||||
|     "id": "bwTatyinOUajKrDwzMmqxxJdnInQUgvM", | ||||
|     "brightness": 100, | ||||
|     "name": "Christmas", | ||||
|     "segments": [0], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "random", | ||||
|     "hue_range": [136, 146], | ||||
|     "saturation_range": [90, 100], | ||||
|     "brightness_range": [50, 100], | ||||
|     "duration": 5000, | ||||
|     "transition": 0, | ||||
|     "init_states": [[136, 0, 100]], | ||||
|     "fadeoff": 2000, | ||||
|     "random_seed": 100, | ||||
|     "backgrounds": [[136, 98, 75], [136, 0, 0], [350, 0, 100], [350, 97, 94]], | ||||
| } | ||||
| EFFECT_FLICKER = { | ||||
|     "custom": 0, | ||||
|     "id": "bCTItKETDFfrKANolgldxfgOakaarARs", | ||||
|     "brightness": 100, | ||||
|     "name": "Flicker", | ||||
|     "segments": [1], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "random", | ||||
|     "hue_range": [30, 40], | ||||
|     "saturation_range": [100, 100], | ||||
|     "brightness_range": [50, 100], | ||||
|     "duration": 0, | ||||
|     "transition": 0, | ||||
|     "transition_range": [375, 500], | ||||
|     "init_states": [[30, 81, 80]], | ||||
| } | ||||
| EFFECT_HANUKKAH = { | ||||
|     "custom": 0, | ||||
|     "id": "CdLeIgiKcQrLKMINRPTMbylATulQewLD", | ||||
|     "brightness": 100, | ||||
|     "name": "Hanukkah", | ||||
|     "segments": [1], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "random", | ||||
|     "hue_range": [200, 210], | ||||
|     "saturation_range": [0, 100], | ||||
|     "brightness_range": [50, 100], | ||||
|     "duration": 1500, | ||||
|     "transition": 0, | ||||
|     "transition_range": [400, 500], | ||||
|     "init_states": [[35, 81, 80]], | ||||
| } | ||||
| EFFECT_HAUNTED_MANSION = { | ||||
|     "custom": 0, | ||||
|     "id": "oJnFHsVQzFUTeIOBAhMRfVeujmSauhjJ", | ||||
|     "brightness": 80, | ||||
|     "name": "Haunted Mansion", | ||||
|     "segments": [80], | ||||
|     "expansion_strategy": 2, | ||||
|     "enable": 1, | ||||
|     "type": "random", | ||||
|     "hue_range": [45, 45], | ||||
|     "saturation_range": [10, 10], | ||||
|     "brightness_range": [0, 80], | ||||
|     "duration": 0, | ||||
|     "transition": 0, | ||||
|     "transition_range": [50, 1500], | ||||
|     "init_states": [[45, 10, 100]], | ||||
|     "fadeoff": 200, | ||||
|     "random_seed": 1, | ||||
|     "backgrounds": [[45, 10, 100]], | ||||
| } | ||||
| EFFECT_ICICLE = { | ||||
|     "custom": 0, | ||||
|     "id": "joqVjlaTsgzmuQQBAlHRkkPAqkBUiqeb", | ||||
|     "brightness": 70, | ||||
|     "name": "Icicle", | ||||
|     "segments": [0], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "sequence", | ||||
|     "duration": 0, | ||||
|     "transition": 400, | ||||
|     "direction": 4, | ||||
|     "spread": 3, | ||||
|     "repeat_times": 0, | ||||
|     "sequence": [ | ||||
|         [190, 100, 70], | ||||
|         [190, 100, 70], | ||||
|         [190, 30, 50], | ||||
|         [190, 100, 70], | ||||
|         [190, 100, 70], | ||||
|     ], | ||||
| } | ||||
| EFFECT_LIGHTNING = { | ||||
|     "custom": 0, | ||||
|     "id": "ojqpUUxdGHoIugGPknrUcRoyJiItsjuE", | ||||
|     "brightness": 100, | ||||
|     "name": "Lightning", | ||||
|     "segments": [7, 20, 23, 32, 34, 35, 49, 65, 66, 74, 80], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "random", | ||||
|     "hue_range": [240, 240], | ||||
|     "saturation_range": [10, 11], | ||||
|     "brightness_range": [90, 100], | ||||
|     "duration": 0, | ||||
|     "transition": 50, | ||||
|     "init_states": [[240, 30, 100]], | ||||
|     "fadeoff": 150, | ||||
|     "random_seed": 600, | ||||
|     "backgrounds": [[200, 100, 100], [200, 50, 10], [210, 10, 50], [240, 10, 0]], | ||||
| } | ||||
| EFFECT_OCEAN = { | ||||
|     "custom": 0, | ||||
|     "id": "oJjUMosgEMrdumfPANKbkFmBcAdEQsPy", | ||||
|     "brightness": 30, | ||||
|     "name": "Ocean", | ||||
|     "segments": [0], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "sequence", | ||||
|     "duration": 0, | ||||
|     "transition": 2000, | ||||
|     "direction": 3, | ||||
|     "spread": 16, | ||||
|     "repeat_times": 0, | ||||
|     "sequence": [[198, 84, 30], [198, 70, 30], [198, 10, 30]], | ||||
| } | ||||
| EFFECT_RAINBOW = { | ||||
|     "custom": 0, | ||||
|     "id": "izRhLCQNcDzIKdpMPqSTtBMuAIoreAuT", | ||||
|     "brightness": 100, | ||||
|     "name": "Rainbow", | ||||
|     "segments": [0], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "sequence", | ||||
|     "duration": 0, | ||||
|     "transition": 1500, | ||||
|     "direction": 1, | ||||
|     "spread": 12, | ||||
|     "repeat_times": 0, | ||||
|     "sequence": [[0, 100, 100], [100, 100, 100], [200, 100, 100], [300, 100, 100]], | ||||
| } | ||||
| EFFECT_RAINDROP = { | ||||
|     "custom": 0, | ||||
|     "id": "QbDFwiSFmLzQenUOPnJrsGqyIVrJrRsl", | ||||
|     "brightness": 30, | ||||
|     "name": "Raindrop", | ||||
|     "segments": [0], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "random", | ||||
|     "hue_range": [200, 200], | ||||
|     "saturation_range": [10, 20], | ||||
|     "brightness_range": [10, 30], | ||||
|     "duration": 0, | ||||
|     "transition": 1000, | ||||
|     "init_states": [[200, 40, 100]], | ||||
|     "fadeoff": 1000, | ||||
|     "random_seed": 24, | ||||
|     "backgrounds": [[200, 40, 0]], | ||||
| } | ||||
| EFFECT_SPRING = { | ||||
|     "custom": 0, | ||||
|     "id": "URdUpEdQbnOOechDBPMkKrwhSupLyvAg", | ||||
|     "brightness": 100, | ||||
|     "name": "Spring", | ||||
|     "segments": [0], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "random", | ||||
|     "hue_range": [0, 90], | ||||
|     "saturation_range": [30, 100], | ||||
|     "brightness_range": [90, 100], | ||||
|     "duration": 600, | ||||
|     "transition": 0, | ||||
|     "transition_range": [2000, 6000], | ||||
|     "init_states": [[80, 30, 100]], | ||||
|     "fadeoff": 1000, | ||||
|     "random_seed": 20, | ||||
|     "backgrounds": [[130, 100, 40]], | ||||
| } | ||||
| EFFECT_VALENTINES = { | ||||
|     "custom": 0, | ||||
|     "id": "QglBhMShPHUAuxLqzNEefFrGiJwahOmz", | ||||
|     "brightness": 100, | ||||
|     "name": "Valentines", | ||||
|     "segments": [0], | ||||
|     "expansion_strategy": 1, | ||||
|     "enable": 1, | ||||
|     "type": "random", | ||||
|     "hue_range": [340, 340], | ||||
|     "saturation_range": [30, 40], | ||||
|     "brightness_range": [90, 100], | ||||
|     "duration": 600, | ||||
|     "transition": 2000, | ||||
|     "init_states": [[340, 30, 100]], | ||||
|     "fadeoff": 3000, | ||||
|     "random_seed": 100, | ||||
|     "backgrounds": [[340, 20, 50], [20, 50, 50], [0, 100, 50]], | ||||
| } | ||||
|  | ||||
| EFFECTS_LIST_V1 = [ | ||||
|     EFFECT_AURORA, | ||||
|     EFFECT_BUBBLING_CAULDRON, | ||||
|     EFFECT_CANDY_CANE, | ||||
|     EFFECT_CHRISTMAS, | ||||
|     EFFECT_FLICKER, | ||||
|     EFFECT_HANUKKAH, | ||||
|     EFFECT_HAUNTED_MANSION, | ||||
|     EFFECT_ICICLE, | ||||
|     EFFECT_LIGHTNING, | ||||
|     EFFECT_OCEAN, | ||||
|     EFFECT_RAINBOW, | ||||
|     EFFECT_RAINDROP, | ||||
|     EFFECT_SPRING, | ||||
|     EFFECT_VALENTINES, | ||||
| ] | ||||
|  | ||||
| EFFECT_NAMES_V1: List[str] = [cast(str, effect["name"]) for effect in EFFECTS_LIST_V1] | ||||
| EFFECT_MAPPING_V1 = {effect["name"]: effect for effect in EFFECTS_LIST_V1} | ||||
| @@ -172,6 +172,12 @@ class SmartBulb(SmartDevice): | ||||
|  | ||||
|         return light_state | ||||
|  | ||||
|     @property  # type: ignore | ||||
|     @requires_update | ||||
|     def has_effects(self) -> bool: | ||||
|         """Return True if the device supports effects.""" | ||||
|         return "lighting_effect_state" in self.sys_info | ||||
|  | ||||
|     async def get_light_details(self) -> Dict[str, int]: | ||||
|         """Return light details. | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,9 @@ | ||||
| """Module for light strips (KL430).""" | ||||
| from typing import Any, Dict | ||||
| from typing import Any, Dict, List, Optional | ||||
|  | ||||
| from .effects import EFFECT_MAPPING_V1, EFFECT_NAMES_V1 | ||||
| from .smartbulb import SmartBulb | ||||
| from .smartdevice import DeviceType, requires_update | ||||
| from .smartdevice import DeviceType, SmartDeviceException, requires_update | ||||
|  | ||||
|  | ||||
| class SmartLightStrip(SmartBulb): | ||||
| @@ -64,6 +65,16 @@ class SmartLightStrip(SmartBulb): | ||||
|         """ | ||||
|         return self.sys_info["lighting_effect_state"] | ||||
|  | ||||
|     @property  # type: ignore | ||||
|     @requires_update | ||||
|     def effect_list(self) -> Optional[List[str]]: | ||||
|         """Return built-in effects list. | ||||
|  | ||||
|         Example: | ||||
|             ['Aurora', 'Bubbling Cauldron', ...] | ||||
|         """ | ||||
|         return EFFECT_NAMES_V1 if self.has_effects else None | ||||
|  | ||||
|     @property  # type: ignore | ||||
|     @requires_update | ||||
|     def state_information(self) -> Dict[str, Any]: | ||||
| @@ -71,5 +82,37 @@ class SmartLightStrip(SmartBulb): | ||||
|         info = super().state_information | ||||
|  | ||||
|         info["Length"] = self.length | ||||
|         if self.has_effects: | ||||
|             info["Effect"] = self.effect["name"] | ||||
|  | ||||
|         return info | ||||
|  | ||||
|     @requires_update | ||||
|     async def set_effect( | ||||
|         self, | ||||
|         effect: str, | ||||
|     ) -> None: | ||||
|         """Set an effect on the device. | ||||
|  | ||||
|         :param str effect: The effect to set | ||||
|         """ | ||||
|         if effect not in EFFECT_MAPPING_V1: | ||||
|             raise SmartDeviceException(f"The effect {effect} is not a built in effect.") | ||||
|         await self.set_custom_effect(EFFECT_MAPPING_V1[effect]) | ||||
|  | ||||
|     @requires_update | ||||
|     async def set_custom_effect( | ||||
|         self, | ||||
|         effect_dict: Dict, | ||||
|     ) -> None: | ||||
|         """Set a custom effect on the device. | ||||
|  | ||||
|         :param str effect_dict: The custom effect dict to set | ||||
|         """ | ||||
|         if not self.has_effects: | ||||
|             raise SmartDeviceException("Bulb does not support effects.") | ||||
|         await self._query_helper( | ||||
|             "smartlife.iot.lighting_effect", | ||||
|             "set_lighting_effect", | ||||
|             effect_dict, | ||||
|         ) | ||||
|   | ||||
							
								
								
									
										57
									
								
								kasa/tests/fixtures/KL400L5(US)_1.0_1.0.8.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								kasa/tests/fixtures/KL400L5(US)_1.0_1.0.8.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| { | ||||
|     "smartlife.iot.common.emeter": { | ||||
|         "get_realtime": { | ||||
|             "err_code": 0, | ||||
|             "power_mw": 10800, | ||||
|             "total_wh": 1 | ||||
|         } | ||||
|     }, | ||||
|     "system": { | ||||
|         "get_sysinfo": { | ||||
|             "LEF": 0, | ||||
|             "active_mode": "none", | ||||
|             "alias": "Kl400", | ||||
|             "ctrl_protocols": { | ||||
|                 "name": "Linkie", | ||||
|                 "version": "1.0" | ||||
|             }, | ||||
|             "description": "Kasa Smart Light Strip, Multicolor", | ||||
|             "dev_state": "normal", | ||||
|             "deviceId": "0000000000000000000000000000000000000000", | ||||
|             "disco_ver": "1.0", | ||||
|             "err_code": 0, | ||||
|             "hwId": "00000000000000000000000000000000", | ||||
|             "hw_ver": "1.0", | ||||
|             "is_color": 1, | ||||
|             "is_dimmable": 1, | ||||
|             "is_factory": false, | ||||
|             "is_variable_color_temp": 0, | ||||
|             "latitude_i": 0, | ||||
|             "length": 1, | ||||
|             "light_state": { | ||||
|                 "brightness": 100, | ||||
|                 "color_temp": 6500, | ||||
|                 "hue": 0, | ||||
|                 "mode": "normal", | ||||
|                 "on_off": 1, | ||||
|                 "saturation": 0 | ||||
|             }, | ||||
|             "lighting_effect_state": { | ||||
|                 "brightness": 100, | ||||
|                 "custom": 0, | ||||
|                 "enable": 1, | ||||
|                 "id": "CdLeIgiKcQrLKMINRPTMbylATulQewLD", | ||||
|                 "name": "Hanukkah" | ||||
|             }, | ||||
|             "longitude_i": 0, | ||||
|             "mic_mac": "00:00:00:00:00:00", | ||||
|             "mic_type": "IOT.SMARTBULB", | ||||
|             "model": "KL400L5(US)", | ||||
|             "oemId": "00000000000000000000000000000000", | ||||
|             "preferred_state": [], | ||||
|             "rssi": -44, | ||||
|             "status": "new", | ||||
|             "sw_ver": "1.0.8 Build 211018 Rel.162056" | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										57
									
								
								kasa/tests/fixtures/KL430(US)_2.0_1.0.9.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								kasa/tests/fixtures/KL430(US)_2.0_1.0.9.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| { | ||||
|     "smartlife.iot.common.emeter": { | ||||
|         "get_realtime": { | ||||
|             "err_code": 0, | ||||
|             "power_mw": 11150, | ||||
|             "total_wh": 18 | ||||
|         } | ||||
|     }, | ||||
|     "system": { | ||||
|         "get_sysinfo": { | ||||
|             "LEF": 1, | ||||
|             "active_mode": "none", | ||||
|             "alias": "kl430 updated", | ||||
|             "ctrl_protocols": { | ||||
|                 "name": "Linkie", | ||||
|                 "version": "1.0" | ||||
|             }, | ||||
|             "description": "Kasa Smart Light Strip, Multicolor", | ||||
|             "dev_state": "normal", | ||||
|             "deviceId": "0000000000000000000000000000000000000000", | ||||
|             "disco_ver": "1.0", | ||||
|             "err_code": 0, | ||||
|             "hwId": "00000000000000000000000000000000", | ||||
|             "hw_ver": "2.0", | ||||
|             "is_color": 1, | ||||
|             "is_dimmable": 1, | ||||
|             "is_factory": false, | ||||
|             "is_variable_color_temp": 1, | ||||
|             "latitude_i": 0, | ||||
|             "length": 16, | ||||
|             "light_state": { | ||||
|                 "brightness": 100, | ||||
|                 "color_temp": 0, | ||||
|                 "hue": 194, | ||||
|                 "mode": "normal", | ||||
|                 "on_off": 1, | ||||
|                 "saturation": 50 | ||||
|             }, | ||||
|             "lighting_effect_state": { | ||||
|                 "brightness": 100, | ||||
|                 "custom": 0, | ||||
|                 "enable": 1, | ||||
|                 "id": "izRhLCQNcDzIKdpMPqSTtBMuAIoreAuT", | ||||
|                 "name": "Rainbow" | ||||
|             }, | ||||
|             "longitude_i": 0, | ||||
|             "mic_mac": "00:00:00:00:00:00", | ||||
|             "mic_type": "IOT.SMARTBULB", | ||||
|             "model": "KL430(US)", | ||||
|             "oemId": "00000000000000000000000000000000", | ||||
|             "preferred_state": [], | ||||
|             "rssi": -58, | ||||
|             "status": "new", | ||||
|             "sw_ver": "1.0.9 Build 210915 Rel.170534" | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -359,6 +359,10 @@ class FakeTransportProtocol(TPLinkSmartHomeProtocol): | ||||
|             self.proto["system"]["get_sysinfo"]["relay_state"] = 1 | ||||
|             self.proto["system"]["get_sysinfo"]["brightness"] = x["brightness"] | ||||
|  | ||||
|     def set_lighting_effect(self, effect, *args): | ||||
|         _LOGGER.debug("Setting light effect to %s", effect) | ||||
|         self.proto["system"]["get_sysinfo"]["lighting_effect_state"] = dict(effect) | ||||
|  | ||||
|     def transition_light_state(self, state_changes, *args): | ||||
|         _LOGGER.debug("Setting light state to %s", state_changes) | ||||
|         light_state = self.proto["system"]["get_sysinfo"]["light_state"] | ||||
| @@ -422,6 +426,9 @@ class FakeTransportProtocol(TPLinkSmartHomeProtocol): | ||||
|             "get_light_state": light_state, | ||||
|             "transition_light_state": transition_light_state, | ||||
|         }, | ||||
|         "smartlife.iot.lighting_effect": { | ||||
|             "set_lighting_effect": set_lighting_effect, | ||||
|         }, | ||||
|         # lightstrip follows the same payloads but uses different module & method | ||||
|         "smartlife.iot.lightStrip": { | ||||
|             "set_light_state": transition_light_state, | ||||
|   | ||||
| @@ -1,4 +1,7 @@ | ||||
| import pytest | ||||
|  | ||||
| from kasa import DeviceType, SmartLightStrip | ||||
| from kasa.exceptions import SmartDeviceException | ||||
|  | ||||
| from .conftest import lightstrip, pytestmark | ||||
|  | ||||
| @@ -15,3 +18,19 @@ async def test_lightstrip_effect(dev: SmartLightStrip): | ||||
|     assert isinstance(dev.effect, dict) | ||||
|     for k in ["brightness", "custom", "enable", "id", "name"]: | ||||
|         assert k in dev.effect | ||||
|  | ||||
|  | ||||
| @lightstrip | ||||
| async def test_effects_lightstrip_set_effect(dev: SmartLightStrip): | ||||
|     with pytest.raises(SmartDeviceException): | ||||
|         await dev.set_effect("Not real") | ||||
|  | ||||
|     await dev.set_effect("Candy Cane") | ||||
|     assert dev.effect["name"] == "Candy Cane" | ||||
|     assert dev.state_information["Effect"] == "Candy Cane" | ||||
|  | ||||
|  | ||||
| @lightstrip | ||||
| async def test_effects_lightstrip_has_effects(dev: SmartLightStrip): | ||||
|     assert dev.has_effects is True | ||||
|     assert dev.effect_list | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 J. Nick Koston
					J. Nick Koston