def execute_action(message): logging.debug(str(message)) bulb = Bulb(message['dest'], 55443, 'smooth', 500, True,type=message['model']) command_list= message['command'].split(' ') if command_list[0] == 'turn': if command_list[1] == 'on': bulb.turn_on() else: bulb.turn_off() elif command_list[0] == 'stop': bulb.stop_flow() elif command_list[0] == 'rgb': red, green, blue = utils.hex_color_to_rgb(message['option']) bulb.set_rgb(red, green, blue) elif command_list[0] == 'toggle': bulb.toggle() elif command_list[0] == 'brightness': bulb.set_brightness(int(message['option'])) elif command_list[0] == 'temperature': if len(command_list)>1: bulb.set_color_temp(int(command_list[1])) else: bulb.set_color_temp(int(message['option'])) elif command_list[0] == 'flow': flow_params = message['option'].split(' ') translist = flow_params[2].split('-') list =[] for transition in translist: elements = transition.split(',') if elements[0] in globals.DICT_MAPPING_YEELIGHT: effect = globals.DICT_MAPPING_YEELIGHT[elements[0]] if elements[0] == 'hsv': list.append(effect(int(elements[1]),int(elements[2]),int(elements[3]),int(elements[4]))) elif elements[0] == 'rgb' : list.append(effect(int(elements[1]),int(elements[2]),int(elements[3]),int(elements[4]),int(elements[5]))) elif elements[0] == 'temp' : list.append(effect(int(elements[1]),int(elements[2]),int(elements[3]))) else: list.append(effect(int(elements[1]))) else: logging.debug("Not an effect") if flow_params[1] == 'recover': flow = Flow(int(flow_params[0]),Flow.actions.recover,list) elif flow_params[1] == 'stay' : flow = Flow(int(flow_params[0]),Flow.actions.stay,list) else: flow = Flow(int(flow_params[0]),Flow.actions.off,list) bulb.start_flow(flow) elif command_list[0] == 'cron': bulb.cron_add(enums.CronType.off, int(message['option'])) elif command_list[0] == 'hsv': hsv_option = message['option'].split(' ') bulb.set_hsv(int(hsv_option[0]), int(hsv_option[1])) t = threading.Timer(2, refresh,args=(message,)) t.start() return
def strobe(): """ Rapid flashing on and off. :returns: An infinite Flow consisting of 2 transitions. :rtype: Flow """ return Flow(count=0, action=Action.recover, transitions=transitions.strobe())
def temp(): """ Slowly-changing color temperature. :returns: An infinite Flow consisting of 2 transitions. :rtype: Flow """ return Flow(count=0, action=Action.recover, transitions=transitions.temp())
def disco(bpm=120): """ Color changes to the beat. :param int bpm: The beats per minute to pulse to. :returns: An infinite Flow consisting of 8 transitions. :rtype: Flow """ return Flow(count=0, action=Action.recover, transitions=transitions.disco(bpm))
def alarm(duration=250): """ Red alarm; flashing bright red to dark red. :param int duration: The duration between hi/lo brightness,in milliseconds. :returns: An infinite Flow consisting of 2 transitions. :rtype: Flow """ return Flow(count=0, action=Action.recover, transitions=transitions.alarm(duration))
def strobe_color(brightness=100): """ Rapid flashing colors. :param int brightness: The brightness of the transition. :returns: An infinite Flow consisting of 6 transitions. :rtype: Flow """ return Flow(count=0, action=Action.recover, transitions=transitions.strobe_color(brightness))
def lsd(duration=3000, brightness=100): """ Gradual changes to a pleasing, trippy palette. :param int duration: The duration to fade to next color, in milliseconds. :param int brightness: The brightness of the transition. :returns: An infinite Flow consisting of 5 transitions. :rtype: Flow """ return Flow(count=0, action=Action.recover, transitions=transitions.lsd(duration, brightness))
def police2(duration=250, brightness=100): """ Color flashes red and then blue, like urgent police lights. :param int duration: The duration to fade to next color, in milliseconds. :param int brightness: The brightness of the transition. :returns: An infinite Flow consisting of 8 transitions. :rtype: Flow """ return Flow(count=0, action=Action.recover, transitions=transitions.police2(duration, brightness))
def police(duration=300, brightness=100): """ Color changes from red to blue, like police lights. :param int duration: The duration between red and blue, in milliseconds. :param int brightness: The brightness of the transition. :returns: An infinite Flow consisting of 2 transitions. :rtype: Flow """ return Flow(count=0, action=Action.recover, transitions=transitions.police(duration, brightness))
def night_mode(duration=500, brightness=1): """ Dim the lights to a dark red, pleasant for the eyes at night. :param int duration: The duration to fade to next color, in milliseconds. :param int brightness: The brightness of the transition. :returns: An infinite Flow consisting of 1 transition. :rtype: Flow """ transition = [RGBTransition(0xFF, 0x99, 0x00, duration=duration, brightness=brightness)] return Flow(count=0, action=Action.recover, transitions=transition)
def christmas(duration=250, brightness=100, sleep=3000): """ Color changes from red to green, like christmas lights. :param int duration: The duration between red and green, in milliseconds. :param int brightness: The brightness of the transition. :param int sleep: The time to sleep between colors, in milliseconds. :returns: An infinite Flow consisting of 4 transitions. :rtype: Flow """ return Flow(count=0, action=Action.recover, transitions=transitions.christmas(duration, brightness, sleep))
def rgb(duration=250, brightness=100, sleep=3000): """ Color changes from red to green to blue. :param int duration: The duration to fade to next color, in milliseconds. :param int brightness: The brightness of the transition. :param int sleep: The time to sleep between colors, in milliseconds :returns: An infinite Flow consisting of 6 transitions. :rtype: Flow """ return Flow(count=0, action=Action.recover, transitions=transitions.rgb(duration, brightness, sleep))
def romance(): """ Romantic lights. :returns: An infinite Flow consisting of 2 transitions. :rtype: Flow """ transitions = [ RGBTransition(red=0x59, green=0x15, blue=0x6D, duration=4000, brightness=1), RGBTransition(red=0x66, green=0x14, blue=0x2A, duration=4000, brightness=1), ] return Flow(count=0, action=Action.stay, transitions=transitions)
def random_loop(duration=750, brightness=100, count=9): """ Color changes between `count` randomly chosen colors. :param int duration: The duration to fade to next color, in milliseconds. :param int brightness: The brightness of the transition. :param int count: The number of random chosen colors in transition. :returns: An infinite Flow consisting of up to 9 transitions. :rtype: Flow """ return Flow(count=0, action=Action.recover, transitions=transitions.random_loop(duration, brightness, count))
def movie(duration=500, brightness=50): """ Dim the lights to a comfy purple. :param int duration: The duration to fade to next color, in milliseconds. :param int brightness: The brightness of the transition. :returns: An infinite Flow consisting of 1 transition. :rtype: Flow """ transition = [RGBTransition(red=0x14, green=0x14, blue=0x32, duration=duration, brightness=brightness)] return Flow(count=0, action=Action.recover, transitions=transition)
def date_night(duration=500, brightness=50): """ Dim the lights to a cozy orange. :param int duration: The duration to fade to next color, in milliseconds. :param int brightness: The brightness of the transition. :returns: An infinite Flow consisting of 1 transition. :rtype: Flow """ transition = [RGBTransition(0xFF, 0x66, 0x00, duration=duration, brightness=brightness)] return Flow(count=0, action=Action.recover, transitions=transition)
def slowdown(duration=2000, brightness=100, count=8): """ Changes between `count` random chosen colors with increasing transition time. :param int duration: The duration to fade to next color, in milliseconds. :param int brightness: The brightness of the transition. :param int count: The number of random chosen colors in transition. :returns: An infinite Flow consisting of up to 8 transitions. :rtype: Flow """ return Flow(count=0, action=Action.recover, transitions=transitions.slowdown(duration, brightness, count))
def home(duration=500, brightness=80): """ Simulate daylight. :param int duration: The duration to fade to next color, in milliseconds. :param int brightness: The brightness of the transition. :returns: An infinite Flow consisting of 1 transition. :rtype: Flow """ transition = [TemperatureTransition(degrees=3200, duration=duration, brightness=brightness)] return Flow(count=0, action=Action.recover, transitions=transition)
def happy_birthday(): """ Happy Birthday lights. :returns: An infinite Flow consisting of 3 transitions. :rtype: Flow """ transitions = [ RGBTransition(red=0xDC, green=0x50, blue=0x19, duration=1996, brightness=80), RGBTransition(red=0xDC, green=0x78, blue=0x1E, duration=1996, brightness=80), RGBTransition(red=0xAA, green=0x32, blue=0x14, duration=1996, brightness=80), ] return Flow(count=0, action=Action.stay, transitions=transitions)
def sunrise(): """ Simulate a natural and gentle sunrise in 15 minutes. :returns: A Flow consisting of 3 transitions, after which the bulb stays on. :rtype: Flow """ transitions = [ RGBTransition(red=0xFF, green=0x4D, blue=0x00, duration=50, brightness=1), TemperatureTransition(degrees=1700, duration=360000, brightness=10), TemperatureTransition(degrees=2700, duration=540000, brightness=100), ] return Flow(count=1, action=Action.stay, transitions=transitions)
def sunset(): """ Simulate a natural sunset and offering relaxing dimming to help you sleep in 10 minutes. :returns: A Flow consisting of 3 transitions, after which the bulb turns off. :rtype: Flow """ transitions = [ TemperatureTransition(degrees=2700, duration=50, brightness=10), TemperatureTransition(degrees=1700, duration=180000, brightness=5), RGBTransition(red=0xFF, green=0x4C, blue=0x00, duration=420000, brightness=1), ] return Flow(count=1, action=Action.off, transitions=transitions)
def pulse(red, green, blue, duration=250, brightness=100): """ Pulse a single color once (mainly to be used for notifications). :param int red: The red color component to pulse (0-255). :param int green: The green color component to pulse (0-255). :param int blue: The blue color component to pulse (0-255). :param int duration: The duration to pulse for, in milliseconds. :param int brightness: The brightness to pulse at (1-100). :returns: A Flow consisting of 2 transitions, after which the bulb returns to its previous state. :rtype: Flow """ return Flow(count=1, action=Action.recover, transitions=transitions.pulse(red, green, blue, duration, brightness))
def candle_flicker(): """ Simulate candle flicker. :returns: An infinite Flow consisting of 9 transitions. :rtype: Flow """ transitions = [ TemperatureTransition(degrees=2700, duration=800, brightness=50), TemperatureTransition(degrees=2700, duration=800, brightness=30), TemperatureTransition(degrees=2700, duration=1200, brightness=80), TemperatureTransition(degrees=2700, duration=800, brightness=60), TemperatureTransition(degrees=2700, duration=1200, brightness=90), TemperatureTransition(degrees=2700, duration=2400, brightness=50), TemperatureTransition(degrees=2700, duration=1200, brightness=80), TemperatureTransition(degrees=2700, duration=800, brightness=60), TemperatureTransition(degrees=2700, duration=400, brightness=70), ] return Flow(count=0, action=Action.recover, transitions=transitions)
async def test_effects(hass: HomeAssistant): """Test effects.""" assert await async_setup_component( hass, DOMAIN, { DOMAIN: { CONF_CUSTOM_EFFECTS: [ { CONF_NAME: "mock_effect", CONF_FLOW_PARAMS: { ATTR_COUNT: 3, ATTR_TRANSITIONS: [ {YEELIGHT_HSV_TRANSACTION: [300, 50, 500, 50]}, {YEELIGHT_RGB_TRANSITION: [100, 100, 100, 300, 30]}, {YEELIGHT_TEMPERATURE_TRANSACTION: [3000, 200, 20]}, {YEELIGHT_SLEEP_TRANSACTION: [800]}, ], }, } ] } }, ) config_entry = MockConfigEntry(domain=DOMAIN, data=CONFIG_ENTRY_DATA) config_entry.add_to_hass(hass) mocked_bulb = _mocked_bulb() with _patch_discovery(), _patch_discovery_interval(), patch( f"{MODULE}.AsyncBulb", return_value=mocked_bulb ): assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert hass.states.get(ENTITY_LIGHT).attributes.get( "effect_list" ) == YEELIGHT_COLOR_EFFECT_LIST + ["mock_effect"] async def _async_test_effect(name, target=None, called=True): async_mocked_start_flow = AsyncMock() mocked_bulb.async_start_flow = async_mocked_start_flow await hass.services.async_call( "light", SERVICE_TURN_ON, {ATTR_ENTITY_ID: ENTITY_LIGHT, ATTR_EFFECT: name}, blocking=True, ) if not called: return async_mocked_start_flow.assert_called_once() if target is None: return args, _ = async_mocked_start_flow.call_args flow = args[0] assert flow.count == target.count assert flow.action == target.action assert str(flow.transitions) == str(target.transitions) effects = { "mock_effect": Flow( count=3, transitions=[ HSVTransition(300, 50, 500, 50), RGBTransition(100, 100, 100, 300, 30), TemperatureTransition(3000, 200, 20), SleepTransition(800), ], ), EFFECT_DISCO: Flow(transitions=transitions.disco()), EFFECT_FAST_RANDOM_LOOP: None, EFFECT_WHATSAPP: Flow(count=2, transitions=transitions.pulse(37, 211, 102)), EFFECT_FACEBOOK: Flow(count=2, transitions=transitions.pulse(59, 89, 152)), EFFECT_TWITTER: Flow(count=2, transitions=transitions.pulse(0, 172, 237)), EFFECT_HOME: Flow( count=0, action=Action.recover, transitions=[ TemperatureTransition(degrees=3200, duration=500, brightness=80) ], ), EFFECT_NIGHT_MODE: Flow( count=0, action=Action.recover, transitions=[RGBTransition(0xFF, 0x99, 0x00, duration=500, brightness=1)], ), EFFECT_DATE_NIGHT: Flow( count=0, action=Action.recover, transitions=[RGBTransition(0xFF, 0x66, 0x00, duration=500, brightness=50)], ), EFFECT_MOVIE: Flow( count=0, action=Action.recover, transitions=[ RGBTransition( red=0x14, green=0x14, blue=0x32, duration=500, brightness=50 ) ], ), EFFECT_SUNRISE: Flow( count=1, action=Action.stay, transitions=[ RGBTransition( red=0xFF, green=0x4D, blue=0x00, duration=50, brightness=1 ), TemperatureTransition(degrees=1700, duration=360000, brightness=10), TemperatureTransition(degrees=2700, duration=540000, brightness=100), ], ), EFFECT_SUNSET: Flow( count=1, action=Action.off, transitions=[ TemperatureTransition(degrees=2700, duration=50, brightness=10), TemperatureTransition(degrees=1700, duration=180000, brightness=5), RGBTransition( red=0xFF, green=0x4C, blue=0x00, duration=420000, brightness=1 ), ], ), EFFECT_ROMANCE: Flow( count=0, action=Action.stay, transitions=[ RGBTransition( red=0x59, green=0x15, blue=0x6D, duration=4000, brightness=1 ), RGBTransition( red=0x66, green=0x14, blue=0x2A, duration=4000, brightness=1 ), ], ), EFFECT_HAPPY_BIRTHDAY: Flow( count=0, action=Action.stay, transitions=[ RGBTransition( red=0xDC, green=0x50, blue=0x19, duration=1996, brightness=80 ), RGBTransition( red=0xDC, green=0x78, blue=0x1E, duration=1996, brightness=80 ), RGBTransition( red=0xAA, green=0x32, blue=0x14, duration=1996, brightness=80 ), ], ), EFFECT_CANDLE_FLICKER: Flow( count=0, action=Action.recover, transitions=[ TemperatureTransition(degrees=2700, duration=800, brightness=50), TemperatureTransition(degrees=2700, duration=800, brightness=30), TemperatureTransition(degrees=2700, duration=1200, brightness=80), TemperatureTransition(degrees=2700, duration=800, brightness=60), TemperatureTransition(degrees=2700, duration=1200, brightness=90), TemperatureTransition(degrees=2700, duration=2400, brightness=50), TemperatureTransition(degrees=2700, duration=1200, brightness=80), TemperatureTransition(degrees=2700, duration=800, brightness=60), TemperatureTransition(degrees=2700, duration=400, brightness=70), ], ), } for name, target in effects.items(): await _async_test_effect(name, target) await _async_test_effect("not_existed", called=False)
async def test_effects(hass: HomeAssistant): """Test effects.""" yaml_configuration = { DOMAIN: { CONF_DEVICES: YAML_CONFIGURATION[DOMAIN][CONF_DEVICES], CONF_CUSTOM_EFFECTS: [ { CONF_NAME: "mock_effect", CONF_FLOW_PARAMS: { ATTR_COUNT: 3, ATTR_TRANSITIONS: [ { YEELIGHT_HSV_TRANSACTION: [300, 50, 500, 50] }, { YEELIGHT_RGB_TRANSITION: [100, 100, 100, 300, 30] }, { YEELIGHT_TEMPERATURE_TRANSACTION: [3000, 200, 20] }, { YEELIGHT_SLEEP_TRANSACTION: [800] }, ], }, }, ], } } mocked_bulb = _mocked_bulb() with patch(f"{MODULE}.Bulb", return_value=mocked_bulb): assert await async_setup_component(hass, DOMAIN, yaml_configuration) await hass.async_block_till_done() assert hass.states.get(ENTITY_LIGHT).attributes.get( "effect_list") == YEELIGHT_COLOR_EFFECT_LIST + ["mock_effect"] async def _async_test_effect(name, target=None, called=True): mocked_start_flow = MagicMock() type(mocked_bulb).start_flow = mocked_start_flow await hass.services.async_call( "light", SERVICE_TURN_ON, { ATTR_ENTITY_ID: ENTITY_LIGHT, ATTR_EFFECT: name }, blocking=True, ) if not called: return mocked_start_flow.assert_called_once() if target is None: return args, _ = mocked_start_flow.call_args flow = args[0] assert flow.count == target.count assert flow.action == target.action assert str(flow.transitions) == str(target.transitions) effects = { "mock_effect": Flow( count=3, transitions=[ HSVTransition(300, 50, 500, 50), RGBTransition(100, 100, 100, 300, 30), TemperatureTransition(3000, 200, 20), SleepTransition(800), ], ), EFFECT_DISCO: Flow(transitions=transitions.disco()), EFFECT_FAST_RANDOM_LOOP: None, EFFECT_WHATSAPP: Flow(count=2, transitions=transitions.pulse(37, 211, 102)), EFFECT_FACEBOOK: Flow(count=2, transitions=transitions.pulse(59, 89, 152)), EFFECT_TWITTER: Flow(count=2, transitions=transitions.pulse(0, 172, 237)), } for name, target in effects.items(): await _async_test_effect(name, target) await _async_test_effect("not_existed", called=False)
async def test_effects(hass: HomeAssistant): """Test effects.""" assert await async_setup_component( hass, DOMAIN, { DOMAIN: { CONF_CUSTOM_EFFECTS: [ { CONF_NAME: "mock_effect", CONF_FLOW_PARAMS: { ATTR_COUNT: 3, ATTR_TRANSITIONS: [ { YEELIGHT_HSV_TRANSACTION: [300, 50, 500, 50] }, { YEELIGHT_RGB_TRANSITION: [100, 100, 100, 300, 30] }, { YEELIGHT_TEMPERATURE_TRANSACTION: [3000, 200, 20] }, { YEELIGHT_SLEEP_TRANSACTION: [800] }, ], }, }, ], }, }, ) config_entry = MockConfigEntry( domain=DOMAIN, data={ CONF_ID: "", CONF_HOST: IP_ADDRESS, CONF_TRANSITION: DEFAULT_TRANSITION, CONF_MODE_MUSIC: DEFAULT_MODE_MUSIC, CONF_SAVE_ON_CHANGE: DEFAULT_SAVE_ON_CHANGE, CONF_NIGHTLIGHT_SWITCH: DEFAULT_NIGHTLIGHT_SWITCH, }, ) config_entry.add_to_hass(hass) mocked_bulb = _mocked_bulb() with _patch_discovery(MODULE), patch(f"{MODULE}.Bulb", return_value=mocked_bulb): assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert hass.states.get(ENTITY_LIGHT).attributes.get( "effect_list") == YEELIGHT_COLOR_EFFECT_LIST + ["mock_effect"] async def _async_test_effect(name, target=None, called=True): mocked_start_flow = MagicMock() type(mocked_bulb).start_flow = mocked_start_flow await hass.services.async_call( "light", SERVICE_TURN_ON, { ATTR_ENTITY_ID: ENTITY_LIGHT, ATTR_EFFECT: name }, blocking=True, ) if not called: return mocked_start_flow.assert_called_once() if target is None: return args, _ = mocked_start_flow.call_args flow = args[0] assert flow.count == target.count assert flow.action == target.action assert str(flow.transitions) == str(target.transitions) effects = { "mock_effect": Flow( count=3, transitions=[ HSVTransition(300, 50, 500, 50), RGBTransition(100, 100, 100, 300, 30), TemperatureTransition(3000, 200, 20), SleepTransition(800), ], ), EFFECT_DISCO: Flow(transitions=transitions.disco()), EFFECT_FAST_RANDOM_LOOP: None, EFFECT_WHATSAPP: Flow(count=2, transitions=transitions.pulse(37, 211, 102)), EFFECT_FACEBOOK: Flow(count=2, transitions=transitions.pulse(59, 89, 152)), EFFECT_TWITTER: Flow(count=2, transitions=transitions.pulse(0, 172, 237)), } for name, target in effects.items(): await _async_test_effect(name, target) await _async_test_effect("not_existed", called=False)