Пример #1
0
def test_generate_entity_id_given_keys():
    """Test generating an entity id given current ids."""
    fmt = 'test.{}'
    assert entity.generate_entity_id(
        fmt, 'overwrite hidden true', current_ids=[
            'test.overwrite_hidden_true']) == 'test.overwrite_hidden_true_2'
    assert entity.generate_entity_id(
        fmt, 'overwrite hidden true', current_ids=[
            'test.another_entity']) == 'test.overwrite_hidden_true'
Пример #2
0
 def test_generate_entity_id_given_keys(self):
     """Test generating an entity id given current ids."""
     fmt = 'test.{}'
     self.assertEqual(
         'test.overwrite_hidden_true_2',
         entity.generate_entity_id(
             fmt, 'overwrite hidden true',
             current_ids=['test.overwrite_hidden_true']))
     self.assertEqual(
         'test.overwrite_hidden_true',
         entity.generate_entity_id(fmt, 'overwrite hidden true',
                                   current_ids=['test.another_entity']))
Пример #3
0
def setup(hass, config):
    """ Setup zone. """
    entities = set()

    for key in extract_domain_configs(config, DOMAIN):
        entries = config[key]
        if not isinstance(entries, list):
            entries = entries,

        for entry in entries:
            name = entry.get(CONF_NAME, DEFAULT_NAME)
            latitude = entry.get(ATTR_LATITUDE)
            longitude = entry.get(ATTR_LONGITUDE)
            radius = entry.get(ATTR_RADIUS, DEFAULT_RADIUS)
            icon = entry.get(ATTR_ICON)
            passive = entry.get(ATTR_PASSIVE, DEFAULT_PASSIVE)

            if None in (latitude, longitude):
                logging.getLogger(__name__).error(
                    'Each zone needs a latitude and longitude.')
                continue

            zone = Zone(hass, name, latitude, longitude, radius, icon, passive)
            zone.entity_id = generate_entity_id(ENTITY_ID_FORMAT, name,
                                                entities)
            zone.update_ha_state()
            entities.add(zone.entity_id)

    if ENTITY_ID_HOME not in entities:
        zone = Zone(hass, hass.config.location_name, hass.config.latitude,
                    hass.config.longitude, DEFAULT_RADIUS, ICON_HOME, False)
        zone.entity_id = ENTITY_ID_HOME
        zone.update_ha_state()

    return True
Пример #4
0
 def test_generate_entity_id_given_hass(self):
     """Test generating an entity id given hass object."""
     fmt = 'test.{}'
     self.assertEqual(
         'test.overwrite_hidden_true_2',
         entity.generate_entity_id(fmt, 'overwrite hidden true',
                                   hass=self.hass))
    def create_service(call):
        """Handle a create notification service call."""
        title = call.data.get(ATTR_TITLE)
        message = call.data.get(ATTR_MESSAGE)
        notification_id = call.data.get(ATTR_NOTIFICATION_ID)

        if notification_id is not None:
            entity_id = ENTITY_ID_FORMAT.format(slugify(notification_id))
        else:
            entity_id = generate_entity_id(ENTITY_ID_FORMAT, DEFAULT_OBJECT_ID,
                                           hass=hass)
        attr = {}
        if title is not None:
            try:
                title = template.render(hass, title)
            except TemplateError as ex:
                _LOGGER.error('Error rendering title %s: %s', title, ex)

            attr[ATTR_TITLE] = title

        try:
            message = template.render(hass, message)
        except TemplateError as ex:
            _LOGGER.error('Error rendering message %s: %s', message, ex)

        hass.states.set(entity_id, message, attr)
Пример #6
0
    def request_config(
            self, name, callback,
            description, description_image, submit_caption,
            fields, link_name, link_url, entity_picture):
        """Set up a request for configuration."""
        entity_id = generate_entity_id(ENTITY_ID_FORMAT, name, hass=self.hass)

        if fields is None:
            fields = []

        request_id = self._generate_unique_id()

        self._requests[request_id] = (entity_id, fields, callback)

        data = {
            ATTR_CONFIGURE_ID: request_id,
            ATTR_FIELDS: fields,
            ATTR_FRIENDLY_NAME: name,
            ATTR_ENTITY_PICTURE: entity_picture,
        }

        data.update({
            key: value for key, value in [
                (ATTR_DESCRIPTION, description),
                (ATTR_DESCRIPTION_IMAGE, description_image),
                (ATTR_SUBMIT_CAPTION, submit_caption),
                (ATTR_LINK_NAME, link_name),
                (ATTR_LINK_URL, link_url),
            ] if value is not None
        })

        self.hass.states.set(entity_id, STATE_CONFIGURE, data)

        return request_id
Пример #7
0
    def __init__(self, hass, device_id, friendly_name,
                 target_entity, attribute, sensor_class, invert):
        """Initialize the sensor."""
        self._hass = hass
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id,
                                            hass=hass)
        self._name = friendly_name
        self._target_entity = target_entity
        self._attribute = attribute
        self._sensor_class = sensor_class
        self._invert = invert
        self._state = None
        self.from_state = None
        self.to_state = None

        self.update()

        def trend_sensor_state_listener(entity, old_state, new_state):
            """Called when the target device changes state."""
            self.from_state = old_state
            self.to_state = new_state
            self.update_ha_state(True)

        track_state_change(hass, target_entity,
                           trend_sensor_state_listener)
Пример #8
0
 def __init__(self, slug_id, hass, name, host, icon):
     """initialize the sensor entity"""
     self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, slug_id, hass=hass)
     self.hass = hass
     self._name = name
     self._host = host
     self._icon = icon 
     self._state = get_device_status(host)
 def __init__(self, hass, scene_data, room_data, pv_instance):
     """Initialize the scene."""
     self.pv_instance = pv_instance
     self.hass = hass
     self.scene_data = scene_data
     self._sync_room_data(room_data)
     self.entity_id_format = DOMAIN + ".{}"
     self.entity_id = generate_entity_id(self.entity_id_format, str(self.scene_data["id"]), hass=hass)
Пример #10
0
 def _add_node_to_component():
     name = node_name(node)
     generated_id = generate_entity_id(DOMAIN + '.{}', name, [])
     node_config = device_config.get(generated_id)
     if node_config.get(CONF_IGNORED):
         _LOGGER.info(
             "Ignoring node entity %s due to device settings",
             generated_id)
         return
     component.add_entities([entity])
Пример #11
0
 def node_added(node):
     """Handle a new node on the network."""
     entity = ZWaveNodeEntity(node, network)
     name = node_name(node)
     generated_id = generate_entity_id(DOMAIN + '.{}', name, [])
     node_config = device_config.get(generated_id)
     if node_config.get(CONF_IGNORED):
         _LOGGER.info(
             "Ignoring node entity %s due to device settings",
             generated_id)
         return
     component.add_entities([entity])
Пример #12
0
 def __init__(self, hass, device_id, friendly_name, state_template,
              on_action, off_action):
     """Initialize the Template switch."""
     self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id,
                                         hass=hass)
     self.hass = hass
     self._name = friendly_name
     self._template = state_template
     self._on_action = on_action
     self._off_action = off_action
     self.update()
     self.hass.bus.listen(EVENT_STATE_CHANGED, self._event_listener)
Пример #13
0
    def __init__(self, hass, device_id, friendly_name, unit_of_measurement,
                 state_template):
        """Initialize the sensor."""
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id,
                                            hass=hass)

        self.hass = hass
        self._name = friendly_name
        self._unit_of_measurement = unit_of_measurement
        self._template = state_template
        self.update()
        self.hass.bus.listen(EVENT_STATE_CHANGED, self._event_listener)
Пример #14
0
def get_calendar_info(hass, calendar):
    """Convert data from Google into DEVICE_SCHEMA."""
    calendar_info = DEVICE_SCHEMA({
        CONF_CAL_ID: calendar['id'],
        CONF_ENTITIES: [{
            CONF_TRACK: calendar['track'],
            CONF_NAME: calendar['summary'],
            CONF_DEVICE_ID: generate_entity_id(
                '{}', calendar['summary'], hass=hass),
        }]
    })
    return calendar_info
Пример #15
0
    def __init__(self, hass, domain, area_name, lutron_device, controller):
        """Initialize the device."""
        self._lutron_device = lutron_device
        self._controller = controller
        self._area_name = area_name

        self.hass = hass
        object_id = '{} {}'.format(area_name, lutron_device.name)
        self.entity_id = generate_entity_id(domain + '.{}', object_id,
                                            hass=hass)

        self._controller.subscribe(self._lutron_device, self._update_callback)
Пример #16
0
        def _add_node_to_component():
            if hass.data[DATA_DEVICES].get(entity.unique_id):
                return

            name = node_name(node)
            generated_id = generate_entity_id(DOMAIN + '.{}', name, [])
            node_config = device_config.get(generated_id)
            if node_config.get(CONF_IGNORED):
                _LOGGER.info(
                    "Ignoring node entity %s due to device settings",
                    generated_id)
                return

            hass.data[DATA_DEVICES][entity.unique_id] = entity
            component.add_entities([entity])
Пример #17
0
    def __init__(self, hass, device, friendly_name, sensor_class,
                 value_template):
        self._hass = hass
        self._device = device
        self._name = friendly_name
        self._sensor_class = sensor_class
        self._template = value_template
        self._state = None

        self.entity_id = generate_entity_id(
            ENTITY_ID_FORMAT, device,
            hass=hass)

        _LOGGER.info('Started template sensor %s', device)
        hass.bus.listen(EVENT_STATE_CHANGED, self._event_listener)
Пример #18
0
    def __init__(self, hass, device_id, friendly_name, unit_of_measurement, state_template):

        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id, hass=hass)

        self.hass = hass
        self._name = friendly_name
        self._unit_of_measurement = unit_of_measurement
        self._template = state_template
        self.update()

        def _update_callback(_event):
            """ Called when the target device changes state. """
            self.update_ha_state(True)

        self.hass.bus.listen(EVENT_STATE_CHANGED, _update_callback)
Пример #19
0
    def add_entity(self, entity):
        """Add entity to component."""
        if entity is None or entity in self.entities.values():
            return False

        entity.hass = self.hass

        if getattr(entity, 'entity_id', None) is None:
            entity.entity_id = generate_entity_id(
                self.entity_id_format, entity.name,
                self.entities.keys())

        self.entities[entity.entity_id] = entity
        entity.update_ha_state()

        return True
Пример #20
0
    def __init__(self, hass, device_id, friendly_name, unit_of_measurement, state_template, entity_ids):
        """Initialize the sensor."""
        self.hass = hass
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id, hass=hass)
        self._name = friendly_name
        self._unit_of_measurement = unit_of_measurement
        self._template = state_template
        self._state = None

        self.update()

        def template_sensor_state_listener(entity, old_state, new_state):
            """Called when the target device changes state."""
            self.update_ha_state(True)

        track_state_change(hass, entity_ids, template_sensor_state_listener)
Пример #21
0
def add_zone(hass, name, zone, entities=None):
    """Add a zone from other components."""
    _LOGGER.info("Adding new zone %s", name)
    if entities is None:
        _entities = set()
    else:
        _entities = entities
    zone.entity_id = generate_entity_id(ENTITY_ID_FORMAT, name,
                                        _entities)
    zone_exists = hass.states.get(zone.entity_id)
    if zone_exists is None:
        zone.update_ha_state()
        _entities.add(zone.entity_id)
        return zone
    else:
        _LOGGER.info("Zone already exists")
        return zone_exists
Пример #22
0
 def __init__(self, hass, device_id, friendly_name, entity_id,
              attribute, device_class, invert, max_samples,
              min_gradient, sample_duration):
     """Initialize the sensor."""
     self._hass = hass
     self.entity_id = generate_entity_id(
         ENTITY_ID_FORMAT, device_id, hass=hass)
     self._name = friendly_name
     self._entity_id = entity_id
     self._attribute = attribute
     self._device_class = device_class
     self._invert = invert
     self._sample_duration = sample_duration
     self._min_gradient = min_gradient
     self._gradient = None
     self._state = None
     self.samples = deque(maxlen=max_samples)
Пример #23
0
    def __init__(self, hass, name, entity_ids=None, user_defined=True, icon=None, view=False, object_id=None):
        self.hass = hass
        self._name = name
        self._state = STATE_UNKNOWN
        self._order = len(hass.states.entity_ids(DOMAIN))
        self._user_defined = user_defined
        self._icon = icon
        self._view = view
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, object_id or name, hass=hass)
        self.tracking = []
        self.group_on = None
        self.group_off = None

        if entity_ids is not None:
            self.update_tracked_entity_ids(entity_ids)
        else:
            self.update_ha_state(True)
Пример #24
0
    def __init__(self, hass, device, friendly_name, sensor_class,
                 value_template, entity_ids):
        """Initialize the Template binary sensor."""
        self.hass = hass
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device,
                                            hass=hass)
        self._name = friendly_name
        self._sensor_class = sensor_class
        self._template = value_template
        self._state = None

        self.update()

        def template_bsensor_state_listener(entity, old_state, new_state):
            """Called when the target device changes state."""
            self.update_ha_state(True)

        track_state_change(hass, entity_ids, template_bsensor_state_listener)
Пример #25
0
    def add_entity(self, entity, platform=None):
        """Add entity to component."""
        if entity is None or entity in self.entities.values():
            return False

        entity.hass = self.hass

        if getattr(entity, "entity_id", None) is None:
            object_id = entity.name or DEVICE_DEFAULT_NAME

            if platform is not None and platform.entity_namespace is not None:
                object_id = "{} {}".format(platform.entity_namespace, object_id)

            entity.entity_id = generate_entity_id(self.entity_id_format, object_id, self.entities.keys())

        self.entities[entity.entity_id] = entity
        entity.update_ha_state()

        return True
Пример #26
0
    def __init__(self, hass, device, friendly_name, sensor_class,
                 value_template):
        """Initialize the Template binary sensor."""
        self.hass = hass
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device,
                                            hass=hass)
        self._name = friendly_name
        self._sensor_class = sensor_class
        self._template = value_template
        self._state = None

        self.update()

        def template_bsensor_event_listener(event):
            """Called when the target device changes state."""
            self.update_ha_state(True)

        hass.bus.listen(EVENT_STATE_CHANGED,
                        template_bsensor_event_listener)
Пример #27
0
    def __init__(self, hass, data):
        """Create the Calendar Event Device."""
        self._name = data.get(CONF_NAME)
        self.dev_id = data.get(CONF_DEVICE_ID)
        self._offset = data.get(CONF_OFFSET, DEFAULT_CONF_OFFSET)
        self.entity_id = generate_entity_id(
            ENTITY_ID_FORMAT, self.dev_id, hass=hass)

        self._cal_data = {
            'all_day': False,
            'offset_time': dt.dt.timedelta(),
            'message': '',
            'start': None,
            'end': None,
            'location': '',
            'description': '',
        }

        self.update()
Пример #28
0
    def __init__(self, hass, device_id, friendly_name, state_template,
                 on_action, off_action, entity_ids):
        """Initialize the Template switch."""
        self.hass = hass
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id,
                                            hass=hass)
        self._name = friendly_name
        self._template = state_template
        self._on_script = Script(hass, on_action)
        self._off_script = Script(hass, off_action)
        self._state = False

        self.update()

        def template_switch_state_listener(entity, old_state, new_state):
            """Called when the target device changes state."""
            self.update_ha_state(True)

        track_state_change(hass, entity_ids, template_switch_state_listener)
Пример #29
0
 def __init__(self, hass, icloudobject, name, identifier):
     # pylint: disable=too-many-arguments
     self.hass = hass
     self.icloudobject = icloudobject
     self.devicename = name
     self.identifier = identifier
     self._request_interval_seconds = 60
     self._interval = 1
     self.api = icloudobject.api
     self._distance = None
     self._battery = None
     self._overridestate = None
     self._devicestatuscode = None
     self._devicestatus = None
     self._lowPowerMode = None
     self._batteryStatus = None
     
     self.entity_id = generate_entity_id(
         ENTITY_ID_FORMAT_DEVICE, self.devicename,
         hass=self.hass)
Пример #30
0
    def __init__(self, hass, device_id, friendly_name, state_template,
                 on_action, off_action):
        """Initialize the Template switch."""
        self.hass = hass
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id,
                                            hass=hass)
        self._name = friendly_name
        self._template = state_template
        self._on_action = on_action
        self._off_action = off_action
        self._state = False

        self.update()

        def template_switch_event_listener(event):
            """Called when the target device changes state."""
            self.update_ha_state(True)

        hass.bus.listen(EVENT_STATE_CHANGED,
                        template_switch_event_listener)
Пример #31
0
 def test_generate_entity_id_requires_hass_or_ids(self):
     """Ensure we require at least hass or current ids."""
     fmt = 'test.{}'
     with self.assertRaises(ValueError):
         entity.generate_entity_id(fmt, 'hello world')
Пример #32
0
    def _check_entity_ready(self):
        """Check if all required values are discovered and create entity."""
        if self._workaround_ignore:
            return
        if self._entity is not None:
            return

        for name in self._schema[const.DISC_VALUES]:
            if self._values[name] is None and not self._schema[
                    const.DISC_VALUES][name].get(const.DISC_OPTIONAL):
                return

        component = self._schema[const.DISC_COMPONENT]

        workaround_component = workaround.get_device_component_mapping(
            self.primary)
        if workaround_component and workaround_component != component:
            if workaround_component == workaround.WORKAROUND_IGNORE:
                _LOGGER.info(
                    "Ignoring Node %d Value %d due to workaround.",
                    self.primary.node.node_id,
                    self.primary.value_id,
                )
                # No entity will be created for this value
                self._workaround_ignore = True
                return
            _LOGGER.debug("Using %s instead of %s", workaround_component,
                          component)
            component = workaround_component

        entity_id = self._registry.async_get_entity_id(
            component, DOMAIN, compute_value_unique_id(self._node,
                                                       self.primary))
        if entity_id is None:
            value_name = _value_name(self.primary)
            entity_id = generate_entity_id(component + ".{}", value_name, [])
        node_config = self._device_config.get(entity_id)

        # Configure node
        _LOGGER.debug(
            "Adding Node_id=%s Generic_command_class=%s, "
            "Specific_command_class=%s, "
            "Command_class=%s, Value type=%s, "
            "Genre=%s as %s",
            self._node.node_id,
            self._node.generic,
            self._node.specific,
            self.primary.command_class,
            self.primary.type,
            self.primary.genre,
            component,
        )

        if node_config.get(CONF_IGNORED):
            _LOGGER.info("Ignoring entity %s due to device settings",
                         entity_id)
            # No entity will be created for this value
            self._workaround_ignore = True
            return

        polling_intensity = convert(node_config.get(CONF_POLLING_INTENSITY),
                                    int)
        if polling_intensity:
            self.primary.enable_poll(polling_intensity)

        platform = import_module(f".{component}", __name__)

        device = platform.get_device(node=self._node,
                                     values=self,
                                     node_config=node_config,
                                     hass=self._hass)
        if device is None:
            # No entity will be created for this value
            self._workaround_ignore = True
            return

        self._entity = device

        @callback
        def _on_ready(sec):
            _LOGGER.info(
                "Z-Wave entity %s (node_id: %d) ready after %d seconds",
                device.name,
                self._node.node_id,
                sec,
            )
            self._hass.async_add_job(discover_device, component, device)

        @callback
        def _on_timeout(sec):
            _LOGGER.warning(
                "Z-Wave entity %s (node_id: %d) not ready after %d seconds, "
                "continuing anyway",
                device.name,
                self._node.node_id,
                sec,
            )
            self._hass.async_add_job(discover_device, component, device)

        async def discover_device(component, device):
            """Put device in a dictionary and call discovery on it."""
            if self._hass.data[DATA_DEVICES].get(device.unique_id):
                return

            self._hass.data[DATA_DEVICES][device.unique_id] = device
            if component in SUPPORTED_PLATFORMS:
                async_dispatcher_send(self._hass, f"zwave_new_{component}",
                                      device)
            else:
                await discovery.async_load_platform(
                    self._hass,
                    component,
                    DOMAIN,
                    {const.DISCOVERY_DEVICE: device.unique_id},
                    self._zwave_config,
                )

        if device.unique_id:
            self._hass.add_job(discover_device, component, device)
        else:
            self._hass.add_job(check_has_unique_id, device, _on_ready,
                               _on_timeout)
Пример #33
0
 def create_entity(number):
     """Create entity helper."""
     entity = MockEntity()
     entity.entity_id = generate_entity_id(DOMAIN + '.{}',
                                           'Number', hass=self.hass)
     return entity
Пример #34
0
    def __init__(self, hass, username, password, name, ignored_devices,
                 getevents):
        # pylint: disable=too-many-arguments
        self.hass = hass
        self.username = username
        self.password = password
        self.accountname = name
        self._max_wait_seconds = 120
        self._request_interval_seconds = 10
        self._interval = 1
        self.api = None
        self.devices = {}
        self.getevents = getevents
        self.events = {}
        self.currentevents = {}
        self.nextevents = {}
        self._ignored_devices = ignored_devices
        self._ignored_identifiers = {}
        
        self.entity_id = generate_entity_id(
            ENTITY_ID_FORMAT_ICLOUD, self.accountname,
            hass=self.hass)

        if self.username is None or self.password is None:
            _LOGGER.error('Must specify a username and password')
        else:
            try:
                # Attempt the login to iCloud
                self.api = PyiCloudService(self.username,
                                           self.password,
                                           verify=True)
                for device in self.api.devices:
                    status = device.status(DEVICESTATUSSET)
                    devicename = re.sub(r"(\s|\W|')", '',
                                        status['name']).lower()
                    if (devicename not in self.devices and
                        devicename not in self._ignored_devices):
                        idevice = IDevice(self.hass, self, devicename, device)
                        idevice.update_ha_state()
                        self.devices[devicename] = idevice
                    elif devicename in self._ignored_devices:
                        self._ignored_identifiers[devicename] = device
                    
                if self.getevents:
                    from_dt = dt_util.now()
                    to_dt = from_dt + timedelta(days=7)
                    events = self.api.calendar.events(from_dt, to_dt)
                    new_events = sorted(events.list_of_dict, key=operator.attrgetter('startDate'))
                    starttime = None
                    endtime = None
                    duration = None
                    title = None
                    tz = pytz.utc
                    location = None
                    guid = None
                    for event in new_events:
                        tz = event['tz']
                        if tz is None:
                            tz = pytz.utc
                        else:
                            tz = timezone(tz)
                        tempnow = dt_util.now(tz)
                        guid = event['guid']
                        starttime = event['startDate']
                        startdate = datetime(starttime[1], starttime[2],
                                             starttime[3], starttime[4],
                                             starttime[5], 0, 0, tz)
                        endtime = event['endDate']
                        enddate = datetime(endtime[1], endtime[2], endtime[3],
                                           endtime[4], endtime[5], 0, 0, tz)
                        duration = event['duration']
                        title = event['title']
                        location = event['location']
                        
                        strnow = tempnow.strftime("%Y%m%d%H%M%S")
                        strstart = startdate.strftime("%Y%m%d%H%M%S")
                        strend = enddate.strftime("%Y%m%d%H%M%S")
                        
                        if strnow > strstart and strend > strnow:
                            ievent = IEvent(self.hass, self, guid,
                                            TYPE_CURRENT)
                            ievent.update_ha_state()
                            self.currentevents[guid] = ievent
                            self.currentevents[guid].keep_alive(starttime,
                                                                endtime,
                                                                duration,
                                                                title,
                                                                tz,
                                                                location)

                        starttime = None
                        endtime = None
                        duration = None
                        title = None
                        tz = pytz.utc
                        location = None
                        guid = None
                    
                    starttime = None
                    endtime = None
                    duration = None
                    title = None
                    tz = pytz.utc
                    location = None
                    guid = None
                    for event in new_events:
                        tz = event['tz']
                        if tz is None:
                            tz = pytz.utc
                        else:
                            tz = timezone(tz)
                        tempnow = dt_util.now(tz)
                        guid = event['guid']
                        starttime = event['startDate']
                        startdate = datetime(starttime[1],
                                             starttime[2],
                                             starttime[3],
                                             starttime[4],
                                             starttime[5], 0, 0, tz)
                        endtime = event['endDate']
                        enddate = datetime(endtime[1], endtime[2],
                                           endtime[3], endtime[4],
                                           endtime[5], 0, 0, tz)
                        duration = event['duration']
                        title = event['title']
                        location = event['location']
                        
                        strnow = tempnow.strftime("%Y%m%d%H%M%S")
                        strstart = startdate.strftime("%Y%m%d%H%M%S")
                        strend = enddate.strftime("%Y%m%d%H%M%S")
                        
                        if strnow < strstart:
                            ievent = IEvent(self.hass, self, guid,
                                            TYPE_NEXT)
                            ievent.update_ha_state()
                            self.nextevents[guid] = ievent
                            self.nextevents[guid].keep_alive(starttime,
                                                             endtime,
                                                             duration,
                                                             title,
                                                             tz,
                                                             location)
                        
            except PyiCloudFailedLoginException as error:
                _LOGGER.error('Error logging into iCloud Service: %s',
                              error)
Пример #35
0
 def keep_alive(self):
     """ Keeps the api alive """
     if self.api is None:
         try:
             # Attempt the login to iCloud
             self.api = PyiCloudService(self.username,
                                        self.password,
                                        verify=True)
                     
         except PyiCloudFailedLoginException as error:
             _LOGGER.error('Error logging into iCloud Service: %s',
                           error)
     
     
     if self.api is not None:
         self.api.authenticate()
         for devicename in self.devices:
             self.devices[devicename].keep_alive()
         if self.getevents:
             from_dt = dt_util.now()
             to_dt = from_dt + timedelta(days=7)
             events = self.api.calendar.events(from_dt, to_dt)
             new_events = sorted(events.list_of_dict, key=operator.attrgetter('startDate'))
             starttime = None
             endtime = None
             duration = None
             title = None
             tz = pytz.utc
             location = None
             guid = None
             for event in new_events:
                 tz = event['tz']
                 if tz is None:
                     tz = pytz.utc
                 else:
                     tz = timezone(tz)
                 tempnow = dt_util.now(tz)
                 guid = event['guid']
                 starttime = event['startDate']
                 startdate = datetime(starttime[1], starttime[2],
                                      starttime[3], starttime[4],
                                      starttime[5], 0, 0, tz)
                 endtime = event['endDate']
                 enddate = datetime(endtime[1], endtime[2], endtime[3],
                                    endtime[4], endtime[5], 0, 0, tz)
                 duration = event['duration']
                 title = event['title']
                 location = event['location']
                     
                 strnow = tempnow.strftime("%Y%m%d%H%M%S")
                 strstart = startdate.strftime("%Y%m%d%H%M%S")
                 strend = enddate.strftime("%Y%m%d%H%M%S")
                     
                 if strnow > strstart and strend > strnow:
                     if guid not in self.currentevents:
                         ievent = IEvent(self.hass, self, guid,
                                         TYPE_CURRENT)
                         ievent.update_ha_state()
                         self.currentevents[guid] = ievent
                     self.currentevents[guid].keep_alive(starttime,
                                                         endtime,
                                                         duration,
                                                         title,
                                                         tz,
                                                         location)
                 starttime = None
                 endtime = None
                 duration = None
                 title = None
                 tz = pytz.utc
                 location = None
                 guid = None
                 
             for addedevent in self.currentevents:
                 found = False
                 eventguid = self.currentevents[addedevent].eventguid
                 for event in new_events:
                     if event['guid'] == eventguid:
                         found = True
                 if not found:
                     ent_id = generate_entity_id(ENTITY_ID_FORMAT_EVENT,
                                                 eventguid,
                                                 hass=self.hass)
                     self.hass.states.remove(ent_id)
                     del self.currentevents[addedevent]
                 else:
                     self.currentevents[addedevent].check_alive()
             
             starttime = None
             endtime = None
             duration = None
             title = None
             tz = pytz.utc
             location = None
             guid = None
             for event in new_events:
                 tz = event['tz']
                 if tz is None:
                     tz = pytz.utc
                 else:
                     tz = timezone(tz)
                 tempnow = dt_util.now(tz)
                 guid = event['guid']
                 starttime = event['startDate']
                 startdate = datetime(starttime[1],
                                      starttime[2],
                                      starttime[3],
                                      starttime[4],
                                      starttime[5], 0, 0, tz)
                 endtime = event['endDate']
                 enddate = datetime(endtime[1], endtime[2],
                                    endtime[3], endtime[4],
                                    endtime[5], 0, 0, tz)
                 duration = event['duration']
                 title = event['title']
                 location = event['location']
                     
                 strnow = tempnow.strftime("%Y%m%d%H%M%S")
                 strstart = startdate.strftime("%Y%m%d%H%M%S")
                 strend = enddate.strftime("%Y%m%d%H%M%S")
                     
                 if strnow < strstart:
                     if guid not in self.nextevents:
                         ievent = IEvent(self.hass, self, guid,
                                         TYPE_NEXT)
                         ievent.update_ha_state()
                         self.nextevents[guid] = ievent
                     self.nextevents[guid].keep_alive(starttime,
                                                      endtime,
                                                      duration,
                                                      title,
                                                      tz,
                                                      location)
             for addedevent in self.nextevents:
                 found = False
                 eventguid = self.nextevents[addedevent].eventguid
                 for event in new_events:
                     if event['guid'] == eventguid:
                         found = True
                 if not found:
                     ent_id = generate_entity_id(ENTITY_ID_FORMAT_EVENT,
                                                 eventguid,
                                                 hass=self.hass)
                     self.hass.states.remove(ent_id)
                     del self.nextevents[addedevent]
                 else:
                     self.nextevents[addedevent].check_alive()
Пример #36
0
 def test_generate_entity_id_given_hass(self):
     """Test generating an entity id given hass object."""
     fmt = 'test.{}'
     assert entity.generate_entity_id(
         fmt, 'overwrite hidden true',
         hass=self.hass) == 'test.overwrite_hidden_true_2'
Пример #37
0
async def async_setup_entry(
    hass: HomeAssistant,
    config_entry: ConfigEntry,
    async_add_entities: AddEntitiesCallback,
) -> None:
    """Set up the google calendar platform."""
    calendar_service = hass.data[DOMAIN][config_entry.entry_id][DATA_SERVICE]
    try:
        result = await calendar_service.async_list_calendars()
    except ApiException as err:
        raise PlatformNotReady(str(err)) from err

    entity_registry = er.async_get(hass)
    registry_entries = er.async_entries_for_config_entry(
        entity_registry, config_entry.entry_id)
    entity_entry_map = {
        entity_entry.unique_id: entity_entry
        for entity_entry in registry_entries
    }

    # Yaml configuration may override objects from the API
    calendars = await hass.async_add_executor_job(
        load_config, hass.config.path(YAML_DEVICES))
    new_calendars = []
    entities = []
    for calendar_item in result.items:
        calendar_id = calendar_item.id
        if calendars and calendar_id in calendars:
            calendar_info = calendars[calendar_id]
        else:
            calendar_info = get_calendar_info(
                hass, calendar_item.dict(exclude_unset=True))
            new_calendars.append(calendar_info)
        # Yaml calendar config may map one calendar to multiple entities with extra options like
        # offsets or search criteria.
        num_entities = len(calendar_info[CONF_ENTITIES])
        for data in calendar_info[CONF_ENTITIES]:
            entity_enabled = data.get(CONF_TRACK, True)
            if not entity_enabled:
                _LOGGER.warning(
                    "The 'track' option in google_calendars.yaml has been deprecated. The setting "
                    "has been imported to the UI, and should now be removed from google_calendars.yaml"
                )
            entity_name = data[CONF_DEVICE_ID]
            # The unique id is based on the config entry and calendar id since multiple accounts
            # can have a common calendar id (e.g. `en.usa#[email protected]`).
            # When using google_calendars.yaml with multiple entities for a single calendar, we
            # have no way to set a unique id.
            if num_entities > 1:
                unique_id = None
            else:
                unique_id = f"{config_entry.unique_id}-{calendar_id}"
            # Migrate to new unique_id format which supports multiple config entries as of 2022.7
            for old_unique_id in (calendar_id, f"{calendar_id}-{entity_name}"):
                if not (entity_entry := entity_entry_map.get(old_unique_id)):
                    continue
                if unique_id:
                    _LOGGER.debug(
                        "Migrating unique_id for %s from %s to %s",
                        entity_entry.entity_id,
                        old_unique_id,
                        unique_id,
                    )
                    entity_registry.async_update_entity(
                        entity_entry.entity_id, new_unique_id=unique_id)
                else:
                    _LOGGER.debug(
                        "Removing entity registry entry for %s from %s",
                        entity_entry.entity_id,
                        old_unique_id,
                    )
                    entity_registry.async_remove(entity_entry.entity_id, )
            coordinator = CalendarUpdateCoordinator(
                hass,
                calendar_service,
                data[CONF_NAME],
                calendar_id,
                data.get(CONF_SEARCH),
            )
            entities.append(
                GoogleCalendarEntity(
                    coordinator,
                    calendar_id,
                    data,
                    generate_entity_id(ENTITY_ID_FORMAT,
                                       entity_name,
                                       hass=hass),
                    unique_id,
                    entity_enabled,
                ))
Пример #38
0
    def keep_alive(self):
        """Keep the api alive."""
        # pylint: disable=too-many-locals,too-many-branches,too-many-statements
        if self.api is None:
            from pyicloud import PyiCloudService
            from pyicloud.exceptions import PyiCloudFailedLoginException
            try:
                # Attempt the login to iCloud
                self.api = PyiCloudService(self.username,
                                           self.password,
                                           cookie_directory=self.cookiedir,
                                           verify=True)
            except PyiCloudFailedLoginException as error:
                _LOGGER.error('Error logging into iCloud Service: %s', error)

        if self.api is not None:
            if not self.getevents:
                self.api.authenticate()
            for devicename in self.devices:
                self.devices[devicename].keep_alive()
            if self.getevents:
                from_dt = dt_util.now()
                to_dt = from_dt + timedelta(days=7)
                events = self.api.calendar.events(from_dt, to_dt)
                new_events = sorted(events, key=self.get_key)
                for event in new_events:
                    tzone = event['tz']
                    if tzone is None:
                        tzone = pytz.utc
                    else:
                        tzone = timezone(tzone)
                    tempnow = dt_util.now(tzone)
                    guid = event['guid']
                    starttime = event['startDate']
                    startdate = datetime(starttime[1], starttime[2],
                                         starttime[3], starttime[4],
                                         starttime[5], 0, 0, tzone)
                    endtime = event['endDate']
                    enddate = datetime(endtime[1], endtime[2], endtime[3],
                                       endtime[4], endtime[5], 0, 0, tzone)
                    duration = event['duration']
                    title = event['title']
                    location = event['location']

                    strnow = tempnow.strftime("%Y%m%d%H%M%S")
                    strstart = startdate.strftime("%Y%m%d%H%M%S")
                    strend = enddate.strftime("%Y%m%d%H%M%S")

                    if strnow > strstart and strend > strnow:
                        if guid not in self.currentevents:
                            ievent = IEvent(self.hass, self, guid,
                                            TYPE_CURRENT)
                            ievent.update_ha_state()
                            self.currentevents[guid] = ievent
                        self.currentevents[guid].keep_alive(
                            starttime, endtime, duration, title, tzone,
                            location)

                for addedevent in self.currentevents:
                    found = False
                    eventguid = self.currentevents[addedevent].eventguid
                    for event in new_events:
                        if event['guid'] == eventguid:
                            found = True
                    if not found:
                        ent_id = generate_entity_id(ENTITY_ID_FORMAT_EVENT,
                                                    eventguid,
                                                    hass=self.hass)
                        self.hass.states.remove(ent_id)
                        del self.currentevents[addedevent]
                    else:
                        self.currentevents[addedevent].check_alive()

                for event in new_events:
                    tzone = event['tz']
                    if tzone is None:
                        tzone = pytz.utc
                    else:
                        tzone = timezone(tzone)
                    tempnow = dt_util.now(tzone)
                    guid = event['guid']
                    starttime = event['startDate']
                    startdate = datetime(starttime[1], starttime[2],
                                         starttime[3], starttime[4],
                                         starttime[5], 0, 0, tzone)
                    endtime = event['endDate']
                    enddate = datetime(endtime[1], endtime[2], endtime[3],
                                       endtime[4], endtime[5], 0, 0, tzone)
                    duration = event['duration']
                    title = event['title']
                    location = event['location']

                    strnow = tempnow.strftime("%Y%m%d%H%M%S")
                    strstart = startdate.strftime("%Y%m%d%H%M%S")
                    strend = enddate.strftime("%Y%m%d%H%M%S")

                    if strnow < strstart:
                        if guid not in self.nextevents:
                            ievent = IEvent(self.hass, self, guid, TYPE_NEXT)
                            ievent.update_ha_state()
                            self.nextevents[guid] = ievent
                        self.nextevents[guid].keep_alive(
                            starttime, endtime, duration, title, tzone,
                            location)
                for addedevent in self.nextevents:
                    found = False
                    eventguid = self.nextevents[addedevent].eventguid
                    for event in new_events:
                        if event['guid'] == eventguid:
                            found = True
                    if not found:
                        ent_id = generate_entity_id(ENTITY_ID_FORMAT_EVENT,
                                                    eventguid,
                                                    hass=self.hass)
                        self.hass.states.remove(ent_id)
                        del self.nextevents[addedevent]
                    else:
                        self.nextevents[addedevent].check_alive()

                self._currentevents = 0
                self._nextevents = 0
                for entity_id in self.hass.states.entity_ids('ievent'):
                    state = self.hass.states.get(entity_id)
                    friendlyname = state.attributes.get(ATTR_FRIENDLY_NAME)
                    if friendlyname == 'nextevent':
                        self._nextevents = self._nextevents + 1
                    elif friendlyname == 'currentevent':
                        self._currentevents = self._currentevents + 1
                self.update_ha_state()
Пример #39
0
    def __init__(self, hass, username, password, cookiedirectory, name,
                 ignored_devices, getevents, googletraveltime):
        """Initialize an iCloud account."""
        # pylint: disable=too-many-arguments,too-many-branches
        # pylint: disable=too-many-statements,too-many-locals
        self.hass = hass
        self.username = username
        self.password = password
        self.cookiedir = cookiedirectory
        self.accountname = name
        self._max_wait_seconds = 120
        self._request_interval_seconds = 10
        self._interval = 1
        self.api = None
        self.devices = {}
        self.getevents = getevents
        self.events = {}
        self.currentevents = {}
        self.nextevents = {}
        self._ignored_devices = ignored_devices
        self._ignored_identifiers = {}
        self.googletraveltime = googletraveltime

        self._currentevents = 0
        self._nextevents = 0

        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT_ICLOUD,
                                            self.accountname,
                                            hass=self.hass)

        if self.username is None or self.password is None:
            _LOGGER.error('Must specify a username and password')
        else:
            from pyicloud import PyiCloudService
            from pyicloud.exceptions import PyiCloudFailedLoginException
            try:
                # Attempt the login to iCloud
                self.api = PyiCloudService(self.username,
                                           self.password,
                                           cookie_directory=self.cookiedir,
                                           verify=True)
                for device in self.api.devices:
                    status = device.status(DEVICESTATUSSET)
                    devicename = slugify(status['name'].replace(' ', '', 99))
                    if (devicename not in self.devices
                            and devicename not in self._ignored_devices):
                        gtt = None
                        if devicename in self.googletraveltime:
                            gtt = self.googletraveltime[devicename]
                        idevice = IDevice(self.hass, self, devicename, device,
                                          gtt)
                        idevice.update_ha_state()
                        self.devices[devicename] = idevice
                    elif devicename in self._ignored_devices:
                        self._ignored_identifiers[devicename] = device

                if self.getevents:
                    from_dt = dt_util.now()
                    to_dt = from_dt + timedelta(days=7)
                    events = self.api.calendar.events(from_dt, to_dt)
                    new_events = sorted(events, key=self.get_key)
                    for event in new_events:
                        tzone = event['tz']
                        if tzone is None:
                            tzone = pytz.utc
                        else:
                            tzone = timezone(tzone)
                        tempnow = dt_util.now(tzone)
                        guid = event['guid']
                        starttime = event['startDate']
                        startdate = datetime(starttime[1], starttime[2],
                                             starttime[3], starttime[4],
                                             starttime[5], 0, 0, tzone)
                        endtime = event['endDate']
                        enddate = datetime(endtime[1], endtime[2], endtime[3],
                                           endtime[4], endtime[5], 0, 0, tzone)
                        duration = event['duration']
                        title = event['title']
                        location = event['location']

                        strnow = tempnow.strftime("%Y%m%d%H%M%S")
                        strstart = startdate.strftime("%Y%m%d%H%M%S")
                        strend = enddate.strftime("%Y%m%d%H%M%S")

                        if strnow > strstart and strend > strnow:
                            ievent = IEvent(self.hass, self, guid,
                                            TYPE_CURRENT)
                            ievent.update_ha_state()
                            self.currentevents[guid] = ievent
                            self.currentevents[guid].keep_alive(
                                starttime, endtime, duration, title, tzone,
                                location)

                    for event in new_events:
                        tzone = event['tz']
                        if tzone is None:
                            tzone = pytz.utc
                        else:
                            tzone = timezone(tzone)
                        tempnow = dt_util.now(tzone)
                        guid = event['guid']
                        starttime = event['startDate']
                        startdate = datetime(starttime[1], starttime[2],
                                             starttime[3], starttime[4],
                                             starttime[5], 0, 0, tzone)
                        endtime = event['endDate']
                        enddate = datetime(endtime[1], endtime[2], endtime[3],
                                           endtime[4], endtime[5], 0, 0, tzone)
                        duration = event['duration']
                        title = event['title']
                        location = event['location']

                        strnow = tempnow.strftime("%Y%m%d%H%M%S")
                        strstart = startdate.strftime("%Y%m%d%H%M%S")
                        strend = enddate.strftime("%Y%m%d%H%M%S")

                        if strnow < strstart:
                            ievent = IEvent(self.hass, self, guid, TYPE_NEXT)
                            ievent.update_ha_state()
                            self.nextevents[guid] = ievent
                            self.nextevents[guid].keep_alive(
                                starttime, endtime, duration, title, tzone,
                                location)

            except PyiCloudFailedLoginException as error:
                _LOGGER.error('Error logging into iCloud Service: %s', error)
Пример #40
0
 def zone_from_place(place, entity_id=None):
     zone = Zone(hass, *place, None, DEFAULT_PASSIVE)
     zone.entity_id = (entity_id or generate_entity_id(
         ZN_ENTITY_ID_FORMAT, place.name, None, hass))
     zone.schedule_update_ha_state()
     return zone
Пример #41
0
 def test_generate_entity_id_given_hass(self):
     """Test generating an entity id given hass object."""
     fmt = "test.{}"
     assert (entity.generate_entity_id(
         fmt, "overwrite hidden true",
         hass=self.hass) == "test.overwrite_hidden_true_2")
Пример #42
0
def test_generate_entity_id_with_nonlatin_name():
    """Test generate_entity_id given a name containing non-latin characters."""
    fmt = 'test.{}'
    assert entity.generate_entity_id(fmt, 'ホームアシスタント',
                                     current_ids=[]) == 'test.unnamed_device'
 def create_entity(number):
     """Create entity helper."""
     entity = EntityTest()
     entity.entity_id = generate_entity_id(component.entity_id_format,
                                           'Number', hass=self.hass)
     return entity
Пример #44
0
def test_generate_entity_id_requires_hass_or_ids():
    """Ensure we require at least hass or current ids."""
    with pytest.raises(ValueError):
        entity.generate_entity_id("test.{}", "hello world")
Пример #45
0
    def _check_entity_ready(self):
        """Check if all required values are discovered and create entity."""
        if self._workaround_ignore:
            return
        if self._entity is not None:
            return

        for name in self._schema[const.DISC_VALUES]:
            if self._values[name] is None and \
                    not self._schema[const.DISC_VALUES][name].get(
                            const.DISC_OPTIONAL):
                return

        component = self._schema[const.DISC_COMPONENT]

        workaround_component = workaround.get_device_component_mapping(
            self.primary)
        if workaround_component and workaround_component != component:
            if workaround_component == workaround.WORKAROUND_IGNORE:
                _LOGGER.info("Ignoring Node %d Value %d due to workaround.",
                             self.primary.node.node_id, self.primary.value_id)
                # No entity will be created for this value
                self._workaround_ignore = True
                return
            _LOGGER.debug("Using %s instead of %s", workaround_component,
                          component)
            component = workaround_component

        value_name = _value_name(self.primary)
        if self._zwave_config[DOMAIN][CONF_NEW_ENTITY_IDS]:
            generated_id = generate_entity_id(component + '.{}', value_name,
                                              [])
        else:
            generated_id = "{}.{}".format(component, object_id(self.primary))
        node_config = self._device_config.get(generated_id)

        # Configure node
        _LOGGER.debug(
            "Adding Node_id=%s Generic_command_class=%s, "
            "Specific_command_class=%s, "
            "Command_class=%s, Value type=%s, "
            "Genre=%s as %s", self._node.node_id, self._node.generic,
            self._node.specific, self.primary.command_class, self.primary.type,
            self.primary.genre, component)

        if node_config.get(CONF_IGNORED):
            _LOGGER.info("Ignoring entity %s due to device settings",
                         generated_id)
            # No entity will be created for this value
            self._workaround_ignore = True
            return

        polling_intensity = convert(node_config.get(CONF_POLLING_INTENSITY),
                                    int)
        if polling_intensity:
            self.primary.enable_poll(polling_intensity)
        else:
            self.primary.disable_poll()

        platform = get_platform(component, DOMAIN)
        device = platform.get_device(node=self._node,
                                     values=self,
                                     node_config=node_config,
                                     hass=self._hass)
        if device is None:
            # No entity will be created for this value
            self._workaround_ignore = True
            return

        device.old_entity_id = "{}.{}".format(component,
                                              object_id(self.primary))
        device.new_entity_id = "{}.{}".format(component, slugify(device.name))
        if not self._zwave_config[DOMAIN][CONF_NEW_ENTITY_IDS]:
            device.entity_id = device.old_entity_id

        self._entity = device

        dict_id = id(self)

        @asyncio.coroutine
        def discover_device(component, device, dict_id):
            """Put device in a dictionary and call discovery on it."""
            self._hass.data[DATA_DEVICES][dict_id] = device
            yield from discovery.async_load_platform(
                self._hass, component, DOMAIN,
                {const.DISCOVERY_DEVICE: dict_id}, self._zwave_config)

        self._hass.add_job(discover_device, component, device, dict_id)