diff --git a/homeassistant/actors.py b/homeassistant/actors.py index b58a55f2752..d58c10f892d 100644 --- a/homeassistant/actors.py +++ b/homeassistant/actors.py @@ -26,12 +26,9 @@ LIGHT_TRANSITION_TIME = timedelta(minutes=15) DOMAIN_DOWNLOADER = "downloader" DOMAIN_BROWSER = "browser" DOMAIN_KEYBOARD = "keyboard" -DOMAIN_LIGHT_CONTROL = "light_control" SERVICE_DOWNLOAD_FILE = "download_file" SERVICE_BROWSE_URL = "browse_url" -SERVICE_TURN_LIGHT_ON = "turn_light_on" -SERVICE_TURN_LIGHT_OFF = "turn_light_off" SERVICE_KEYBOARD_VOLUME_UP = "volume_up" SERVICE_KEYBOARD_VOLUME_DOWN = "volume_down" SERVICE_KEYBOARD_VOLUME_MUTE = "volume_mute" @@ -192,19 +189,30 @@ class HueLightControl(object): return - self.bridge = phue.Bridge(host) - self.lights = self.bridge.get_light_objects() - self.light_ids = [light.light_id for light in self.lights] + self._bridge = phue.Bridge(host) + + self._light_map = {light.light_id: light + for light in self._bridge.get_light_objects()} self.success_init = True + @property + def light_ids(self): + """ Return a list of light ids. """ + return self._light_map.keys() + + def get_light_name(self, light_id): + """ Return the name of the specified light. """ + return self._light_map[light_id].name + def is_light_on(self, light_id=None): """ Returns if specified or all light are on. """ if not light_id: - return sum([1 for light in self.lights if light.on]) > 0 + return sum( + [1 for light in self._light_map.values() if light.on]) > 0 else: - return self.bridge.get_light(light_id, 'on') + return self._bridge.get_light(light_id, 'on') def turn_light_on(self, light_id=None, transition_seconds=None): """ Turn the specified or all lights on. """ @@ -217,7 +225,7 @@ class HueLightControl(object): command['transitiontime'] = \ _hue_process_transition_time(transition_seconds) - self.bridge.set_light(light_id, command) + self._bridge.set_light(light_id, command) def turn_light_off(self, light_id=None, transition_seconds=None): """ Turn the specified or all lights off. """ @@ -230,30 +238,7 @@ class HueLightControl(object): command['transitiontime'] = \ _hue_process_transition_time(transition_seconds) - self.bridge.set_light(light_id, command) - - -def setup_light_control_services(bus, light_control): - """ Exposes light control via services. """ - - def handle_light_event(service): - """ Hande a turn light on or off service call. """ - light_id = service.data.get("light_id", None) - transition_seconds = service.data.get("transition_seconds", None) - - if service.service == SERVICE_TURN_LIGHT_ON: - light_control.turn_light_on(light_id, transition_seconds) - else: - light_control.turn_light_off(light_id, transition_seconds) - - # Listen for light on and light off events - bus.register_service(DOMAIN_LIGHT_CONTROL, SERVICE_TURN_LIGHT_ON, - handle_light_event) - - bus.register_service(DOMAIN_LIGHT_CONTROL, SERVICE_TURN_LIGHT_OFF, - handle_light_event) - - return True + self._bridge.set_light(light_id, command) def setup_file_downloader(bus, download_path): diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 9773360536a..6dc3c44e328 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -92,7 +92,7 @@ def from_config_file(config_path): # Light trigger if light_control: - actors.setup_light_control_services(bus, light_control) + observers.setup_light_control_services(bus, statemachine, light_control) actors.LightTrigger(bus, statemachine, device_tracker, light_control) diff --git a/homeassistant/observers.py b/homeassistant/observers.py index 8981c1b5975..4b3a811e6aa 100644 --- a/homeassistant/observers.py +++ b/homeassistant/observers.py @@ -18,12 +18,16 @@ import json import requests import homeassistant as ha +import homeassistant.util as util DOMAIN_DEVICE_TRACKER = "device_tracker" DOMAIN_CHROMECAST = "chromecast" +DOMAIN_LIGHT_CONTROL = "light_control" SERVICE_DEVICE_TRACKER_RELOAD = "reload_devices_csv" SERVICE_CHROMECAST_YOUTUBE_VIDEO = "play_youtube_video" +SERVICE_TURN_LIGHT_ON = "turn_light_on" +SERVICE_TURN_LIGHT_OFF = "turn_light_off" STATE_CATEGORY_SUN = "weather.sun" STATE_ATTRIBUTE_NEXT_SUN_RISING = "next_rising" @@ -34,9 +38,15 @@ STATE_CATEGORY_DEVICE_FORMAT = 'device.{}' STATE_CATEGORY_CHROMECAST = 'chromecast' +STATE_CATEGORY_ALL_LIGHTS = 'light.ALL' +STATE_CATEGORY_LIGHT_FORMAT = "light.{}" + SUN_STATE_ABOVE_HORIZON = "above_horizon" SUN_STATE_BELOW_HORIZON = "below_horizon" +LIGHT_STATE_ON = "on" +LIGHT_STATE_OFF = "off" + DEVICE_STATE_NOT_HOME = 'device_not_home' DEVICE_STATE_HOME = 'device_home' @@ -131,6 +141,48 @@ def setup_chromecast(bus, statemachine, host): return True +def setup_light_control_services(bus, statemachine, light_control): + """ Exposes light control via statemachine and services. """ + + def update_light_state(time): # pylint: disable=unused-argument + """ Track the state of the lights. """ + status = {light_id: light_control.is_light_on(light_id) + for light_id in light_control.light_ids} + + for light_id, state in status.items(): + state_category = STATE_CATEGORY_LIGHT_FORMAT.format( + util.slugify(light_control.get_light_name(light_id))) + + statemachine.set_state(state_category, + LIGHT_STATE_ON if state + else LIGHT_STATE_OFF) + + statemachine.set_state(STATE_CATEGORY_ALL_LIGHTS, + LIGHT_STATE_ON if True in status.values() + else LIGHT_STATE_OFF) + + ha.track_time_change(bus, update_light_state, second=[0, 30]) + + def handle_light_event(service): + """ Hande a turn light on or off service call. """ + light_id = service.data.get("light_id", None) + transition_seconds = service.data.get("transition_seconds", None) + + if service.service == SERVICE_TURN_LIGHT_ON: + light_control.turn_light_on(light_id, transition_seconds) + else: + light_control.turn_light_off(light_id, transition_seconds) + + # Listen for light on and light off events + bus.register_service(DOMAIN_LIGHT_CONTROL, SERVICE_TURN_LIGHT_ON, + handle_light_event) + + bus.register_service(DOMAIN_LIGHT_CONTROL, SERVICE_TURN_LIGHT_OFF, + handle_light_event) + + return True + + class DeviceTracker(object): """ Class that tracks which devices are home and which are not. """