def async_stop_program_service(call):

        for program in conf.get(ATTR_PROGRAMS):
            y_irrigation_id = cv.slugify(program.get(ATTR_IRRIG_ID))
            entity_id = ENTITY_ID_FORMAT.format(y_irrigation_id)
            entity = component.get_entity(entity_id)
            if entity:
                target_irrigation = [entity]
                tasks = [
                    irrigation.async_stop_program()
                    for irrigation in target_irrigation
                ]
                if tasks:
                    yield from asyncio.wait(tasks, loop=hass.loop)
            else:
                _LOGGER.error('irrigation program not found: %s', entity_id)

        for zone in conf.get(ATTR_ZONES):
            y_irrigation_id = cv.slugify(zone.get(ATTR_IRRIG_ID))
            entity_id = ZONE_ENTITY_ID_FORMAT.format(y_irrigation_id)
            entity = component.get_entity(entity_id)
            if entity:
                target_irrigation = [entity]
                tasks = [
                    irrigation_zone.async_stop_zone()
                    for irrigation_zone in target_irrigation
                ]
                if tasks:
                    yield from asyncio.wait(tasks, loop=hass.loop)
            else:
                _LOGGER.error('irrigation_zone not found: %s', entity_id)
Example #2
0
    async def async_step_init(self, info=None):
        """Handle config flow initiation."""
        if info:
            name = info[CONF_NAME]
            device = info[CONF_DEVICE]
            gw_id = cv.slugify(info.get(CONF_ID, name))

            entries = [
                e.data for e in self.hass.config_entries.async_entries(DOMAIN)
            ]

            if gw_id in [e[CONF_ID] for e in entries]:
                return self._show_form({"base": "id_exists"})

            if device in [e[CONF_DEVICE] for e in entries]:
                return self._show_form({"base": "already_configured"})

            async def test_connection():
                """Try to connect to the OpenTherm Gateway."""
                otgw = pyotgw.pyotgw()
                status = await otgw.connect(self.hass.loop, device)
                await otgw.disconnect()
                return status.get(pyotgw.OTGW_ABOUT)

            try:
                res = await asyncio.wait_for(test_connection(), timeout=10)
            except asyncio.TimeoutError:
                return self._show_form({"base": "timeout"})
            except SerialException:
                return self._show_form({"base": "serial_error"})

            if res:
                return self._create_entry(gw_id, name, device)

        return self._show_form()
Example #3
0
def load_config(path: str, hass: HomeAssistantType, consider_home: timedelta):
    """Load devices from YAML configuration file."""
    dev_schema = vol.Schema({
        vol.Required('name'): cv.string,
        vol.Optional('track', default=False): cv.boolean,
        vol.Optional('mac', default=None): vol.Any(None, vol.All(cv.string,
                                                                 vol.Upper)),
        vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE): cv.boolean,
        vol.Optional('gravatar', default=None): vol.Any(None, cv.string),
        vol.Optional('picture', default=None): vol.Any(None, cv.string),
        vol.Optional(CONF_CONSIDER_HOME, default=consider_home): vol.All(
            cv.time_period, cv.positive_timedelta)
    })
    try:
        result = []
        devices = load_yaml_config_file(path)
        for dev_id, device in devices.items():
            try:
                device = dev_schema(device)
                device['dev_id'] = cv.slugify(dev_id)
            except vol.Invalid as exp:
                log_exception(exp, dev_id, devices)
            else:
                result.append(Device(hass, **device))
        return result
    except (HomeAssistantError, FileNotFoundError):
        # When YAML file could not be loaded/did not contain a dict
        return []
Example #4
0
def load_config(path: str, hass: HomeAssistantType, consider_home: timedelta):
    """Load devices from YAML configuration file."""
    dev_schema = vol.Schema({
        vol.Required('name'):
        cv.string,
        vol.Optional('track', default=False):
        cv.boolean,
        vol.Optional('mac', default=None):
        vol.Any(None, vol.All(cv.string, vol.Upper)),
        vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE):
        cv.boolean,
        vol.Optional('gravatar', default=None):
        vol.Any(None, cv.string),
        vol.Optional('picture', default=None):
        vol.Any(None, cv.string),
        vol.Optional(CONF_CONSIDER_HOME, default=consider_home):
        vol.All(cv.time_period, cv.positive_timedelta)
    })
    try:
        result = []
        devices = load_yaml_config_file(path)
        for dev_id, device in devices.items():
            try:
                device = dev_schema(device)
                device['dev_id'] = cv.slugify(dev_id)
            except vol.Invalid as exp:
                log_exception(exp, dev_id, devices)
            else:
                result.append(Device(hass, **device))
        return result
    except (HomeAssistantError, FileNotFoundError):
        # When YAML file could not be loaded/did not contain a dict
        return []
Example #5
0
        async def do_enable(name):
            """Enable the named Pi-Hole."""
            slug = cv.slugify(name)
            pi_hole = hass.data[DOMAIN][slug]

            LOGGER.debug("Enabling Pi-hole '%s' (%s)", name, pi_hole.api.host)
            await pi_hole.api.enable()
Example #6
0
    def __init__(self, hass, name, config):
        """Initialize the Plant component."""
        self._config = config
        self._sensors = dict()
        self._readings = dict()
        self._unit_of_measurement = dict()
        self._state = None
        self._name = name
        self._problems = PROBLEM_NONE
        self._sensor_basename = "{}.{}{}_".format(
            SENSOR_DOMAIN,
            (self._config[CONF_DISCOVERY_PREFIX] +
             "_" if self._config[CONF_DISCOVERY_PREFIX] else ""),
            cv.slugify(self._name).lower())
        _LOGGER.debug("Sensors starting with %s will be added to %s",
                      self._sensor_basename, self._name)
        for reading, entity_id in self._config.get("sensors", {}).items():
            _LOGGER.debug(
                "Adding statically defined sensor %s for reading %s on %s",
                entity_id, reading, self._name)
            self._sensors[entity_id] = reading
            self._add_reading(reading, entity_id)

        self._conf_check_days = self._config[CONF_CHECK_DAYS]
        self._brightness_history = DailyHistory(self._conf_check_days)
    def _update_members(self, members, members_updated):
        for member in members:
            member_id = member['id']
            if member_id in members_updated:
                continue
            members_updated.append(member_id)
            err_key = 'Member data'
            try:
                first = member.get('firstName')
                last = member.get('lastName')
                if first and last:
                    full_name = ' '.join([first, last])
                else:
                    full_name = first or last
                slug_name = cv.slugify(full_name)
                include_member = _include_name(self._members_filter, slug_name)
                dev_id = self._dev_id(slug_name)
                if member_id not in self._members_logged:
                    self._members_logged.add(member_id)
                    _LOGGER.debug('%s -> %s: will%s be tracked, id=%s',
                                  full_name, dev_id,
                                  '' if include_member else ' NOT', member_id)
                sharing = bool(int(member['features']['shareLocation']))
            except (KeyError, TypeError, ValueError, vol.Invalid):
                self._err(err_key, member)
                continue
            self._ok(err_key)

            if include_member and sharing:
                self._update_member(member, dev_id)
    def _update_members(self, members, members_updated):
        for member in members:
            member_id = member["id"]
            if member_id in members_updated:
                continue
            err_key = "Member data"
            try:
                first = member.get("firstName")
                last = member.get("lastName")
                if first and last:
                    full_name = " ".join([first, last])
                else:
                    full_name = first or last
                slug_name = cv.slugify(full_name)
                include_member = _include_name(self._members_filter, slug_name)
                dev_id = self._dev_id(slug_name)
                if member_id not in self._members_logged:
                    self._members_logged.add(member_id)
                    _LOGGER.debug(
                        "%s -> %s: will%s be tracked, id=%s",
                        full_name,
                        dev_id,
                        "" if include_member else " NOT",
                        member_id,
                    )
                sharing = bool(int(member["features"]["shareLocation"]))
            except (KeyError, TypeError, ValueError, vol.Invalid):
                self._err(err_key, member)
                continue
            self._ok(err_key)

            if include_member and sharing:
                members_updated.append(member_id)
                self._update_member(member, dev_id)
Example #9
0
async def async_load_config(path: str, hass: HomeAssistantType,
                            config: ConfigType, async_add_entities):
    """Load devices from YAML configuration file.
    This method is a coroutine.
    """
    dev_schema = vol.Schema({
        vol.Required('dev_id'):
        cv.string,
        vol.Optional(CONF_NAME, default=''):
        cv.string,
        vol.Optional(CONF_DEVICE_CLASS, default='motion'):
        DEVICE_CLASSES_SCHEMA
        #        vol.Optional(CONF_ICON, default=None): vol.Any(None, cv.icon),
        #        vol.Optional('track', default=False): cv.boolean,
        #        vol.Optional(CONF_MAC, default=None):
        #        vol.Any(None, vol.All(cv.string, vol.Upper)),
        #        vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE): cv.boolean,
        #        vol.Optional('gravatar', default=None): vol.Any(None, cv.string),
        #        vol.Optional('picture', default=None): vol.Any(None, cv.string),
        #        vol.Optional(CONF_CONSIDER_HOME, default=consider_home): vol.All(
        #            cv.time_period, cv.positive_timedelta),
    })
    result = []
    try:
        _LOGGER.debug("async_load_config(): reading config file %s", path)

        devices = await hass.async_add_job(load_yaml_config_file, path)

        _LOGGER.debug(
            'async_load_config(): devices loaded from config file: %s',
            devices)

    except HomeAssistantError as err:
        _LOGGER.error("async_load_config(): unable to load %s: %s", path,
                      str(err))
        return []
    except FileNotFoundError as err:
        _LOGGER.debug("async_load_config(): file %s could not be found: %s",
                      path, str(err))
        return []

    for dev_id, device in devices.items():
        # Deprecated option. We just ignore it to avoid breaking change
        #        device.pop('vendor', None)
        try:
            device = dev_schema(device)
            device['dev_id'] = cv.slugify(dev_id)
        except vol.Invalid as exp:
            async_log_exception(exp, dev_id, devices, hass)
        else:
            _LOGGER.debug('device: %s', device)
            dev = JablotronSensor(hass, **device)
            result.append(dev)
            """ Create sensors for each device in devices """
            #            device = JablotronSensor(hass, dev_id)
            async_add_entities([dev])
    return result
Example #10
0
        async def do_disable(name):
            """Disable the named Pi-Hole."""
            slug = cv.slugify(name)
            pi_hole = hass.data[DOMAIN][slug]

            LOGGER.debug(
                "Disabling Pi-hole '%s' (%s) for %d seconds",
                name,
                pi_hole.api.host,
                duration,
            )
            await pi_hole.api.disable(duration)
Example #11
0
 def async_stop_switches(call):
     _LOGGER.info('async_stop_switches')
     for zone in conf.get(ATTR_ZONES):
         irrigation_id = cv.slugify(zone.get(ATTR_IRRIG_ID))
         entity_id = ZONE_ENTITY_ID_FORMAT.format(irrigation_id)
         entity = component.get_entity(entity_id)
         if entity:
             target_irrigation = [entity]
             tasks = [irrigation_zone.async_stop_switch()
                      for irrigation_zone in target_irrigation]
             if tasks:
                 yield from asyncio.wait(tasks, loop=hass.loop)
         else:
             _LOGGER.error('irrigation_zone not found: %s', entity_id)
Example #12
0
def async_load_config(path: str, hass: HomeAssistantType,
                      consider_home: timedelta):
    """Load devices from YAML configuration file.

    This method is a coroutine.
    """
    dev_schema = vol.Schema({
        vol.Required(CONF_NAME):
        cv.string,
        vol.Optional(CONF_ICON, default=None):
        vol.Any(None, cv.icon),
        vol.Optional('track', default=False):
        cv.boolean,
        vol.Optional(CONF_MAC, default=None):
        vol.Any(None, vol.All(cv.string, vol.Upper)),
        vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE):
        cv.boolean,
        vol.Optional('gravatar', default=None):
        vol.Any(None, cv.string),
        vol.Optional('picture', default=None):
        vol.Any(None, cv.string),
        vol.Optional(CONF_CONSIDER_HOME, default=consider_home):
        vol.All(cv.time_period, cv.positive_timedelta),
    })
    try:
        result = []
        try:
            devices = yield from hass.async_add_job(load_yaml_config_file,
                                                    path)
        except HomeAssistantError as err:
            _LOGGER.error("Unable to load %s: %s", path, str(err))
            return []

        for dev_id, device in devices.items():
            # Deprecated option. We just ignore it to avoid breaking change
            device.pop('vendor', None)
            try:
                device = dev_schema(device)
                device['dev_id'] = cv.slugify(dev_id)
            except vol.Invalid as exp:
                async_log_exception(exp, dev_id, devices, hass)
            else:
                result.append(Device(hass, **device))
        return result
    except (HomeAssistantError, FileNotFoundError):
        # When YAML file could not be loaded/did not contain a dict
        return []
 def __init__(self, config):
     """Assumes config confirms to const.MOTION_SCHEMA"""
     self._url = config[CONF_URL]
     if self._url.endswith('/'): self._url = self._url[0:-1]
     self._unique_id = cv.slugify(self._url)
     self._username = config[CONF_USERNAME]
     self._password = config[CONF_PASSWORD]
     self._auth = config[CONF_AUTHENTICATION]
     self._pwhash = hashlib.sha1(self._password.encode('utf-8')).hexdigest()
     self._session = requests.Session()
     self._cameras = {}
     o = urlparse.urlparse(self._url)
     self._host = o.scheme + '://' + o.hostname
     self._path = o.path
     _LOGGER.info(
         f"step motion created API {self.unique_id} -> {self._host} {self._path}"
     )
Example #14
0
def async_load_config(path: str, hass: HomeAssistantType,
                      consider_home: timedelta):
    """Load devices from YAML configuration file.

    This method is a coroutine.
    """
    dev_schema = vol.Schema({
        vol.Required('name'):
        cv.string,
        vol.Optional('track', default=False):
        cv.boolean,
        vol.Optional('mac', default=None):
        vol.Any(None, vol.All(cv.string, vol.Upper)),
        vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE):
        cv.boolean,
        vol.Optional('gravatar', default=None):
        vol.Any(None, cv.string),
        vol.Optional('picture', default=None):
        vol.Any(None, cv.string),
        vol.Optional(CONF_CONSIDER_HOME, default=consider_home):
        vol.All(cv.time_period, cv.positive_timedelta),
        vol.Optional('vendor', default=None):
        vol.Any(None, cv.string),
    })
    try:
        result = []
        try:
            devices = yield from hass.loop.run_in_executor(
                None, load_yaml_config_file, path)
        except HomeAssistantError as err:
            _LOGGER.error('Unable to load %s: %s', path, str(err))
            return []

        for dev_id, device in list(devices.items()):
            try:
                device = dev_schema(device)
                device['dev_id'] = cv.slugify(dev_id)
            except vol.Invalid as exp:
                async_log_exception(exp, dev_id, devices, hass)
            else:
                result.append(Device(hass, **device))
        return result
    except (HomeAssistantError, FileNotFoundError):
        # When YAML file could not be loaded/did not contain a dict
        return []
Example #15
0
    def ensure_api_token(call_data):
        """Ensure the Pi-Hole to be enabled/disabled has a api_token configured."""
        data = get_data()
        if SERVICE_DISABLE_ATTR_NAME not in call_data:
            for slug in data:
                call_data[SERVICE_DISABLE_ATTR_NAME] = data[slug].name
                ensure_api_token(call_data)

            call_data[SERVICE_DISABLE_ATTR_NAME] = None
        else:
            slug = cv.slugify(call_data[SERVICE_DISABLE_ATTR_NAME])

            if (data[slug]).api.api_token is None:
                raise vol.Invalid(
                    "Pi-hole '{}' must have an api_key provided in configuration to be enabled."
                    .format(pi_hole.name))

        return call_data
Example #16
0
async def async_load_config(path: str, hass: HomeAssistant,
                            consider_home: timedelta) -> list[Device]:
    """Load devices from YAML configuration file.

    This method is a coroutine.
    """
    dev_schema = vol.Schema({
        vol.Required(CONF_NAME):
        cv.string,
        vol.Optional(CONF_ICON, default=None):
        vol.Any(None, cv.icon),
        vol.Optional("track", default=False):
        cv.boolean,
        vol.Optional(CONF_MAC, default=None):
        vol.Any(None, vol.All(cv.string, vol.Upper)),
        vol.Optional("gravatar", default=None):
        vol.Any(None, cv.string),
        vol.Optional("picture", default=None):
        vol.Any(None, cv.string),
        vol.Optional(CONF_CONSIDER_HOME, default=consider_home):
        vol.All(cv.time_period, cv.positive_timedelta),
    })
    result: list[Device] = []
    try:
        devices = await hass.async_add_executor_job(load_yaml_config_file,
                                                    path)
    except HomeAssistantError as err:
        LOGGER.error("Unable to load %s: %s", path, str(err))
        return []
    except FileNotFoundError:
        return []

    for dev_id, device in devices.items():
        # Deprecated option. We just ignore it to avoid breaking change
        device.pop("vendor", None)
        device.pop("hide_if_away", None)
        try:
            device = dev_schema(device)
            device["dev_id"] = cv.slugify(dev_id)
        except vol.Invalid as exp:
            async_log_exception(exp, dev_id, devices, hass)
        else:
            result.append(Device(hass, **device))
    return result
Example #17
0
async def _get_legacy_devices(hass: HomeAssistant) -> dict:
    legacy_devices = {}

    try:
        devices = await hass.async_add_executor_job(load_yaml_config_file, hass.config.path(LEGACY_YAML_DEVICES))
    except HomeAssistantError:
        return {}
    except FileNotFoundError:
        return {}

    for dev_id, device in devices.items():
        try:
            device = legacy_schema(device)
            device["dev_id"] = cv.slugify(dev_id)
        except vol.Invalid:
            continue
        else:
            legacy_devices[device["mac"]] = dict(device)

    return legacy_devices
Example #18
0
async def async_load_config(path: str, hass: HomeAssistantType,
                            consider_home: timedelta):
    """Load devices from YAML configuration file.

    This method is a coroutine.
    """
    dev_schema = vol.Schema({
        vol.Required(CONF_NAME): cv.string,
        vol.Optional(CONF_ICON, default=None): vol.Any(None, cv.icon),
        vol.Optional('track', default=False): cv.boolean,
        vol.Optional(CONF_MAC, default=None):
            vol.Any(None, vol.All(cv.string, vol.Upper)),
        vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE): cv.boolean,
        vol.Optional('gravatar', default=None): vol.Any(None, cv.string),
        vol.Optional('picture', default=None): vol.Any(None, cv.string),
        vol.Optional(CONF_CONSIDER_HOME, default=consider_home): vol.All(
            cv.time_period, cv.positive_timedelta),
    })
    try:
        result = []
        try:
            devices = await hass.async_add_job(
                load_yaml_config_file, path)
        except HomeAssistantError as err:
            _LOGGER.error("Unable to load %s: %s", path, str(err))
            return []

        for dev_id, device in devices.items():
            # Deprecated option. We just ignore it to avoid breaking change
            device.pop('vendor', None)
            try:
                device = dev_schema(device)
                device['dev_id'] = cv.slugify(dev_id)
            except vol.Invalid as exp:
                async_log_exception(exp, dev_id, devices, hass)
            else:
                result.append(Device(hass, **device))
        return result
    except (HomeAssistantError, FileNotFoundError):
        # When YAML file could not be loaded/did not contain a dict
        return []
Example #19
0
def async_load_config(path: str, hass: HomeAssistantType,
                      consider_home: timedelta):
    """Load devices from YAML configuration file.

    This method is a coroutine.
    """
    dev_schema = vol.Schema({
        vol.Required('name'): cv.string,
        vol.Optional('track', default=False): cv.boolean,
        vol.Optional('mac', default=None): vol.Any(None, vol.All(cv.string,
                                                                 vol.Upper)),
        vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE): cv.boolean,
        vol.Optional('gravatar', default=None): vol.Any(None, cv.string),
        vol.Optional('picture', default=None): vol.Any(None, cv.string),
        vol.Optional(CONF_CONSIDER_HOME, default=consider_home): vol.All(
            cv.time_period, cv.positive_timedelta),
        vol.Optional('vendor', default=None): vol.Any(None, cv.string),
    })
    try:
        result = []
        try:
            devices = yield from hass.loop.run_in_executor(
                None, load_yaml_config_file, path)
        except HomeAssistantError as err:
            _LOGGER.error('Unable to load %s: %s', path, str(err))
            return []

        for dev_id, device in devices.items():
            try:
                device = dev_schema(device)
                device['dev_id'] = cv.slugify(dev_id)
            except vol.Invalid as exp:
                async_log_exception(exp, dev_id, devices, hass)
            else:
                result.append(Device(hass, **device))
        return result
    except (HomeAssistantError, FileNotFoundError):
        # When YAML file could not be loaded/did not contain a dict
        return []
Example #20
0
def coerce_slug(config):
    """Coerce the name of the Pi-Hole into a slug."""
    config[CONF_SLUG] = cv.slugify(config[CONF_NAME])
    return config
Example #21
0
async def async_setup(hass, config):

    @asyncio.coroutine
    def async_run_program_service(call):
        _LOGGER.info('async_run_program_service')
        entity_id = call.data.get(CONST_ENTITY)

        """ stop any running zones  before starting a new program"""
        hass.services.async_call(DOMAIN,
                                 'stop_programs',
                                 {})

        DATA = {}
        entity = component.get_entity(entity_id)
        if entity:
            target_irrigation = [entity]
            tasks = [irrigation.async_run_program(DATA)
                     for irrigation in target_irrigation]
            if tasks:
                yield from asyncio.wait(tasks, loop=hass.loop)
        else:
            _LOGGER.error('irrigation program not found: %s', entity_id)
    """ END async_run_program_service """

    @asyncio.coroutine
    def async_stop_program_service(call):
        _LOGGER.info('async_stop_program_service')
        entity_id = call.data.get(CONST_ENTITY)
        entity = component.get_entity(entity_id)
        if entity:
            target_irrigation = [entity]
            tasks = [irrigation.async_stop_program()
                     for irrigation in target_irrigation]
            if tasks:
                yield from asyncio.wait(tasks, loop=hass.loop)
        else:
            _LOGGER.error('irrigation program not found: %s',
                          entity_id)
    """ END async_stop_program_service """

    @asyncio.coroutine
    def async_run_zone_service(call):
        _LOGGER.info('async_run_zone_service')
        entity_id = call.data.get(CONST_ENTITY)
        duration = call.data.get(ATTR_DURATION, 0)

        DATA = {ATTR_DURATION: duration}
        entity = component.get_entity(entity_id)
        if entity:
            target_irrigation = [entity]
            tasks = [irrigation_zone.async_run_zone(DATA)
                     for irrigation_zone in target_irrigation]
            if tasks:
                yield from asyncio.wait(tasks, loop=hass.loop)
        else:
            _LOGGER.error('irrigation_zone not found: %s', entity_id)
    """ END async_run_zone_service """

    @asyncio.coroutine
    def async_stop_zone_service(call):
        _LOGGER.info('async_stop_zone_service')
        entity_id = call.data.get(CONST_ENTITY)
        entity = component.get_entity(entity_id)
        if entity:
            target_irrigation = [entity]
            tasks = [irrigation_zone.async_stop_zone()
                     for irrigation_zone in target_irrigation]
            if tasks:
                yield from asyncio.wait(tasks, loop=hass.loop)
        else:
            _LOGGER.error('irrigation_zone not found: %s',
                          entity_id)
    """ END async_stop_zone_service """

    @asyncio.coroutine
    def async_stop_programs_service(call):
        _LOGGER.info('async_stop_programs_service')
        for program in conf.get(ATTR_PROGRAMS):
            irrigation_id = cv.slugify(program.get(ATTR_IRRIG_ID))
            entity_id = ENTITY_ID_FORMAT.format(irrigation_id)
            entity = component.get_entity(entity_id)
            if entity:
                target_irrigation = [entity]
                tasks = [irrigation.async_stop_program()
                         for irrigation in target_irrigation]
                if tasks:
                    yield from asyncio.wait(tasks, loop=hass.loop)
            else:
                _LOGGER.error('irrigation program not found: %s',
                              entity_id)

        for zone in conf.get(ATTR_ZONES):
            irrigation_id = cv.slugify(zone.get(ATTR_IRRIG_ID))
            entity_id = ZONE_ENTITY_ID_FORMAT.format(irrigation_id)
            entity = component.get_entity(entity_id)
            if entity:
                target_irrigation = [entity]
                tasks = [irrigation_zone.async_stop_zone()
                         for irrigation_zone in target_irrigation]
                if tasks:
                    yield from asyncio.wait(tasks, loop=hass.loop)
            else:
                _LOGGER.error('irrigation_zone not found: %s',
                              entity_id)
    """ END async_stop_programs_service """

    @asyncio.coroutine
    def async_stop_switches(call):
        _LOGGER.info('async_stop_switches')
        for zone in conf.get(ATTR_ZONES):
            irrigation_id = cv.slugify(zone.get(ATTR_IRRIG_ID))
            entity_id = ZONE_ENTITY_ID_FORMAT.format(irrigation_id)
            entity = component.get_entity(entity_id)
            if entity:
                target_irrigation = [entity]
                tasks = [irrigation_zone.async_stop_switch()
                         for irrigation_zone in target_irrigation]
                if tasks:
                    yield from asyncio.wait(tasks, loop=hass.loop)
            else:
                _LOGGER.error('irrigation_zone not found: %s', entity_id)
    """ END async_stop_switches """

    """ create the entities and time tracking on setup of the component """
    conf = config[DOMAIN]
    component = EntityComponent(_LOGGER, DOMAIN, hass)

    """ parse progams """
    programentities = []
    for program in conf.get(ATTR_PROGRAMS):
        irrigation_id = cv.slugify(program.get(ATTR_IRRIG_ID))
        template = program.get(ATTR_TEMPLATE)
        if template is not None:
            template.hass = hass
            p_entity = ENTITY_ID_FORMAT.format(irrigation_id)
            programentities.append(Irrigation(p_entity,
                                              program,
                                              component))
            _LOGGER.info('Irrigation %s added', irrigation_id)
            if(not program.get(ATTR_ENABLED)):
                _LOGGER.warn('Irrigation %s disabled', irrigation_id)
    await component.async_add_entities(programentities)

    """ parse zones """
    zoneentities = []
    for zone in conf.get(ATTR_ZONES):
        irrigation_id = cv.slugify(zone.get(ATTR_IRRIG_ID))
        p_entity = ZONE_ENTITY_ID_FORMAT.format(irrigation_id)
        zoneentities.append(IrrigationZone(p_entity,
                                           zone))
        _LOGGER.info('Zone %s added', p_entity)
    await component.async_add_entities(zoneentities)

    """ define services """
    hass.services.async_register(DOMAIN,
                                 'run_program',
                                 async_run_program_service)
    hass.services.async_register(DOMAIN,
                                 'stop_program',
                                 async_stop_program_service)
    hass.services.async_register(DOMAIN,
                                 'run_zone',
                                 async_run_zone_service)
    hass.services.async_register(DOMAIN,
                                 'stop_zone',
                                 async_stop_zone_service)
    hass.services.async_register(DOMAIN,
                                 'stop_programs',
                                 async_stop_programs_service)

    return True
async def async_setup(hass, config):
    @asyncio.coroutine
    def async_run_program_service(call):
        try:
            perform_eval = call.data.get(ATTR_EVAL, False)
            entity_id = call.data.get(CONST_ENTITY)
        except:
            perform_eval = call.get(ATTR_EVAL, False)
            entity_id = call.get(CONST_ENTITY)
        """ stop any running zones  before starting a new program"""
        hass.services.async_call(DOMAIN, 'stop_programs', {ATTR_EVAL: True})

        entity = component.get_entity(entity_id)
        if entity:
            target_irrigation = [entity]
            tasks = [
                irrigation.async_run_program(perform_eval)
                for irrigation in target_irrigation
            ]
            if tasks:
                yield from asyncio.wait(tasks, loop=hass.loop)
        else:
            _LOGGER.error('irrigation program not found: %s', entity_id)

    """ END async_run_program_service """

    @asyncio.coroutine
    def async_run_zone_service(call):
        """ called from manually service """
        entity_id = call.data.get(CONST_ENTITY)
        y_water = call.data.get(ATTR_WATER, 0)
        y_wait = call.data.get(ATTR_WAIT, 0)
        y_repeat = call.data.get(ATTR_REPEAT, 0)
        y_ignore = call.data.get(ATTR_EVAL, False)

        DATA = {
            ATTR_WATER: y_water,
            ATTR_WAIT: y_wait,
            ATTR_REPEAT: y_repeat,
            ATTR_EVAL: y_ignore
        }

        entity = component.get_entity(entity_id)
        if entity:
            target_irrigation = [entity]
            tasks = [
                irrigation_zone.async_run_zone(DATA)
                for irrigation_zone in target_irrigation
            ]
            if tasks:
                yield from asyncio.wait(tasks, loop=hass.loop)
        else:
            _LOGGER.error('irrigation_zone not found: %s', entity_id)

    """ END async_run_zone_service """

    @asyncio.coroutine
    def async_stop_program_service(call):

        for program in conf.get(ATTR_PROGRAMS):
            y_irrigation_id = cv.slugify(program.get(ATTR_IRRIG_ID))
            entity_id = ENTITY_ID_FORMAT.format(y_irrigation_id)
            entity = component.get_entity(entity_id)
            if entity:
                target_irrigation = [entity]
                tasks = [
                    irrigation.async_stop_program()
                    for irrigation in target_irrigation
                ]
                if tasks:
                    yield from asyncio.wait(tasks, loop=hass.loop)
            else:
                _LOGGER.error('irrigation program not found: %s', entity_id)

        for zone in conf.get(ATTR_ZONES):
            y_irrigation_id = cv.slugify(zone.get(ATTR_IRRIG_ID))
            entity_id = ZONE_ENTITY_ID_FORMAT.format(y_irrigation_id)
            entity = component.get_entity(entity_id)
            if entity:
                target_irrigation = [entity]
                tasks = [
                    irrigation_zone.async_stop_zone()
                    for irrigation_zone in target_irrigation
                ]
                if tasks:
                    yield from asyncio.wait(tasks, loop=hass.loop)
            else:
                _LOGGER.error('irrigation_zone not found: %s', entity_id)

    """ END async_stop_program_service """

    @asyncio.coroutine
    def async_stop_switches(call):
        for zone in conf.get(ATTR_ZONES):
            y_irrigation_id = cv.slugify(zone.get(ATTR_IRRIG_ID))

            entity_id = ZONE_ENTITY_ID_FORMAT.format(y_irrigation_id)
            entity = component.get_entity(entity_id)
            if entity:
                target_irrigation = [entity]
                tasks = [
                    irrigation_zone.async_stop_switch()
                    for irrigation_zone in target_irrigation
                ]
                if tasks:
                    yield from asyncio.wait(tasks, loop=hass.loop)
            else:
                _LOGGER.error('irrigation_zone not found: %s', entity_id)

    """ END async_stop_switches """
    """ create the entities and time tracking on setup of the component """
    conf = config[DOMAIN]
    component = EntityComponent(_LOGGER, DOMAIN, hass)
    entities = []
    zoneentities = []

    for program in conf.get(ATTR_PROGRAMS):
        y_irrigation_id = cv.slugify(program.get(ATTR_IRRIG_ID))
        """ Used same model as Template Sensor """
        entity_ids = set()
        invalid_templates = []

        template = program.get(ATTR_TEMPLATE)

        if template is None:
            continue
        template.hass = hass

        template_entity_ids = template.extract_entities()
        if template_entity_ids == MATCH_ALL:
            entity_ids = MATCH_ALL
            # Cut off _template from name
            invalid_templates.append(tpl_name[:-9])
        elif entity_ids != MATCH_ALL:
            entity_ids |= set(template_entity_ids)

        if invalid_templates:
            _LOGGER.warning(
                'Irrigation %s has no entity ids configured to track nor'
                ' were we able to extract the entities to track from the %s '
                'template.'
                'manually.', device, ', '.join(invalid_templates))

        entity_ids = list(entity_ids)

        p_entity = ENTITY_ID_FORMAT.format(y_irrigation_id)
        entities.append(Irrigation(p_entity, program, entity_ids, component))

    for zone in conf.get(ATTR_ZONES):
        y_irrigation_id = cv.slugify(zone.get(ATTR_IRRIG_ID))
        p_entity = ZONE_ENTITY_ID_FORMAT.format(y_irrigation_id)
        zoneentities.append(IrrigationZone(p_entity, zone))

    await component.async_add_entities(entities)
    await component.async_add_entities(zoneentities)
    """ define services """
    hass.services.async_register(DOMAIN, 'run_program',
                                 async_run_program_service)
    hass.services.async_register(DOMAIN, 'run_zone', async_run_zone_service)
    hass.services.async_register(DOMAIN, 'stop_programs',
                                 async_stop_program_service)

    return True