def setup(self, config):
        """Set up a full entity component.

        Loads the platforms from the config and will listen for supported
        discovered platforms.
        """
        self.config = config

        # Look in config for Domain, Domain 2, Domain 3 etc and load them
        for p_type, p_config in config_per_platform(config, self.domain):
            self._setup_platform(p_type, p_config)

        if self.discovery_platforms:
            # Discovery listener for all items in discovery_platforms array
            # passed from a component's setup method (e.g. light/__init__.py)
            discovery.listen(
                self.hass,
                self.discovery_platforms.keys(),
                lambda service, info: self._setup_platform(self.discovery_platforms[service], {}, info),
            )

        # Generic discovery listener for loading platform dynamically
        # Refer to: homeassistant.components.discovery.load_platform()
        def load_platform_callback(service, info):
            """Callback to load a platform."""
            platform = info.pop(discovery.LOAD_PLATFORM)
            self._setup_platform(platform, {}, info if info else None)

        discovery.listen(self.hass, discovery.LOAD_PLATFORM + "." + self.domain, load_platform_callback)
Example #2
0
    def setup(self, config):
        """Set up a full entity component.

        Loads the platforms from the config and will listen for supported
        discovered platforms.
        """
        self.config = config

        # Look in config for Domain, Domain 2, Domain 3 etc and load them
        for p_type, p_config in config_per_platform(config, self.domain):
            self._setup_platform(p_type, p_config)

        if self.discovery_platforms:
            # Discovery listener for all items in discovery_platforms array
            # passed from a component's setup method (e.g. light/__init__.py)
            discovery.listen(
                self.hass, self.discovery_platforms.keys(),
                lambda service, info: self._setup_platform(
                    self.discovery_platforms[service], {}, info))

        # Generic discovery listener for loading platform dynamically
        # Refer to: homeassistant.components.discovery.load_platform()
        def load_platform_callback(service, info):
            """Callback to load a platform."""
            platform = info.pop(discovery.LOAD_PLATFORM)
            self._setup_platform(platform, {}, info if info else None)

        discovery.listen(self.hass,
                         discovery.LOAD_PLATFORM + '.' + self.domain,
                         load_platform_callback)
Example #3
0
def setup(hass, config):
    """Common setup for WeMo devices."""
    import pywemo

    global SUBSCRIPTION_REGISTRY
    SUBSCRIPTION_REGISTRY = pywemo.SubscriptionRegistry()
    SUBSCRIPTION_REGISTRY.start()

    def stop_wemo(event):
        """Shutdown Wemo subscriptions and subscription thread on exit."""
        _LOGGER.info("Shutting down subscriptions.")
        SUBSCRIPTION_REGISTRY.stop()

    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_wemo)

    def discovery_dispatch(service, discovery_info):
        """Dispatcher for WeMo discovery events."""
        # name, model, location, mac
        _, model_name, _, _, serial = discovery_info

        # Only register a device once
        if serial in KNOWN_DEVICES:
            return
        _LOGGER.debug('Discovered unique device %s', serial)
        KNOWN_DEVICES.append(serial)

        service = WEMO_MODEL_DISPATCH.get(model_name) or DISCOVER_SWITCHES
        component = WEMO_SERVICE_DISPATCH.get(service)

        discovery.discover(hass, service, discovery_info,
                           component, config)

    discovery.listen(hass, discovery.SERVICE_WEMO, discovery_dispatch)

    _LOGGER.info("Scanning for WeMo devices.")
    devices = [(device.host, device) for device in pywemo.discover_devices()]

    # Add static devices from the config file.
    devices.extend((address, None)
                   for address in config.get(DOMAIN, {}).get('static', []))

    for address, device in devices:
        port = pywemo.ouimeaux_device.probe_wemo(address)
        if not port:
            _LOGGER.warning('Unable to probe wemo at %s', address)
            continue
        _LOGGER.info('Adding wemo at %s:%i', address, port)

        url = 'http://%s:%i/setup.xml' % (address, port)
        if device is None:
            device = pywemo.discovery.device_from_description(url, None)

        discovery_info = (device.name, device.model_name, url, device.mac,
                          device.serialnumber)
        discovery.discover(hass, discovery.SERVICE_WEMO, discovery_info)
    return True
Example #4
0
def setup(hass, config):
    """Common setup for WeMo devices."""
    import pywemo

    global SUBSCRIPTION_REGISTRY
    SUBSCRIPTION_REGISTRY = pywemo.SubscriptionRegistry()
    SUBSCRIPTION_REGISTRY.start()

    def stop_wemo(event):
        """Shutdown Wemo subscriptions and subscription thread on exit."""
        _LOGGER.info("Shutting down subscriptions.")
        SUBSCRIPTION_REGISTRY.stop()

    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_wemo)

    def discovery_dispatch(service, discovery_info):
        """Dispatcher for WeMo discovery events."""
        # name, model, location, mac
        _, model_name, _, _, serial = discovery_info

        # Only register a device once
        if serial in KNOWN_DEVICES:
            return
        _LOGGER.debug('Discovered unique device %s', serial)
        KNOWN_DEVICES.append(serial)

        service = WEMO_MODEL_DISPATCH.get(model_name) or DISCOVER_SWITCHES
        component = WEMO_SERVICE_DISPATCH.get(service)

        discovery.discover(hass, service, discovery_info, component, config)

    discovery.listen(hass, discovery.SERVICE_WEMO, discovery_dispatch)

    _LOGGER.info("Scanning for WeMo devices.")
    devices = [(device.host, device) for device in pywemo.discover_devices()]

    # Add static devices from the config file.
    devices.extend((address, None)
                   for address in config.get(DOMAIN, {}).get('static', []))

    for address, device in devices:
        port = pywemo.ouimeaux_device.probe_wemo(address)
        if not port:
            _LOGGER.warning('Unable to probe wemo at %s', address)
            continue
        _LOGGER.info('Adding wemo at %s:%i', address, port)

        url = 'http://%s:%i/setup.xml' % (address, port)
        if device is None:
            device = pywemo.discovery.device_from_description(url, None)

        discovery_info = (device.name, device.model_name, url, device.mac,
                          device.serialnumber)
        discovery.discover(hass, discovery.SERVICE_WEMO, discovery_info)
    return True
    def setup(self, config):
        """
        Sets up a full entity component:
         - Loads the platforms from the config
         - Will listen for supported discovered platforms
        """
        # Look in config for Domain, Domain 2, Domain 3 etc and load them
        for p_type, p_config in \
                config_per_platform(config, self.domain, self.logger):

            self._setup_platform(p_type, p_config)

        if self.discovery_platforms:
            discovery.listen(self.hass, self.discovery_platforms.keys(),
                             self._entity_discovered)
Example #6
0
    def setup(self, config):
        """
        Sets up a full entity component:
         - Loads the platforms from the config
         - Will listen for supported discovered platforms
        """
        # Look in config for Domain, Domain 2, Domain 3 etc and load them
        for p_type, p_config in \
                config_per_platform(config, self.domain, self.logger):

            self._setup_platform(p_type, p_config)

        if self.discovery_platforms:
            discovery.listen(self.hass, self.discovery_platforms.keys(),
                             self._entity_discovered)
Example #7
0
def setup(hass, config):
    """ Track states and offer events for sensors. """
    logger = logging.getLogger(__name__)

    sensors = platform_devices_from_config(
        config, DOMAIN, hass, ENTITY_ID_FORMAT, logger)

    @util.Throttle(MIN_TIME_BETWEEN_SCANS)
    def update_sensor_states(now):
        """ Update states of all sensors. """
        if sensors:
            logger.info("Updating sensor states")

            for sensor in sensors.values():
                sensor.update_ha_state(hass, True)

    update_sensor_states(None)

    # Track all sensors in a group
    sensor_group = group.Group(
        hass, GROUP_NAME_ALL_SENSORS, sensors.keys(), False)

    def sensor_discovered(service, info):
        """ Called when a sensor is discovered. """
        platform = get_component("{}.{}".format(
            DOMAIN, DISCOVERY_PLATFORMS[service]))

        discovered = platform.devices_discovered(hass, config, info)

        for sensor in discovered:
            if sensor is not None and sensor not in sensors.values():
                sensor.entity_id = util.ensure_unique_string(
                    ENTITY_ID_FORMAT.format(util.slugify(sensor.name)),
                    sensors.keys())

                sensors[sensor.entity_id] = sensor

                sensor.update_ha_state(hass)

        sensor_group.update_tracked_entity_ids(sensors.keys())

    discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), sensor_discovered)

    # Fire every 3 seconds
    hass.track_time_change(update_sensor_states, seconds=range(0, 60, 3))

    return True
Example #8
0
def setup(hass, config):
    """ Track states and offer events for sensors. """
    logger = logging.getLogger(__name__)

    sensors = platform_devices_from_config(config, DOMAIN, hass,
                                           ENTITY_ID_FORMAT, logger)

    @util.Throttle(MIN_TIME_BETWEEN_SCANS)
    def update_sensor_states(now):
        """ Update states of all sensors. """
        if sensors:
            logger.info("Updating sensor states")

            for sensor in sensors.values():
                sensor.update_ha_state(hass, True)

    update_sensor_states(None)

    # Track all sensors in a group
    sensor_group = group.Group(hass, GROUP_NAME_ALL_SENSORS, sensors.keys(),
                               False)

    def sensor_discovered(service, info):
        """ Called when a sensor is discovered. """
        platform = get_component("{}.{}".format(DOMAIN,
                                                DISCOVERY_PLATFORMS[service]))

        discovered = platform.devices_discovered(hass, config, info)

        for sensor in discovered:
            if sensor is not None and sensor not in sensors.values():
                sensor.entity_id = util.ensure_unique_string(
                    ENTITY_ID_FORMAT.format(util.slugify(sensor.name)),
                    sensors.keys())

                sensors[sensor.entity_id] = sensor

                sensor.update_ha_state(hass)

        sensor_group.update_tracked_entity_ids(sensors.keys())

    discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), sensor_discovered)

    # Fire every 3 seconds
    hass.track_time_change(update_sensor_states, seconds=range(0, 60, 3))

    return True
Example #9
0
    def setup(self, config):
        """Set up a full entity component.

        Loads the platforms from the config and will listen for supported
        discovered platforms.
        """
        self.config = config

        # Look in config for Domain, Domain 2, Domain 3 etc and load them
        for p_type, p_config in config_per_platform(config, self.domain):
            self._setup_platform(p_type, p_config)

        if self.discovery_platforms:
            discovery.listen(
                self.hass, self.discovery_platforms.keys(),
                lambda service, info: self._setup_platform(
                    self.discovery_platforms[service], {}, info))
    def setup(self, config):
        """Set up a full entity component.

        Loads the platforms from the config and will listen for supported
        discovered platforms.
        """
        self.config = config

        # Look in config for Domain, Domain 2, Domain 3 etc and load them
        for p_type, p_config in config_per_platform(config, self.domain):
            self._setup_platform(p_type, p_config)

        if self.discovery_platforms:
            discovery.listen(
                self.hass, self.discovery_platforms.keys(),
                lambda service, info:
                self._setup_platform(self.discovery_platforms[service], {},
                                     info))
    def setup(self, config):
        """
        Sets up a full device component:
         - Loads the platforms from the config
         - Will update devices on an interval
         - Will listen for supported discovered platforms
        """

        # only setup group if name is given
        if self.group_name is None:
            self.group = None
        else:
            self.group = group.Group(self.hass, self.group_name,
                                     user_defined=False)

        # Look in config for Domain, Domain 2, Domain 3 etc and load them
        for p_type, p_config in \
                config_per_platform(config, self.domain, self.logger):

            self._setup_platform(p_type, p_config)

        if self.discovery_platforms:
            discovery.listen(self.hass, self.discovery_platforms.keys(),
                             self._device_discovered)
    def setup(self, config):
        """
        Sets up a full device component:
         - Loads the platforms from the config
         - Will update devices on an interval
         - Will listen for supported discovered platforms
        """

        # only setup group if name is given
        if self.group_name is None:
            self.group = None
        else:
            self.group = group.Group(self.hass, self.group_name,
                                     user_defined=False)

        # Look in config for Domain, Domain 2, Domain 3 etc and load them
        for p_type, p_config in \
                config_per_platform(config, self.domain, self.logger):

            self._setup_platform(p_type, p_config)

        if self.discovery_platforms:
            discovery.listen(self.hass, self.discovery_platforms.keys(),
                             self._device_discovered)
Example #13
0
def setup(hass, config):
    """Setup device tracker."""
    yaml_path = hass.config.path(YAML_DEVICES)

    conf = config.get(DOMAIN, {})
    if isinstance(conf, list):
        conf = conf[0]
    consider_home = timedelta(
        seconds=util.convert(conf.get(CONF_CONSIDER_HOME), int,
                             DEFAULT_CONSIDER_HOME))
    track_new = util.convert(conf.get(CONF_TRACK_NEW), bool,
                             DEFAULT_CONF_TRACK_NEW)
    home_range = util.convert(conf.get(CONF_HOME_RANGE), int,
                              DEFAULT_HOME_RANGE)

    devices = load_config(yaml_path, hass, consider_home, home_range)
    tracker = DeviceTracker(hass, consider_home, track_new, home_range,
                            devices)

    def setup_platform(p_type, p_config, disc_info=None):
        """Setup a device tracker platform."""
        platform = prepare_setup_platform(hass, config, DOMAIN, p_type)
        if platform is None:
            return

        try:
            if hasattr(platform, 'get_scanner'):
                scanner = platform.get_scanner(hass, {DOMAIN: p_config})

                if scanner is None:
                    _LOGGER.error('Error setting up platform %s', p_type)
                    return

                setup_scanner_platform(hass, p_config, scanner, tracker.see)
                return

            if not platform.setup_scanner(hass, p_config, tracker.see):
                _LOGGER.error('Error setting up platform %s', p_type)
        except Exception:  # pylint: disable=broad-except
            _LOGGER.exception('Error setting up platform %s', p_type)

    for p_type, p_config in config_per_platform(config, DOMAIN):
        setup_platform(p_type, p_config)

    def device_tracker_discovered(service, info):
        """Called when a device tracker platform is discovered."""
        setup_platform(DISCOVERY_PLATFORMS[service], {}, info)

    discovery.listen(hass, DISCOVERY_PLATFORMS.keys(),
                     device_tracker_discovered)

    def update_stale(now):
        """Clean up stale devices."""
        tracker.update_stale(now)
    track_utc_time_change(hass, update_stale, second=range(0, 60, 5))

    tracker.setup_group()

    def see_service(call):
        """Service to see a device."""
        args = {key: value for key, value in call.data.items() if key in
                (ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME,
                 ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_BATTERY)}
        tracker.see(**args)

    descriptions = load_yaml_config_file(
        os.path.join(os.path.dirname(__file__), 'services.yaml'))
    hass.services.register(DOMAIN, SERVICE_SEE, see_service,
                           descriptions.get(SERVICE_SEE))

    return True
Example #14
0
def setup(hass, config):
    """ Exposes light control via statemachine and services. """

    # Load built-in profiles and custom profiles
    profile_paths = [os.path.join(os.path.dirname(__file__),
                                  LIGHT_PROFILES_FILE),
                     hass.get_config_path(LIGHT_PROFILES_FILE)]
    profiles = {}

    for profile_path in profile_paths:

        if os.path.isfile(profile_path):
            with open(profile_path) as inp:
                reader = csv.reader(inp)

                # Skip the header
                next(reader, None)

                try:
                    for profile_id, color_x, color_y, brightness in reader:
                        profiles[profile_id] = (float(color_x), float(color_y),
                                                int(brightness))

                except ValueError:
                    # ValueError if not 4 values per row
                    # ValueError if convert to float/int failed
                    _LOGGER.error(
                        "Error parsing light profiles from %s", profile_path)

                    return False

    # Dict to track entity_id -> lights
    lights = {}

    # Track all lights in a group
    light_group = group.Group(hass, GROUP_NAME_ALL_LIGHTS, user_defined=False)

    def add_lights(new_lights):
        """ Add lights to the component to track. """
        for light in new_lights:
            if light is not None and light not in lights.values():
                light.entity_id = generate_entity_id(
                    ENTITY_ID_FORMAT, light.name, lights.keys())

                lights[light.entity_id] = light

                light.update_ha_state(hass)

        light_group.update_tracked_entity_ids(lights.keys())

    for p_type, p_config in config_per_platform(config, DOMAIN, _LOGGER):
        platform = get_component(ENTITY_ID_FORMAT.format(p_type))

        if platform is None:
            _LOGGER.error("Unknown type specified: %s", p_type)

        platform.setup_platform(hass, p_config, add_lights)

    def update_lights_state(now):
        """ Update the states of all the lights. """
        if lights:
            _LOGGER.info("Updating light states")

            for light in lights.values():
                light.update_ha_state(hass, True)

    update_lights_state(None)

    def light_discovered(service, info):
        """ Called when a light is discovered. """
        platform = get_component(
            ENTITY_ID_FORMAT.format(DISCOVERY_PLATFORMS[service]))

        platform.setup_platform(hass, {}, add_lights, info)

    discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), light_discovered)

    def handle_light_service(service):
        """ Hande a turn light on or off service call. """
        # Get and validate data
        dat = service.data

        # Convert the entity ids to valid light ids
        target_lights = [lights[entity_id] for entity_id
                         in extract_entity_ids(hass, service)
                         if entity_id in lights]

        if not target_lights:
            target_lights = lights.values()

        params = {}

        transition = util.convert(dat.get(ATTR_TRANSITION), int)

        if transition is not None:
            params[ATTR_TRANSITION] = transition

        if service.service == SERVICE_TURN_OFF:
            for light in target_lights:
                # pylint: disable=star-args
                light.turn_off(**params)

        else:
            # Processing extra data for turn light on request

            # We process the profile first so that we get the desired
            # behavior that extra service data attributes overwrite
            # profile values
            profile = profiles.get(dat.get(ATTR_PROFILE))

            if profile:
                *params[ATTR_XY_COLOR], params[ATTR_BRIGHTNESS] = profile

            if ATTR_BRIGHTNESS in dat:
                # We pass in the old value as the default parameter if parsing
                # of the new one goes wrong.
                params[ATTR_BRIGHTNESS] = util.convert(
                    dat.get(ATTR_BRIGHTNESS), int, params.get(ATTR_BRIGHTNESS))

            if ATTR_XY_COLOR in dat:
                try:
                    # xy_color should be a list containing 2 floats
                    xycolor = dat.get(ATTR_XY_COLOR)

                    # Without this check, a xycolor with value '99' would work
                    if not isinstance(xycolor, str):
                        params[ATTR_XY_COLOR] = [float(val) for val in xycolor]

                except (TypeError, ValueError):
                    # TypeError if xy_color is not iterable
                    # ValueError if value could not be converted to float
                    pass

            if ATTR_RGB_COLOR in dat:
                try:
                    # rgb_color should be a list containing 3 ints
                    rgb_color = dat.get(ATTR_RGB_COLOR)

                    if len(rgb_color) == 3:
                        params[ATTR_XY_COLOR] = \
                            util.color_RGB_to_xy(int(rgb_color[0]),
                                                 int(rgb_color[1]),
                                                 int(rgb_color[2]))

                except (TypeError, ValueError):
                    # TypeError if rgb_color is not iterable
                    # ValueError if not all values can be converted to int
                    pass

            if ATTR_FLASH in dat:
                if dat[ATTR_FLASH] == FLASH_SHORT:
                    params[ATTR_FLASH] = FLASH_SHORT

                elif dat[ATTR_FLASH] == FLASH_LONG:
                    params[ATTR_FLASH] = FLASH_LONG

            for light in target_lights:
                # pylint: disable=star-args
                light.turn_on(**params)

        for light in target_lights:
            light.update_ha_state(hass, True)

    # Update light state every 30 seconds
    hass.track_time_change(update_lights_state, second=[0, 30])

    # Listen for light on and light off service calls
    hass.services.register(DOMAIN, SERVICE_TURN_ON,
                           handle_light_service)

    hass.services.register(DOMAIN, SERVICE_TURN_OFF,
                           handle_light_service)

    return True
Example #15
0
def setup(hass, config):
    """ Setup device tracker """
    yaml_path = hass.config.path(YAML_DEVICES)
    csv_path = hass.config.path(CSV_DEVICES)
    if os.path.isfile(csv_path) and not os.path.isfile(yaml_path) and \
       convert_csv_config(csv_path, yaml_path):
        os.remove(csv_path)

    conf = config.get(DOMAIN, {})
    if isinstance(conf, list):
        conf = conf[0]
    consider_home = timedelta(seconds=util.convert(
        conf.get(CONF_CONSIDER_HOME), int, DEFAULT_CONSIDER_HOME))
    track_new = util.convert(conf.get(CONF_TRACK_NEW), bool,
                             DEFAULT_CONF_TRACK_NEW)
    home_range = util.convert(conf.get(CONF_HOME_RANGE), int,
                              DEFAULT_HOME_RANGE)

    devices = load_config(yaml_path, hass, consider_home, home_range)
    tracker = DeviceTracker(hass, consider_home, track_new, home_range,
                            devices)

    def setup_platform(p_type, p_config, disc_info=None):
        """ Setup a device tracker platform. """
        platform = prepare_setup_platform(hass, config, DOMAIN, p_type)
        if platform is None:
            return

        try:
            if hasattr(platform, 'get_scanner'):
                scanner = platform.get_scanner(hass, {DOMAIN: p_config})

                if scanner is None:
                    _LOGGER.error('Error setting up platform %s', p_type)
                    return

                setup_scanner_platform(hass, p_config, scanner, tracker.see)
                return

            if not platform.setup_scanner(hass, p_config, tracker.see):
                _LOGGER.error('Error setting up platform %s', p_type)
        except Exception:  # pylint: disable=broad-except
            _LOGGER.exception('Error setting up platform %s', p_type)

    for p_type, p_config in \
            config_per_platform(config, DOMAIN, _LOGGER):
        setup_platform(p_type, p_config)

    def device_tracker_discovered(service, info):
        """ Called when a device tracker platform is discovered. """
        setup_platform(DISCOVERY_PLATFORMS[service], {}, info)

    discovery.listen(hass, DISCOVERY_PLATFORMS.keys(),
                     device_tracker_discovered)

    def update_stale(now):
        """ Clean up stale devices. """
        tracker.update_stale(now)

    track_utc_time_change(hass, update_stale, second=range(0, 60, 5))

    tracker.setup_group()

    def see_service(call):
        """ Service to see a device. """
        args = {
            key: value
            for key, value in call.data.items()
            if key in (ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME,
                       ATTR_LOCATION_NAME, ATTR_GPS, ATTR_GPS_ACCURACY,
                       ATTR_BATTERY)
        }
        tracker.see(**args)

    descriptions = load_yaml_config_file(
        os.path.join(os.path.dirname(__file__), 'services.yaml'))
    hass.services.register(DOMAIN, SERVICE_SEE, see_service,
                           descriptions.get(SERVICE_SEE))

    return True
Example #16
0
def setup(hass, config):
    """ Exposes light control via statemachine and services. """

    # Load built-in profiles and custom profiles
    profile_paths = [
        os.path.join(os.path.dirname(__file__), LIGHT_PROFILES_FILE),
        hass.get_config_path(LIGHT_PROFILES_FILE)
    ]
    profiles = {}

    for profile_path in profile_paths:

        if os.path.isfile(profile_path):
            with open(profile_path) as inp:
                reader = csv.reader(inp)

                # Skip the header
                next(reader, None)

                try:
                    for profile_id, color_x, color_y, brightness in reader:
                        profiles[profile_id] = (float(color_x), float(color_y),
                                                int(brightness))

                except ValueError:
                    # ValueError if not 4 values per row
                    # ValueError if convert to float/int failed
                    _LOGGER.error("Error parsing light profiles from %s",
                                  profile_path)

                    return False

    # Dict to track entity_id -> lights
    lights = {}

    # Track all lights in a group
    light_group = group.Group(hass, GROUP_NAME_ALL_LIGHTS, user_defined=False)

    def add_lights(new_lights):
        """ Add lights to the component to track. """
        for light in new_lights:
            if light is not None and light not in lights.values():
                light.entity_id = generate_entity_id(ENTITY_ID_FORMAT,
                                                     light.name, lights.keys())

                lights[light.entity_id] = light

                light.update_ha_state(hass)

        light_group.update_tracked_entity_ids(lights.keys())

    for p_type, p_config in config_per_platform(config, DOMAIN, _LOGGER):
        platform = get_component(ENTITY_ID_FORMAT.format(p_type))

        if platform is None:
            _LOGGER.error("Unknown type specified: %s", p_type)

        platform.setup_platform(hass, p_config, add_lights)

    def update_lights_state(now):
        """ Update the states of all the lights. """
        if lights:
            _LOGGER.info("Updating light states")

            for light in lights.values():
                light.update_ha_state(hass, True)

    update_lights_state(None)

    def light_discovered(service, info):
        """ Called when a light is discovered. """
        platform = get_component(
            ENTITY_ID_FORMAT.format(DISCOVERY_PLATFORMS[service]))

        platform.setup_platform(hass, {}, add_lights, info)

    discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), light_discovered)

    def handle_light_service(service):
        """ Hande a turn light on or off service call. """
        # Get and validate data
        dat = service.data

        # Convert the entity ids to valid light ids
        target_lights = [
            lights[entity_id]
            for entity_id in extract_entity_ids(hass, service)
            if entity_id in lights
        ]

        if not target_lights:
            target_lights = lights.values()

        params = {}

        transition = util.convert(dat.get(ATTR_TRANSITION), int)

        if transition is not None:
            params[ATTR_TRANSITION] = transition

        if service.service == SERVICE_TURN_OFF:
            for light in target_lights:
                # pylint: disable=star-args
                light.turn_off(**params)

        else:
            # Processing extra data for turn light on request

            # We process the profile first so that we get the desired
            # behavior that extra service data attributes overwrite
            # profile values
            profile = profiles.get(dat.get(ATTR_PROFILE))

            if profile:
                *params[ATTR_XY_COLOR], params[ATTR_BRIGHTNESS] = profile

            if ATTR_BRIGHTNESS in dat:
                # We pass in the old value as the default parameter if parsing
                # of the new one goes wrong.
                params[ATTR_BRIGHTNESS] = util.convert(
                    dat.get(ATTR_BRIGHTNESS), int, params.get(ATTR_BRIGHTNESS))

            if ATTR_XY_COLOR in dat:
                try:
                    # xy_color should be a list containing 2 floats
                    xycolor = dat.get(ATTR_XY_COLOR)

                    # Without this check, a xycolor with value '99' would work
                    if not isinstance(xycolor, str):
                        params[ATTR_XY_COLOR] = [float(val) for val in xycolor]

                except (TypeError, ValueError):
                    # TypeError if xy_color is not iterable
                    # ValueError if value could not be converted to float
                    pass

            if ATTR_RGB_COLOR in dat:
                try:
                    # rgb_color should be a list containing 3 ints
                    rgb_color = dat.get(ATTR_RGB_COLOR)

                    if len(rgb_color) == 3:
                        params[ATTR_XY_COLOR] = \
                            util.color_RGB_to_xy(int(rgb_color[0]),
                                                 int(rgb_color[1]),
                                                 int(rgb_color[2]))

                except (TypeError, ValueError):
                    # TypeError if rgb_color is not iterable
                    # ValueError if not all values can be converted to int
                    pass

            if ATTR_FLASH in dat:
                if dat[ATTR_FLASH] == FLASH_SHORT:
                    params[ATTR_FLASH] = FLASH_SHORT

                elif dat[ATTR_FLASH] == FLASH_LONG:
                    params[ATTR_FLASH] = FLASH_LONG

            for light in target_lights:
                # pylint: disable=star-args
                light.turn_on(**params)

        for light in target_lights:
            light.update_ha_state(hass, True)

    # Update light state every 30 seconds
    hass.track_time_change(update_lights_state, second=[0, 30])

    # Listen for light on and light off service calls
    hass.services.register(DOMAIN, SERVICE_TURN_ON, handle_light_service)

    hass.services.register(DOMAIN, SERVICE_TURN_OFF, handle_light_service)

    return True
Example #17
0
def setup(hass, config):
    """ Track states and offer events for switches. """
    logger = logging.getLogger(__name__)

    switches = platform_devices_from_config(
        config, DOMAIN, hass, ENTITY_ID_FORMAT, logger)

    @util.Throttle(MIN_TIME_BETWEEN_SCANS)
    def update_states(now):
        """ Update states of all switches. """
        if switches:
            logger.info("Updating switch states")

            for switch in switches.values():
                switch.update_ha_state(hass, True)

    update_states(None)

    # Track all switches in a group
    switch_group = group.Group(
        hass, GROUP_NAME_ALL_SWITCHES, switches.keys(), False)

    def switch_discovered(service, info):
        """ Called when a switch is discovered. """
        platform = get_component("{}.{}".format(
            DOMAIN, DISCOVERY_PLATFORMS[service]))

        discovered = platform.devices_discovered(hass, config, info)

        for switch in discovered:
            if switch is not None and switch not in switches.values():
                switch.entity_id = generate_entity_id(
                    ENTITY_ID_FORMAT, switch.name, switches.keys())

                switches[switch.entity_id] = switch

                switch.update_ha_state(hass)

        switch_group.update_tracked_entity_ids(switches.keys())

    discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), switch_discovered)

    def handle_switch_service(service):
        """ Handles calls to the switch services. """
        target_switches = [switches[entity_id] for entity_id
                           in extract_entity_ids(hass, service)
                           if entity_id in switches]

        if not target_switches:
            target_switches = switches.values()

        for switch in target_switches:
            if service.service == SERVICE_TURN_ON:
                switch.turn_on()
            else:
                switch.turn_off()

            switch.update_ha_state(hass)

    # Update state every 30 seconds
    hass.track_time_change(update_states, second=[0, 30])

    hass.services.register(DOMAIN, SERVICE_TURN_OFF, handle_switch_service)

    hass.services.register(DOMAIN, SERVICE_TURN_ON, handle_switch_service)

    return True