def cycle_themes(lifx: Group, *themes: ColorTheme, rotate_secs: Optional[int] = 60, duration_mins: Optional[int] = 20, transition_secs=5, all_lights=True): """ set lights to theme every `rotate_secs`. will round robin `themes`. rotation still works on one theme as it will re-assign the theme each `rotate_secs` """ end_time = arrow.utcnow().shift(minutes=duration_mins or 100000) themes = [colors_to_theme(t) for t in themes] with lifx.reset_to_orig(): for t in cycle(themes): if arrow.utcnow() > end_time: return lifx.set_theme(t, power_on=all_lights, duration=transition_secs * 1000) if rotate_secs: sleep(rotate_secs) else: sleep(duration_mins * 60 or 10000)
def blink_power(lifx: Group, blink_time_secs=.5, how_long_secs=8): """toggle power on lights every `blink_time_secs`""" num_cycles = math.ceil(how_long_secs / blink_time_secs) with lifx.reset_to_orig(): lifx.turn_off() for _, power in zip(range(num_cycles), cycle(range(2))): lifx.set_power(power) sleep(blink_time_secs)
def blink_color(lifx: Group, colors: Optional[ColorTheme] = None, blink_time_secs=.5, how_long_secs=8): """change colors on lights every `blink_time_secs`""" num_cycles = math.ceil(how_long_secs / blink_time_secs) theme = colors_to_theme(colors) or (Colors.COPILOT_BLUE, Colors.COPILOT_DARK_BLUE) with lifx.reset_to_orig(): for _, color in zip(range(num_cycles), cycle(theme)): lifx.set_color(color) sleep(blink_time_secs)
def rainbow(lifx: Group, colors: Optional[ColorTheme] = Themes.rainbow, duration_secs=0.5, smooth=False, num_repeats=1): """similar to blink_color""" theme = colors_to_theme(colors) transition_time_ms = duration_secs * 1000 if smooth else 0 rapid = duration_secs < 1 with lifx.reset_to_orig(): for _ in range(num_repeats): for color in theme: lifx.set_color(color, transition_time_ms, rapid) sleep(duration_secs)
def breathe(lifx: Group, breath_time_secs=8, min_brightness_pct=30, max_brightness_pct=60, colors: Optional[ColorTheme] = None, duration_mins: Optional[Union[int, float]] = 20): """whatever lights you pass in will breathe""" theme = colors_to_theme(colors) half_period_ms = int(breath_time_secs * 1000.0) sleep_time = breath_time_secs duration_secs = duration_mins * 60 or float('inf') min_brightness = min_brightness_pct / 100.0 * 65535 max_brightness = max_brightness_pct / 100.0 * 65535 with lifx.reset_to_orig(half_period_ms): lifx.set_brightness(max_brightness, duration=2000) if theme: lifx.set_theme(theme) print("Breathing...") try: start_time = time() while True: with lifx.reset_to_orig(half_period_ms): lifx.set_brightness(min_brightness, half_period_ms) sleep(sleep_time) sleep(sleep_time) if time() - start_time > duration_secs: raise KeyboardInterrupt except KeyboardInterrupt: print("Restoring original color and power to all lights...")
def fireworks(lifx: Group): """make lights look like fireworks""" start_color = Colors.SNES_LIGHT_PURPLE with lifx.reset_to_orig(): lifx.set_color(start_color) sleep(1) for pers in (500, 250, 125, 60, 30): num_cycles = 1000 // pers _set_waveforms(lifx, Waveform.pulse, start_color, Colors.SNES_DARK_PURPLE, period_msec=pers, num_cycles=num_cycles, reduce_sleep_msecs=100)
def morse_code(word_or_phrase: str, light_group: Union[Light, Group], delay_time_msec=TIME_QUANTUM_MS, settings: MCSettings = MCSettings()): """translate `word_or_phrase` into morse code that will appear on your lights""" light_group = Group([light_group]) if isinstance(light_group, Light) else light_group m = Morse.from_str(word_or_phrase) with light_group.reset_to_orig(3000): for c, length in m.to_char_and_len(delay_time_msec): light_group.set_color_power(settings.cp_from_char(c)) time.sleep(length)
def waveforms(lifx: Group, waveform: Waveform, start_color: Color, end_color: Color, *, period_msec=4000, num_cycles=4, skew_ratio=.5): """test out waveforms""" with lifx.reset_to_orig(): _set_waveforms(lifx, waveform, start_color, end_color, period_msec=period_msec, num_cycles=num_cycles, skew_ratio=skew_ratio)
def light_eq(lifx: Group, color_theme: Optional[ColorTheme] = None): """ a light equalizer to play with HSBk \b - homerow (aoeu/asdf) controls hue - shift-homerow controls hue even more \b - left/right controls saturation - shift-left/right mins/maxes saturation \b - down/up controls brightness - shift-down/up mins/maxes brightness - jk (dvorak)/cv (qwerty) control kelvin - ctrl-r resets - ctrl-w prints light info to screen """ def _init_lights(): lifx.turn_on() if theme: lifx.set_theme(theme) theme = colors_to_theme(color_theme) with suppress(KeyboardInterrupt), lifx.reset_to_orig(): _init_lights() for ao in _get_offset(): if ao.attr == 'reset': _init_lights() elif ao.attr == 'print': for l in lifx: print(l, l.color) else: getattr(lifx, f'set_{ao.attr}')(ao.value, offset=ao.as_offset)
def _set_waveforms(lifx: Group, waveform: Waveform, start_color: Color, end_color: Color, *, period_msec=4000, num_cycles=4, skew_ratio=.5, reduce_sleep_msecs=0): lifx.turn_on() lifx.set_color(start_color) lifx.set_waveform(waveform, end_color, period_msec, num_cycles, skew_ratio=skew_ratio) sleep((period_msec * num_cycles - reduce_sleep_msecs) / 1000)
def get_next_light(group: Group, gl: GridLight, dirs: Iterable[Dir] = parse_keyboard_inputs( dir_map, separate_process=True)): """get next light from grid light""" for dir in dirs: cur_gl = gl found_light = False # this while loop allows for non-contiguous groups of lights to be traversed while not found_light: next_gl = cur_gl.move(dir) if next_gl == cur_gl: break if not group.get_device_by_name(next_gl.name): cur_gl = next_gl continue found_light = True else: gl = next_gl yield gl
def zones(self, vals: List['Zone']): from lifxlan3 import Group self._zones = Group(vals, allow_dupes=True) self._init_grid()