async def test_parallel_updates_sync_platform_with_constant(hass):
    """Test sync platform can set parallel_updates limit."""
    platform = MockPlatform()
    platform.PARALLEL_UPDATES = 2

    loader.set_component(hass, 'test_domain.platform', platform)

    component = EntityComponent(_LOGGER, DOMAIN, hass)
    component._platforms = {}

    await component.async_setup({
        DOMAIN: {
            'platform': 'platform',
        }
    })

    handle = list(component._platforms.values())[-1]
    assert handle.parallel_updates == 2

    class SyncEntity(MockEntity):
        """Mock entity that has update."""

        async def update(self):
            pass

    entity = SyncEntity()
    await handle.async_add_entities([entity])
    assert entity.parallel_updates is not None
    assert entity.parallel_updates._value == 2
Exemplo n.º 2
0
def setup(hass, config):
    """ Sets up scenes. """

    logger = logging.getLogger(__name__)

    scene_configs = config.get(DOMAIN)

    if not isinstance(scene_configs, list) or \
       any(not isinstance(item, dict) for item in scene_configs):
        logger.error('Scene config should be a list of dictionaries')
        return False

    component = EntityComponent(logger, DOMAIN, hass)

    component.add_entities(Scene(hass, _process_config(scene_config))
                           for scene_config in scene_configs)

    def handle_scene_service(service):
        """ Handles calls to the switch services. """
        target_scenes = component.extract_from_service(service)

        for scene in target_scenes:
            scene.activate()

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

    return True
Exemplo n.º 3
0
async def async_setup(hass, config):
    """Set up an input text box."""
    component = EntityComponent(_LOGGER, DOMAIN, hass)

    entities = []

    for object_id, cfg in config[DOMAIN].items():
        name = cfg.get(CONF_NAME)
        minimum = cfg.get(CONF_MIN)
        maximum = cfg.get(CONF_MAX)
        initial = cfg.get(CONF_INITIAL)
        icon = cfg.get(CONF_ICON)
        unit = cfg.get(ATTR_UNIT_OF_MEASUREMENT)
        pattern = cfg.get(ATTR_PATTERN)
        mode = cfg.get(CONF_MODE)

        entities.append(InputText(
            object_id, name, initial, minimum, maximum, icon, unit,
            pattern, mode))

    if not entities:
        return False

    component.async_register_entity_service(
        SERVICE_SET_VALUE, SERVICE_SET_VALUE_SCHEMA,
        'async_set_value'
    )

    await component.async_add_entities(entities)
    return True
Exemplo n.º 4
0
def setup(hass, config):
    """ Track states and offer events for remote. """
    component = EntityComponent(
        logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL,
        DISCOVERY_PLATFORMS)

    component.setup(config)

    descriptions = load_yaml_config_file(
        os.path.join(os.path.dirname(__file__), 'services.yaml'))

    def remote_service_handler(service):
        """ Maps services to methods on RemoteDevice. """
        target_remotes = component.extract_from_service(service)

        method = SERVICE_TO_METHOD[service.service]

        for remote in target_remotes:
            getattr(remote, method)()

            if remote.should_poll:
                remote.update_ha_state(True)

    for service in SERVICE_TO_METHOD:
        hass.services.register(DOMAIN, service, remote_service_handler,
                               descriptions.get(service))

    return True
Exemplo n.º 5
0
def setup(hass, config):
    """Track states and offer events for locks."""
    component = EntityComponent(
        _LOGGER, DOMAIN, hass, SCAN_INTERVAL, DISCOVERY_PLATFORMS,
        GROUP_NAME_ALL_LOCKS)
    component.setup(config)

    def handle_lock_service(service):
        """Handle calls to the lock services."""
        target_locks = component.extract_from_service(service)

        if ATTR_CODE not in service.data:
            code = None
        else:
            code = service.data[ATTR_CODE]

        for item in target_locks:
            if service.service == SERVICE_LOCK:
                item.lock(code=code)
            else:
                item.unlock(code=code)

            if item.should_poll:
                item.update_ha_state(True)

    descriptions = load_yaml_config_file(
        os.path.join(os.path.dirname(__file__), 'services.yaml'))
    hass.services.register(DOMAIN, SERVICE_UNLOCK, handle_lock_service,
                           descriptions.get(SERVICE_UNLOCK))
    hass.services.register(DOMAIN, SERVICE_LOCK, handle_lock_service,
                           descriptions.get(SERVICE_LOCK))

    return True
def test_setup_dependencies_platform(hass):
    """Test we setup the dependencies of a platform.

    We're explictely testing that we process dependencies even if a component
    with the same name has already been loaded.
    """
    loader.set_component(hass, 'test_component', MockModule('test_component'))
    loader.set_component(hass, 'test_component2',
                         MockModule('test_component2'))
    loader.set_component(
        hass, 'test_domain.test_component',
        MockPlatform(dependencies=['test_component', 'test_component2']))

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    yield from async_setup_component(hass, 'test_component', {})

    yield from component.async_setup({
        DOMAIN: {
            'platform': 'test_component',
        }
    })

    assert 'test_component' in hass.config.components
    assert 'test_component2' in hass.config.components
    assert 'test_domain.test_component' in hass.config.components
    def test_setting_up_group(self):
        """Setup the setting of a group."""
        setup_component(self.hass, 'group', {'group': {}})
        component = EntityComponent(_LOGGER, DOMAIN, self.hass,
                                    group_name='everyone')

        # No group after setup
        assert len(self.hass.states.entity_ids()) == 0

        component.add_entities([MockEntity()])
        self.hass.block_till_done()

        # group exists
        assert len(self.hass.states.entity_ids()) == 2
        assert self.hass.states.entity_ids('group') == ['group.everyone']

        group = self.hass.states.get('group.everyone')

        assert group.attributes.get('entity_id') == \
            ('test_domain.unnamed_device',)

        # group extended
        component.add_entities([MockEntity(name='goodbye')])
        self.hass.block_till_done()

        assert len(self.hass.states.entity_ids()) == 3
        group = self.hass.states.get('group.everyone')

        # Ordered in order of added to the group
        assert group.attributes.get('entity_id') == \
            ('test_domain.goodbye', 'test_domain.unnamed_device')
Exemplo n.º 8
0
def async_setup(hass, config):
    """Track states and offer events for covers."""
    component = EntityComponent(
        _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_COVERS)

    yield from component.async_setup(config)

    @asyncio.coroutine
    def async_handle_cover_service(service):
        """Handle calls to the cover services."""
        covers = component.async_extract_from_service(service)
        method = SERVICE_TO_METHOD.get(service.service)
        params = service.data.copy()
        params.pop(ATTR_ENTITY_ID, None)

        # call method
        update_tasks = []
        for cover in covers:
            yield from getattr(cover, method['method'])(**params)
            if not cover.should_poll:
                continue
            update_tasks.append(cover.async_update_ha_state(True))

        if update_tasks:
            yield from asyncio.wait(update_tasks, loop=hass.loop)

    for service_name in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[service_name].get(
            'schema', COVER_SERVICE_SCHEMA)
        hass.services.async_register(
            DOMAIN, service_name, async_handle_cover_service,
            schema=schema)

    return True
    def test_set_entity_namespace_via_config(self):
        """Test setting an entity namespace."""
        def platform_setup(hass, config, add_devices, discovery_info=None):
            """Test the platform setup."""
            add_devices([
                MockEntity(name='beer'),
                MockEntity(name=None),
            ])

        platform = MockPlatform(platform_setup)

        loader.set_component(self.hass, 'test_domain.platform', platform)

        component = EntityComponent(_LOGGER, DOMAIN, self.hass)

        component.setup({
            DOMAIN: {
                'platform': 'platform',
                'entity_namespace': 'yummy'
            }
        })

        self.hass.block_till_done()

        assert sorted(self.hass.states.entity_ids()) == \
            ['test_domain.yummy_beer', 'test_domain.yummy_unnamed_device']
Exemplo n.º 10
0
def setup(hass, config):
    """Track states and offer events for covers."""
    component = EntityComponent(
        _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_COVERS)
    component.setup(config)

    def handle_cover_service(service):
        """Handle calls to the cover services."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = service.data.copy()
        params.pop(ATTR_ENTITY_ID, None)

        if method:
            for cover in component.extract_from_service(service):
                getattr(cover, method['method'])(**params)

                if cover.should_poll:
                    cover.update_ha_state(True)

    descriptions = load_yaml_config_file(
        os.path.join(os.path.dirname(__file__), 'services.yaml'))

    for service_name in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[service_name].get(
            'schema', COVER_SERVICE_SCHEMA)
        hass.services.register(DOMAIN, service_name, handle_cover_service,
                               descriptions.get(service_name), schema=schema)
    return True
Exemplo n.º 11
0
def setup(hass, config):
    """Track states and offer events for switches."""
    component = EntityComponent(
        _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_SWITCHES)
    component.setup(config)

    def handle_switch_service(service):
        """Handle calls to the switch services."""
        target_switches = component.extract_from_service(service)

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

            if switch.should_poll:
                switch.update_ha_state(True)

    descriptions = load_yaml_config_file(
        os.path.join(os.path.dirname(__file__), 'services.yaml'))
    hass.services.register(DOMAIN, SERVICE_TURN_OFF, handle_switch_service,
                           descriptions.get(SERVICE_TURN_OFF),
                           schema=SWITCH_SERVICE_SCHEMA)
    hass.services.register(DOMAIN, SERVICE_TURN_ON, handle_switch_service,
                           descriptions.get(SERVICE_TURN_ON),
                           schema=SWITCH_SERVICE_SCHEMA)
    hass.services.register(DOMAIN, SERVICE_TOGGLE, handle_switch_service,
                           descriptions.get(SERVICE_TOGGLE),
                           schema=SWITCH_SERVICE_SCHEMA)

    return True
Exemplo n.º 12
0
def async_setup(hass, config):
    """Track states and offer events for calendars."""
    component = EntityComponent(
        _LOGGER, DOMAIN, hass, SCAN_INTERVAL, DOMAIN)

    yield from component.async_setup(config)
    return True
Exemplo n.º 13
0
def setup(hass, config):
    """ Track states and offer events for garage door. """
    component = EntityComponent(
        _LOGGER, DOMAIN, hass, SCAN_INTERVAL, DISCOVERY_PLATFORMS,
        GROUP_NAME_ALL_GARAGE_DOORS)
    component.setup(config)

    def handle_garage_door_service(service):
        """ Handles calls to the garage door services. """
        target_locks = component.extract_from_service(service)

        for item in target_locks:
            if service.service == SERVICE_CLOSE:
                item.close_door()
            else:
                item.open_door()

            if item.should_poll:
                item.update_ha_state(True)

    descriptions = load_yaml_config_file(
        os.path.join(os.path.dirname(__file__), 'services.yaml'))
    hass.services.register(DOMAIN, SERVICE_OPEN, handle_garage_door_service,
                           descriptions.get(SERVICE_OPEN))
    hass.services.register(DOMAIN, SERVICE_CLOSE, handle_garage_door_service,
                           descriptions.get(SERVICE_CLOSE))

    return True
Exemplo n.º 14
0
    def test_setup_recovers_when_setup_raises(self):
        """Test the setup if exceptions are happening."""
        platform1_setup = Mock(side_effect=Exception("Broken"))
        platform2_setup = Mock(return_value=None)

        loader.set_component("test_domain.mod1", MockPlatform(platform1_setup))
        loader.set_component("test_domain.mod2", MockPlatform(platform2_setup))

        component = EntityComponent(_LOGGER, DOMAIN, self.hass)

        assert not platform1_setup.called
        assert not platform2_setup.called

        component.setup(
            OrderedDict(
                [
                    (DOMAIN, {"platform": "mod1"}),
                    ("{} 2".format(DOMAIN), {"platform": "non_exist"}),
                    ("{} 3".format(DOMAIN), {"platform": "mod2"}),
                ]
            )
        )

        assert platform1_setup.called
        assert platform2_setup.called
Exemplo n.º 15
0
def setup(hass, config):
    """Setup scenes."""
    logger = logging.getLogger(__name__)

    # You are not allowed to mutate the original config so make a copy
    config = dict(config)

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

        if not any(CONF_PLATFORM in entry for entry in platform_config):
            platform_config = [{'platform': 'homeassistant', 'states': entry}
                               for entry in platform_config]

        config[config_key] = platform_config

    component = EntityComponent(logger, DOMAIN, hass)

    component.setup(config)

    def handle_scene_service(service):
        """Handle calls to the switch services."""
        target_scenes = component.extract_from_service(service)

        for scene in target_scenes:
            scene.activate()

    hass.services.register(DOMAIN, SERVICE_TURN_ON, handle_scene_service,
                           schema=SCENE_SERVICE_SCHEMA)

    return True
Exemplo n.º 16
0
def async_setup(hass, config):
    """Track states and offer events for binary sensors."""
    component = EntityComponent(
        logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)

    yield from component.async_setup(config)
    return True
Exemplo n.º 17
0
def async_setup(hass, config: dict):
    """Expose fan control via statemachine and services."""
    component = EntityComponent(
        _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_FANS)

    yield from component.async_setup(config)

    @asyncio.coroutine
    def async_handle_fan_service(service):
        """Handle service call for fans."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = service.data.copy()

        # Convert the entity ids to valid fan ids
        target_fans = component.async_extract_from_service(service)
        params.pop(ATTR_ENTITY_ID, None)

        update_tasks = []
        for fan in target_fans:
            yield from getattr(fan, method['method'])(**params)
            if not fan.should_poll:
                continue
            update_tasks.append(fan.async_update_ha_state(True))

        if update_tasks:
            yield from asyncio.wait(update_tasks, loop=hass.loop)

    for service_name in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[service_name].get('schema')
        hass.services.async_register(
            DOMAIN, service_name, async_handle_fan_service, schema=schema)

    return True
Exemplo n.º 18
0
    def test_setting_up_group(self):
        """Setup the setting of a group."""
        component = EntityComponent(_LOGGER, DOMAIN, self.hass,
                                    group_name='everyone')

        # No group after setup
        assert len(self.hass.states.entity_ids()) == 0

        component.add_entities([EntityTest(name='hello')])

        # group exists
        assert len(self.hass.states.entity_ids()) == 2
        assert self.hass.states.entity_ids('group') == ['group.everyone']

        group = self.hass.states.get('group.everyone')

        assert group.attributes.get('entity_id') == ('test_domain.hello',)

        # group extended
        component.add_entities([EntityTest(name='hello2')])

        assert len(self.hass.states.entity_ids()) == 3
        group = self.hass.states.get('group.everyone')

        assert sorted(group.attributes.get('entity_id')) == \
            ['test_domain.hello', 'test_domain.hello2']
Exemplo n.º 19
0
def async_setup(hass, config):
    """Track states and offer events for sensors."""
    component = EntityComponent(
        logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)

    yield from component.async_setup(config)

    @asyncio.coroutine
    def async_alarm_service_handler(service):
        """Map services to methods on Alarm."""
        target_alarms = component.async_extract_from_service(service)

        code = service.data.get(ATTR_CODE)

        method = "async_{}".format(SERVICE_TO_METHOD[service.service])

        update_tasks = []
        for alarm in target_alarms:
            yield from getattr(alarm, method)(code)

            if not alarm.should_poll:
                continue
            update_tasks.append(alarm.async_update_ha_state(True))

        if update_tasks:
            yield from asyncio.wait(update_tasks, loop=hass.loop)

    for service in SERVICE_TO_METHOD:
        hass.services.async_register(
            DOMAIN, service, async_alarm_service_handler,
            schema=ALARM_SERVICE_SCHEMA)

    return True
Exemplo n.º 20
0
def async_setup(hass, config):
    """Set up the vacuum component."""
    component = EntityComponent(
        _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_VACUUMS)

    yield from component.async_setup(config)

    @asyncio.coroutine
    def async_handle_vacuum_service(service):
        """Map services to methods on VacuumDevice."""
        method = SERVICE_TO_METHOD.get(service.service)
        target_vacuums = component.async_extract_from_service(service)
        params = service.data.copy()
        params.pop(ATTR_ENTITY_ID, None)

        update_tasks = []
        for vacuum in target_vacuums:
            yield from getattr(vacuum, method['method'])(**params)
            if not vacuum.should_poll:
                continue
            update_tasks.append(vacuum.async_update_ha_state(True))

        if update_tasks:
            yield from asyncio.wait(update_tasks, loop=hass.loop)

    for service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[service].get(
            'schema', VACUUM_SERVICE_SCHEMA)
        hass.services.async_register(
            DOMAIN, service, async_handle_vacuum_service,
            schema=schema)

    return True
Exemplo n.º 21
0
def setup(hass, config):
    """Track states and offer events for sensors."""
    component = EntityComponent(
        logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL,
        DISCOVERY_PLATFORMS)

    component.setup(config)

    def alarm_service_handler(service):
        """Map services to methods on Alarm."""
        target_alarms = component.extract_from_service(service)

        if ATTR_CODE not in service.data:
            code = None
        else:
            code = service.data[ATTR_CODE]

        method = SERVICE_TO_METHOD[service.service]

        for alarm in target_alarms:
            getattr(alarm, method)(code)
            if alarm.should_poll:
                alarm.update_ha_state(True)

    descriptions = load_yaml_config_file(
        os.path.join(os.path.dirname(__file__), 'services.yaml'))

    for service in SERVICE_TO_METHOD:
        hass.services.register(DOMAIN, service, alarm_service_handler,
                               descriptions.get(service))

    return True
Exemplo n.º 22
0
def async_setup(hass, config):
    """Setup input select."""
    component = EntityComponent(_LOGGER, DOMAIN, hass)

    entities = []

    for object_id, cfg in config[DOMAIN].items():
        name = cfg.get(CONF_NAME)
        options = cfg.get(CONF_OPTIONS)
        state = cfg.get(CONF_INITIAL, options[0])
        icon = cfg.get(CONF_ICON)
        entities.append(InputSelect(object_id, name, state, options, icon))

    if not entities:
        return False

    @asyncio.coroutine
    def async_select_option_service(call):
        """Handle a calls to the input select option service."""
        target_inputs = component.async_extract_from_service(call)

        tasks = [input_select.async_select_option(call.data[ATTR_OPTION])
                 for input_select in target_inputs]
        if tasks:
            yield from asyncio.wait(tasks, loop=hass.loop)

    hass.services.async_register(
        DOMAIN, SERVICE_SELECT_OPTION, async_select_option_service,
        schema=SERVICE_SELECT_OPTION_SCHEMA)

    @asyncio.coroutine
    def async_select_next_service(call):
        """Handle a calls to the input select next service."""
        target_inputs = component.async_extract_from_service(call)

        tasks = [input_select.async_offset_index(1)
                 for input_select in target_inputs]
        if tasks:
            yield from asyncio.wait(tasks, loop=hass.loop)

    hass.services.async_register(
        DOMAIN, SERVICE_SELECT_NEXT, async_select_next_service,
        schema=SERVICE_SELECT_NEXT_SCHEMA)

    @asyncio.coroutine
    def async_select_previous_service(call):
        """Handle a calls to the input select previous service."""
        target_inputs = component.async_extract_from_service(call)

        tasks = [input_select.async_offset_index(-1)
                 for input_select in target_inputs]
        if tasks:
            yield from asyncio.wait(tasks, loop=hass.loop)

    hass.services.async_register(
        DOMAIN, SERVICE_SELECT_PREVIOUS, async_select_previous_service,
        schema=SERVICE_SELECT_PREVIOUS_SCHEMA)

    yield from component.async_add_entities(entities)
    return True
def test_pararell_updates_async_platform_with_constant(hass):
    """Warn we log when platform setup takes a long time."""
    platform = MockPlatform()

    @asyncio.coroutine
    def mock_update(*args, **kwargs):
        pass

    platform.async_setup_platform = mock_update
    platform.PARALLEL_UPDATES = 1

    loader.set_component('test_domain.platform', platform)

    component = EntityComponent(_LOGGER, DOMAIN, hass)
    component._platforms = {}

    yield from component.async_setup({
        DOMAIN: {
            'platform': 'platform',
        }
    })

    handle = list(component._platforms.values())[-1]

    assert handle.parallel_updates is not None
Exemplo n.º 24
0
def setup(hass, config):
    """Setup input select."""
    component = EntityComponent(_LOGGER, DOMAIN, hass)

    entities = []

    for object_id, cfg in config[DOMAIN].items():
        name = cfg.get(CONF_NAME)
        options = cfg.get(CONF_OPTIONS)
        state = cfg.get(CONF_INITIAL, options[0])
        icon = cfg.get(CONF_ICON)
        entities.append(InputSelect(object_id, name, state, options, icon))

    if not entities:
        return False

    def select_option_service(call):
        """Handle a calls to the input select services."""
        target_inputs = component.extract_from_service(call)

        for input_select in target_inputs:
            input_select.select_option(call.data[ATTR_OPTION])

    hass.services.register(DOMAIN, SERVICE_SELECT_OPTION,
                           select_option_service,
                           schema=SERVICE_SELECT_OPTION_SCHEMA)

    component.add_entities(entities)

    return True
Exemplo n.º 25
0
def async_setup(hass, config):
    """Track states and offer events for remotes."""
    component = EntityComponent(
        _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_REMOTES)
    yield from component.async_setup(config)

    component.async_register_entity_service(
        SERVICE_TURN_OFF, REMOTE_SERVICE_ACTIVITY_SCHEMA,
        'async_turn_off'
    )

    component.async_register_entity_service(
        SERVICE_TURN_ON, REMOTE_SERVICE_ACTIVITY_SCHEMA,
        'async_turn_on'
    )

    component.async_register_entity_service(
        SERVICE_TOGGLE, REMOTE_SERVICE_ACTIVITY_SCHEMA,
        'async_toggle'
    )

    component.async_register_entity_service(
        SERVICE_SEND_COMMAND, REMOTE_SERVICE_SEND_COMMAND_SCHEMA,
        'async_send_command'
    )

    return True
def test_entity_with_name_and_entity_id_getting_registered(hass):
    """Ensure that entity ID is used for registration."""
    component = EntityComponent(_LOGGER, DOMAIN, hass)
    yield from component.async_add_entities([
        MockEntity(unique_id='1234', name='bla',
                   entity_id='test_domain.world')])
    assert 'test_domain.world' in hass.states.async_entity_ids()
    def test_setting_up_group(self):
        component = EntityComponent(_LOGGER, DOMAIN, self.hass,
                                    group_name='everyone')

        # No group after setup
        assert 0 == len(self.hass.states.entity_ids())

        component.add_entities([EntityTest(name='hello')])

        # group exists
        assert 2 == len(self.hass.states.entity_ids())
        assert ['group.everyone'] == self.hass.states.entity_ids('group')

        group = self.hass.states.get('group.everyone')

        assert ('test_domain.hello',) == group.attributes.get('entity_id')

        # group extended
        component.add_entities([EntityTest(name='hello2')])

        assert 3 == len(self.hass.states.entity_ids())
        group = self.hass.states.get('group.everyone')

        assert ['test_domain.hello', 'test_domain.hello2'] == \
            sorted(group.attributes.get('entity_id'))
Exemplo n.º 28
0
def setup(hass, config):
    """ Track states and offer events for sensors. """
    component = EntityComponent(
        logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL,
        DISCOVERY_PLATFORMS)

    component.setup(config)

    def alarm_service_handler(service):
        """ Maps services to methods on Alarm. """
        target_alarms = component.extract_from_service(service)

        if ATTR_CODE not in service.data:
            return

        code = service.data[ATTR_CODE]

        method = SERVICE_TO_METHOD[service.service]

        for alarm in target_alarms:
            getattr(alarm, method)(code)

    for service in SERVICE_TO_METHOD:
        hass.services.register(DOMAIN, service, alarm_service_handler)

    return True
def test_not_fails_with_adding_empty_entities_(hass):
    """Test for not fails on empty entities list."""
    component = EntityComponent(_LOGGER, DOMAIN, hass)

    yield from component.async_add_entities([])

    assert len(hass.states.async_entity_ids()) == 0
Exemplo n.º 30
0
def async_setup(hass, config):
    """Set up image processing."""
    component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)

    yield from component.async_setup(config)

    descriptions = yield from hass.async_add_job(
        load_yaml_config_file,
        os.path.join(os.path.dirname(__file__), 'services.yaml'))

    @asyncio.coroutine
    def async_scan_service(service):
        """Service handler for scan."""
        image_entities = component.async_extract_from_service(service)

        update_task = [entity.async_update_ha_state(True) for
                       entity in image_entities]
        if update_task:
            yield from asyncio.wait(update_task, loop=hass.loop)

    hass.services.async_register(
        DOMAIN, SERVICE_SCAN, async_scan_service,
        descriptions.get(SERVICE_SCAN), schema=SERVICE_SCAN_SCHEMA)

    return True
Exemplo n.º 31
0
def async_setup(hass, config):
    """Track states and offer events for calendars."""
    component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL, DOMAIN)

    yield from component.async_setup(config)
    return True
Exemplo n.º 32
0
async def async_setup(hass, config):
    """Expose light control via state machine and services."""
    component = hass.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, hass,
                                                    SCAN_INTERVAL)
    await component.async_setup(config)

    profiles = hass.data[DATA_PROFILES] = Profiles(hass)
    await profiles.async_initialize()

    def preprocess_data(data):
        """Preprocess the service data."""
        base = {
            entity_field: data.pop(entity_field)
            for entity_field in cv.ENTITY_SERVICE_FIELDS
            if entity_field in data
        }

        preprocess_turn_on_alternatives(hass, data)
        base["params"] = data
        return base

    async def async_handle_light_on_service(light, call):
        """Handle turning a light on.

        If brightness is set to 0, this service will turn the light off.
        """
        params = dict(call.data["params"])

        # Only process params once we processed brightness step
        if params and (ATTR_BRIGHTNESS_STEP in params
                       or ATTR_BRIGHTNESS_STEP_PCT in params):
            brightness = light.brightness if light.is_on else 0

            if ATTR_BRIGHTNESS_STEP in params:
                brightness += params.pop(ATTR_BRIGHTNESS_STEP)

            else:
                brightness += round(
                    params.pop(ATTR_BRIGHTNESS_STEP_PCT) / 100 * 255)

            params[ATTR_BRIGHTNESS] = max(0, min(255, brightness))

            preprocess_turn_on_alternatives(hass, params)

        if ATTR_PROFILE not in params:
            profiles.apply_default(light.entity_id, params)

        supported_color_modes = light.supported_color_modes
        # Backwards compatibility: if an RGBWW color is specified, convert to RGB + W
        # for legacy lights
        if ATTR_RGBW_COLOR in params:
            legacy_supported_color_modes = (
                light._light_internal_supported_color_modes  # pylint: disable=protected-access
            )
            if (COLOR_MODE_RGBW in legacy_supported_color_modes
                    and not supported_color_modes):
                rgbw_color = params.pop(ATTR_RGBW_COLOR)
                params[ATTR_RGB_COLOR] = rgbw_color[0:3]
                params[ATTR_WHITE_VALUE] = rgbw_color[3]

        # If a color is specified, convert to the color space supported by the light
        # Backwards compatibility: Fall back to hs color if light.supported_color_modes
        # is not implemented
        if not supported_color_modes:
            if (rgb_color := params.pop(ATTR_RGB_COLOR, None)) is not None:
                params[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color)
            elif (xy_color := params.pop(ATTR_XY_COLOR, None)) is not None:
                params[ATTR_HS_COLOR] = color_util.color_xy_to_hs(*xy_color)
Exemplo n.º 33
0
def test_using_prescribed_entity_id(hass):
    """Test for using predefined entity ID."""
    component = EntityComponent(_LOGGER, DOMAIN, hass)
    yield from component.async_add_entities([
        MockEntity(name='bla', entity_id='hello.world')])
    assert 'hello.world' in hass.states.async_entity_ids()
Exemplo n.º 34
0
def setup(hass, config):
    """Setup zigate platform."""
    import zigate

    port = config[DOMAIN].get(CONF_PORT)
    host = config[DOMAIN].get(CONF_HOST)
    persistent_file = os.path.join(hass.config.config_dir, '.zigate.json')

    myzigate = zigate.connect(port=port,
                              host=host,
                              path=persistent_file,
                              auto_start=False)
    #     if host:
    #         host = host.split(':', 1)
    #         port = None
    #         if len(host) == 2:
    #             port = int(host[1])
    #         myzigate = zigate.ZiGateWiFi(host[0],
    #                                      port,
    #                                      path=persistent_file,
    #                                      auto_start=False)
    #     else:
    #         myzigate = zigate.ZiGate(port,
    #                                  path=persistent_file,
    #                                  auto_start=False)

    hass.data[DOMAIN] = myzigate
    hass.data[DATA_ZIGATE_DEVICES] = {}
    hass.data[DATA_ZIGATE_ATTRS] = {}

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    def device_added(**kwargs):
        device = kwargs['device']
        _LOGGER.debug('Add device {}'.format(device))
        if device.addr not in hass.data[DATA_ZIGATE_DEVICES]:
            entity = ZiGateDeviceEntity(device)
            hass.data[DATA_ZIGATE_DEVICES][device.addr] = entity
            component.add_entities([entity])
            if 'signal' in kwargs:
                hass.components.persistent_notification.create(
                    ('A new ZiGate device "{}"'
                     ' has been added !').format(device),
                    title='ZiGate')

    def device_removed(**kwargs):
        # component.async_remove_entity
        addr = kwargs['addr']
        hass.components.persistent_notification.create(
            'The ZiGate device {} has leaved.'.format(addr), title='ZiGate')

    def device_need_refresh(**kwargs):
        device = kwargs['device']
        hass.components.persistent_notification.create(
            ('The ZiGate device {} needs some'
             ' refresh (missing important'
             ' information)').format(device.addr),
            title='ZiGate')

    zigate.dispatcher.connect(device_added,
                              zigate.ZIGATE_DEVICE_ADDED,
                              weak=False)
    zigate.dispatcher.connect(device_removed,
                              zigate.ZIGATE_DEVICE_REMOVED,
                              weak=False)
    zigate.dispatcher.connect(device_need_refresh,
                              zigate.ZIGATE_DEVICE_NEED_REFRESH,
                              weak=False)

    def attribute_updated(**kwargs):
        device = kwargs['device']
        attribute = kwargs['attribute']
        _LOGGER.debug('Update attribute for device {} {}'.format(
            device, attribute))
        key = '{}-{}-{}-{}'.format(
            device.addr,
            attribute['endpoint'],
            attribute['cluster'],
            attribute['attribute'],
        )
        entity = hass.data[DATA_ZIGATE_ATTRS].get(key)
        if entity:
            if entity.hass:
                entity.schedule_update_ha_state()
        key = '{}-{}-{}'.format(
            device.addr,
            'switch',
            attribute['endpoint'],
        )
        entity = hass.data[DATA_ZIGATE_ATTRS].get(key)
        if entity:
            if entity.hass:
                entity.schedule_update_ha_state()
        key = '{}-{}-{}'.format(
            device.addr,
            'light',
            attribute['endpoint'],
        )
        entity = hass.data[DATA_ZIGATE_ATTRS].get(key)
        if entity:
            if entity.hass:
                entity.schedule_update_ha_state()
        entity = hass.data[DATA_ZIGATE_DEVICES].get(device.addr)
        if entity:
            if entity.hass:
                entity.schedule_update_ha_state()

    zigate.dispatcher.connect(attribute_updated,
                              zigate.ZIGATE_ATTRIBUTE_UPDATED,
                              weak=False)

    def device_updated(**kwargs):
        device = kwargs['device']
        _LOGGER.debug('Update device {}'.format(device))
        entity = hass.data[DATA_ZIGATE_DEVICES].get(device.addr)
        if entity:
            if entity.hass:
                entity.schedule_update_ha_state()
        else:
            _LOGGER.debug('Device not found {}, adding it'.format(device))
            device_added(device=device)

        zigate.dispatcher.connect(device_updated,
                                  zigate.ZIGATE_DEVICE_UPDATED,
                                  weak=False)
        zigate.dispatcher.connect(device_updated,
                                  zigate.ZIGATE_ATTRIBUTE_ADDED,
                                  weak=False)

    def zigate_reset(service):
        myzigate.reset()

    def permit_join(service):
        myzigate.permit_join()

    def zigate_cleanup(service):
        '''
        Remove missing device
        '''
        myzigate.cleanup_devices()

    def start_zigate(service_event=None):
        myzigate.autoStart()
        myzigate.start_auto_save()
        version = myzigate.get_version_text()
        if version < '3.0d':
            hass.components.persistent_notification.create(
                ('Your zigate firmware is outdated, '
                 'Please upgrade to 3.0d or later !'),
                title='ZiGate')
        # first load
        for device in myzigate.devices:
            device_added(device=device)

        for platform in SUPPORTED_PLATFORMS:
            load_platform(hass, platform, DOMAIN, {}, config)

    def stop_zigate(service_event):
        myzigate.save_state()
        myzigate.close()

    def refresh_devices_list(service):
        myzigate.get_devices_list()

    def refresh_device(service):
        addr = service.data.get(ADDR)
        entity_id = service.data.get(ATTR_ENTITY_ID)
        if entity_id:
            entity = component.get_entity(entity_id)
            if entity:
                addr = entity._device.addr
        if addr:
            myzigate.refresh_device(addr)
        else:
            for device in myzigate.devices:
                device.refresh_device()

    def network_scan(service):
        myzigate.start_network_scan()

    def raw_command(service):
        cmd = int(service.data.get('cmd'), 16)
        data = service.data.get('data', '')
        myzigate.send_data(cmd, data)

    def identify_device(service):
        addr = service.data.get('addr')
        myzigate.identify_device(addr)

    def initiate_touchlink(service):
        myzigate.initiate_touchlink()

    def touchlink_factory_reset(service):
        myzigate.touchlink_factory_reset()

    hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zigate)
    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zigate)

    hass.services.register(DOMAIN, 'refresh_devices_list',
                           refresh_devices_list)
    hass.services.register(DOMAIN, 'reset', zigate_reset)
    hass.services.register(DOMAIN, 'permit_join', permit_join)
    hass.services.register(DOMAIN, 'start_zigate', start_zigate)
    hass.services.register(DOMAIN, 'stop_zigate', stop_zigate)
    hass.services.register(DOMAIN, 'cleanup_devices', zigate_cleanup)
    hass.services.register(DOMAIN,
                           'refresh_device',
                           refresh_device,
                           schema=REFRESH_DEVICE_SCHEMA)
    hass.services.register(DOMAIN, 'network_scan', network_scan)
    hass.services.register(DOMAIN,
                           'raw_command',
                           raw_command,
                           schema=RAW_COMMAND_SCHEMA)
    hass.services.register(DOMAIN,
                           'identify_device',
                           identify_device,
                           schema=IDENTIFY_SCHEMA)
    hass.services.register(DOMAIN, 'initiate_touchlink', initiate_touchlink)
    hass.services.register(DOMAIN, 'touchlink_factory_reset',
                           touchlink_factory_reset)

    track_time_change(hass, refresh_devices_list, hour=0, minute=0, second=0)

    return True
Exemplo n.º 35
0
def async_setup(hass, config):
    """Track states and offer events for remotes."""
    component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL,
                                GROUP_NAME_ALL_REMOTES)
    yield from component.async_setup(config)

    component.async_register_entity_service(SERVICE_TURN_OFF,
                                            REMOTE_SERVICE_ACTIVITY_SCHEMA,
                                            'async_turn_off')

    component.async_register_entity_service(SERVICE_TURN_ON,
                                            REMOTE_SERVICE_ACTIVITY_SCHEMA,
                                            'async_turn_on')

    component.async_register_entity_service(SERVICE_TOGGLE,
                                            REMOTE_SERVICE_ACTIVITY_SCHEMA,
                                            'async_toggle')

    component.async_register_entity_service(
        SERVICE_SEND_COMMAND, REMOTE_SERVICE_SEND_COMMAND_SCHEMA,
        'async_send_command')

    return True
Exemplo n.º 36
0
async def async_setup(hass, config):
    """Set up the Geolocation component."""
    component = hass.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, hass,
                                                    SCAN_INTERVAL)
    await component.async_setup(config)
    return True
Exemplo n.º 37
0
async def async_setup(hass, config):
    """Set up the camera component."""
    component = hass.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, hass,
                                                    SCAN_INTERVAL)

    prefs = CameraPreferences(hass)
    await prefs.async_initialize()
    hass.data[DATA_CAMERA_PREFS] = prefs

    hass.http.register_view(CameraImageView(component))
    hass.http.register_view(CameraMjpegStream(component))
    hass.components.websocket_api.async_register_command(
        WS_TYPE_CAMERA_THUMBNAIL, websocket_camera_thumbnail,
        SCHEMA_WS_CAMERA_THUMBNAIL)
    hass.components.websocket_api.async_register_command(ws_camera_stream)
    hass.components.websocket_api.async_register_command(websocket_get_prefs)
    hass.components.websocket_api.async_register_command(
        websocket_update_prefs)

    await component.async_setup(config)

    async def preload_stream(_):
        for camera in component.entities:
            camera_prefs = prefs.get(camera.entity_id)
            if not camera_prefs.preload_stream:
                continue

            async with async_timeout.timeout(10):
                source = await camera.stream_source()

            if not source:
                continue

            request_stream(hass,
                           source,
                           keepalive=True,
                           options=camera.stream_options)

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, preload_stream)

    @callback
    def update_tokens(time):
        """Update tokens of the entities."""
        for entity in component.entities:
            entity.async_update_token()
            entity.async_write_ha_state()

    hass.helpers.event.async_track_time_interval(update_tokens,
                                                 TOKEN_CHANGE_INTERVAL)

    component.async_register_entity_service(SERVICE_ENABLE_MOTION,
                                            CAMERA_SERVICE_SCHEMA,
                                            "async_enable_motion_detection")
    component.async_register_entity_service(SERVICE_DISABLE_MOTION,
                                            CAMERA_SERVICE_SCHEMA,
                                            "async_disable_motion_detection")
    component.async_register_entity_service(SERVICE_TURN_OFF,
                                            CAMERA_SERVICE_SCHEMA,
                                            "async_turn_off")
    component.async_register_entity_service(SERVICE_TURN_ON,
                                            CAMERA_SERVICE_SCHEMA,
                                            "async_turn_on")
    component.async_register_entity_service(SERVICE_SNAPSHOT,
                                            CAMERA_SERVICE_SNAPSHOT,
                                            async_handle_snapshot_service)
    component.async_register_entity_service(
        SERVICE_PLAY_STREAM,
        CAMERA_SERVICE_PLAY_STREAM,
        async_handle_play_stream_service,
    )
    component.async_register_entity_service(SERVICE_RECORD,
                                            CAMERA_SERVICE_RECORD,
                                            async_handle_record_service)

    return True
Exemplo n.º 38
0
async def async_setup(hass, config):
    """Set up the automation."""
    component = EntityComponent(
        _LOGGER, DOMAIN, hass, group_name=GROUP_NAME_ALL_AUTOMATIONS
    )

    await _async_process_config(hass, config, component)

    async def trigger_service_handler(service_call):
        """Handle automation triggers."""
        tasks = []
        for entity in await component.async_extract_from_service(service_call):
            tasks.append(
                entity.async_trigger(
                    service_call.data.get(ATTR_VARIABLES),
                    skip_condition=True,
                    context=service_call.context,
                )
            )

        if tasks:
            await asyncio.wait(tasks)

    async def turn_onoff_service_handler(service_call):
        """Handle automation turn on/off service calls."""
        tasks = []
        method = "async_{}".format(service_call.service)
        for entity in await component.async_extract_from_service(service_call):
            tasks.append(getattr(entity, method)())

        if tasks:
            await asyncio.wait(tasks)

    async def toggle_service_handler(service_call):
        """Handle automation toggle service calls."""
        tasks = []
        for entity in await component.async_extract_from_service(service_call):
            if entity.is_on:
                tasks.append(entity.async_turn_off())
            else:
                tasks.append(entity.async_turn_on())

        if tasks:
            await asyncio.wait(tasks)

    async def reload_service_handler(service_call):
        """Remove all automations and load new ones from config."""
        conf = await component.async_prepare_reload()
        if conf is None:
            return
        await _async_process_config(hass, conf, component)

    hass.services.async_register(
        DOMAIN, SERVICE_TRIGGER, trigger_service_handler, schema=TRIGGER_SERVICE_SCHEMA
    )

    hass.services.async_register(
        DOMAIN, SERVICE_RELOAD, reload_service_handler, schema=RELOAD_SERVICE_SCHEMA
    )

    hass.services.async_register(
        DOMAIN, SERVICE_TOGGLE, toggle_service_handler, schema=ENTITY_SERVICE_SCHEMA
    )

    for service in (SERVICE_TURN_ON, SERVICE_TURN_OFF):
        hass.services.async_register(
            DOMAIN, service, turn_onoff_service_handler, schema=ENTITY_SERVICE_SCHEMA
        )

    return True
Exemplo n.º 39
0
def async_setup(hass, config):
    """Set up the camera component."""
    component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)

    hass.http.register_view(CameraImageView(component.entities))
    hass.http.register_view(CameraMjpegStream(component.entities))

    yield from component.async_setup(config)

    @callback
    def update_tokens(time):
        """Update tokens of the entities."""
        for entity in component.entities.values():
            entity.async_update_token()
            hass.async_add_job(entity.async_update_ha_state())

    hass.helpers.event.async_track_time_interval(
        update_tokens, TOKEN_CHANGE_INTERVAL)

    @asyncio.coroutine
    def async_handle_camera_service(service):
        """Handle calls to the camera services."""
        target_cameras = component.async_extract_from_service(service)

        update_tasks = []
        for camera in target_cameras:
            if service.service == SERVICE_ENABLE_MOTION:
                yield from camera.async_enable_motion_detection()
            elif service.service == SERVICE_DISABLE_MOTION:
                yield from camera.async_disable_motion_detection()

            if not camera.should_poll:
                continue
            update_tasks.append(camera.async_update_ha_state(True))

        if update_tasks:
            yield from asyncio.wait(update_tasks, loop=hass.loop)

    @asyncio.coroutine
    def async_handle_snapshot_service(service):
        """Handle snapshot services calls."""
        target_cameras = component.async_extract_from_service(service)
        filename = service.data[ATTR_FILENAME]
        filename.hass = hass

        for camera in target_cameras:
            snapshot_file = filename.async_render(
                variables={ATTR_ENTITY_ID: camera})

            # check if we allow to access to that file
            if not hass.config.is_allowed_path(snapshot_file):
                _LOGGER.error(
                    "Can't write %s, no access to path!", snapshot_file)
                continue

            image = yield from camera.async_camera_image()

            def _write_image(to_file, image_data):
                """Executor helper to write image."""
                with open(to_file, 'wb') as img_file:
                    img_file.write(image_data)

            try:
                yield from hass.async_add_job(
                    _write_image, snapshot_file, image)
            except OSError as err:
                _LOGGER.error("Can't write image to file: %s", err)

    descriptions = yield from hass.async_add_job(
        load_yaml_config_file, os.path.join(
            os.path.dirname(__file__), 'services.yaml'))

    hass.services.async_register(
        DOMAIN, SERVICE_ENABLE_MOTION, async_handle_camera_service,
        descriptions.get(SERVICE_ENABLE_MOTION), schema=CAMERA_SERVICE_SCHEMA)
    hass.services.async_register(
        DOMAIN, SERVICE_DISABLE_MOTION, async_handle_camera_service,
        descriptions.get(SERVICE_DISABLE_MOTION), schema=CAMERA_SERVICE_SCHEMA)
    hass.services.async_register(
        DOMAIN, SERVICE_SNAPSHOT, async_handle_snapshot_service,
        descriptions.get(SERVICE_SNAPSHOT),
        schema=CAMERA_SERVICE_SNAPSHOT)

    return True
Exemplo n.º 40
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Expose fan control via statemachine and services."""
    component = hass.data[DOMAIN] = EntityComponent(
        _LOGGER, DOMAIN, hass, SCAN_INTERVAL
    )

    await component.async_setup(config)

    # After the transition to percentage and preset_modes concludes,
    # switch this back to async_turn_on and remove async_turn_on_compat
    component.async_register_entity_service(
        SERVICE_TURN_ON,
        {
            vol.Optional(ATTR_PERCENTAGE): vol.All(
                vol.Coerce(int), vol.Range(min=0, max=100)
            ),
            vol.Optional(ATTR_PRESET_MODE): cv.string,
        },
        "async_turn_on",
    )
    component.async_register_entity_service(SERVICE_TURN_OFF, {}, "async_turn_off")
    component.async_register_entity_service(SERVICE_TOGGLE, {}, "async_toggle")
    component.async_register_entity_service(
        SERVICE_INCREASE_SPEED,
        {
            vol.Optional(ATTR_PERCENTAGE_STEP): vol.All(
                vol.Coerce(int), vol.Range(min=0, max=100)
            )
        },
        "async_increase_speed",
        [FanEntityFeature.SET_SPEED],
    )
    component.async_register_entity_service(
        SERVICE_DECREASE_SPEED,
        {
            vol.Optional(ATTR_PERCENTAGE_STEP): vol.All(
                vol.Coerce(int), vol.Range(min=0, max=100)
            )
        },
        "async_decrease_speed",
        [FanEntityFeature.SET_SPEED],
    )
    component.async_register_entity_service(
        SERVICE_OSCILLATE,
        {vol.Required(ATTR_OSCILLATING): cv.boolean},
        "async_oscillate",
        [FanEntityFeature.OSCILLATE],
    )
    component.async_register_entity_service(
        SERVICE_SET_DIRECTION,
        {vol.Optional(ATTR_DIRECTION): cv.string},
        "async_set_direction",
        [FanEntityFeature.DIRECTION],
    )
    component.async_register_entity_service(
        SERVICE_SET_PERCENTAGE,
        {
            vol.Required(ATTR_PERCENTAGE): vol.All(
                vol.Coerce(int), vol.Range(min=0, max=100)
            )
        },
        "async_set_percentage",
        [FanEntityFeature.SET_SPEED],
    )
    component.async_register_entity_service(
        SERVICE_SET_PRESET_MODE,
        {vol.Required(ATTR_PRESET_MODE): cv.string},
        "async_set_preset_mode",
        [FanEntityFeature.SET_SPEED, FanEntityFeature.PRESET_MODE],
    )

    return True
Exemplo n.º 41
0
async def async_setup(hass, config):
    """Track states and offer events for media_players."""
    component = hass.data[DOMAIN] = EntityComponent(
        logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)

    hass.components.websocket_api.async_register_command(
        WS_TYPE_MEDIA_PLAYER_THUMBNAIL, websocket_handle_thumbnail,
        SCHEMA_WEBSOCKET_GET_THUMBNAIL)
    hass.http.register_view(MediaPlayerImageView(component))

    await component.async_setup(config)

    component.async_register_entity_service(SERVICE_TURN_ON,
                                            MEDIA_PLAYER_SCHEMA,
                                            'async_turn_on')
    component.async_register_entity_service(SERVICE_TURN_OFF,
                                            MEDIA_PLAYER_SCHEMA,
                                            'async_turn_off')
    component.async_register_entity_service(SERVICE_TOGGLE,
                                            MEDIA_PLAYER_SCHEMA,
                                            'async_toggle')
    component.async_register_entity_service(SERVICE_VOLUME_UP,
                                            MEDIA_PLAYER_SCHEMA,
                                            'async_volume_up')
    component.async_register_entity_service(SERVICE_VOLUME_DOWN,
                                            MEDIA_PLAYER_SCHEMA,
                                            'async_volume_down')
    component.async_register_entity_service(SERVICE_MEDIA_PLAY_PAUSE,
                                            MEDIA_PLAYER_SCHEMA,
                                            'async_media_play_pause')
    component.async_register_entity_service(SERVICE_MEDIA_PLAY,
                                            MEDIA_PLAYER_SCHEMA,
                                            'async_media_play')
    component.async_register_entity_service(SERVICE_MEDIA_PAUSE,
                                            MEDIA_PLAYER_SCHEMA,
                                            'async_media_pause')
    component.async_register_entity_service(SERVICE_MEDIA_STOP,
                                            MEDIA_PLAYER_SCHEMA,
                                            'async_media_stop')
    component.async_register_entity_service(SERVICE_MEDIA_NEXT_TRACK,
                                            MEDIA_PLAYER_SCHEMA,
                                            'async_media_next_track')
    component.async_register_entity_service(SERVICE_MEDIA_PREVIOUS_TRACK,
                                            MEDIA_PLAYER_SCHEMA,
                                            'async_media_previous_track')
    component.async_register_entity_service(SERVICE_CLEAR_PLAYLIST,
                                            MEDIA_PLAYER_SCHEMA,
                                            'async_clear_playlist')
    component.async_register_entity_service(
        SERVICE_VOLUME_SET, MEDIA_PLAYER_SET_VOLUME_SCHEMA,
        lambda entity, call: entity.async_set_volume_level(volume=call.data[
            ATTR_MEDIA_VOLUME_LEVEL]))
    component.async_register_entity_service(
        SERVICE_VOLUME_MUTE, MEDIA_PLAYER_MUTE_VOLUME_SCHEMA,
        lambda entity, call: entity.async_mute_volume(mute=call.data[
            ATTR_MEDIA_VOLUME_MUTED]))
    component.async_register_entity_service(
        SERVICE_MEDIA_SEEK, MEDIA_PLAYER_MEDIA_SEEK_SCHEMA,
        lambda entity, call: entity.async_media_seek(position=call.data[
            ATTR_MEDIA_SEEK_POSITION]))
    component.async_register_entity_service(SERVICE_SELECT_SOURCE,
                                            MEDIA_PLAYER_SELECT_SOURCE_SCHEMA,
                                            'async_select_source')
    component.async_register_entity_service(
        SERVICE_SELECT_SOUND_MODE, MEDIA_PLAYER_SELECT_SOUND_MODE_SCHEMA,
        'async_select_sound_mode')
    component.async_register_entity_service(
        SERVICE_PLAY_MEDIA, MEDIA_PLAYER_PLAY_MEDIA_SCHEMA,
        lambda entity, call: entity.async_play_media(
            media_type=call.data[ATTR_MEDIA_CONTENT_TYPE],
            media_id=call.data[ATTR_MEDIA_CONTENT_ID],
            enqueue=call.data.get(ATTR_MEDIA_ENQUEUE)))
    component.async_register_entity_service(SERVICE_SHUFFLE_SET,
                                            MEDIA_PLAYER_SET_SHUFFLE_SCHEMA,
                                            'async_set_shuffle')

    return True
Exemplo n.º 42
0
async def async_setup(hass, config):
    """Load the scripts from the configuration."""
    hass.data[DOMAIN] = component = EntityComponent(_LOGGER, DOMAIN, hass)

    await _async_process_config(hass, config, component)

    async def reload_service(service):
        """Call a service to reload scripts."""
        conf = await component.async_prepare_reload()
        if conf is None:
            return

        await _async_process_config(hass, conf, component)

    async def turn_on_service(service):
        """Call a service to turn script on."""
        variables = service.data.get(ATTR_VARIABLES)
        for script_entity in await component.async_extract_from_service(service
                                                                        ):
            if script_entity.script.is_legacy:
                await hass.services.async_call(DOMAIN,
                                               script_entity.object_id,
                                               variables,
                                               context=service.context)
            else:
                await script_entity.async_turn_on(variables=variables,
                                                  context=service.context,
                                                  wait=False)

    async def turn_off_service(service):
        """Cancel a script."""
        # Stopping a script is ok to be done in parallel
        scripts = await component.async_extract_from_service(service)

        if not scripts:
            return

        await asyncio.wait([script.async_turn_off() for script in scripts])

    async def toggle_service(service):
        """Toggle a script."""
        for script_entity in await component.async_extract_from_service(service
                                                                        ):
            await script_entity.async_toggle(context=service.context)

    hass.services.async_register(DOMAIN,
                                 SERVICE_RELOAD,
                                 reload_service,
                                 schema=RELOAD_SERVICE_SCHEMA)
    hass.services.async_register(DOMAIN,
                                 SERVICE_TURN_ON,
                                 turn_on_service,
                                 schema=SCRIPT_TURN_ONOFF_SCHEMA)
    hass.services.async_register(DOMAIN,
                                 SERVICE_TURN_OFF,
                                 turn_off_service,
                                 schema=SCRIPT_TURN_ONOFF_SCHEMA)
    hass.services.async_register(DOMAIN,
                                 SERVICE_TOGGLE,
                                 toggle_service,
                                 schema=SCRIPT_TURN_ONOFF_SCHEMA)

    return True
Exemplo n.º 43
0
async def async_setup(hass, config):
    """Set up variables from config."""
    component = EntityComponent(_LOGGER, DOMAIN, hass)

    entities = []

    for object_id, cfg in config[DOMAIN].items():
        if not cfg:
            cfg = {}

        initial_value = cfg.get(CONF_INITIAL_VALUE)
        unit = cfg.get(ATTR_UNIT_OF_MEASUREMENT)
        restore = cfg.get(CONF_RESTORE, True)
        force_update = cfg.get(CONF_FORCE_UPDATE, False)
        friendly_name = cfg.get(ATTR_FRIENDLY_NAME, object_id)
        icon = cfg.get(CONF_ICON)
        entity_picture = cfg.get(ATTR_ENTITY_PICTURE)

        value_template = cfg.get(CONF_VALUE_TEMPLATE)
        friendly_name_template = cfg.get(CONF_FRIENDLY_NAME_TEMPLATE)
        icon_template = cfg.get(CONF_ICON_TEMPLATE)
        entity_picture_template = cfg.get(CONF_ENTITY_PICTURE_TEMPLATE)
        for template in (
                value_template,
                icon_template,
                entity_picture_template,
                friendly_name_template,
        ):
            if template is not None:
                template.hass = hass

        manual_entity_ids = cfg.get(CONF_TRACKED_ENTITY_ID)

        tracked_entity_ids = list()
        if manual_entity_ids is not None:
            tracked_entity_ids = list(set(manual_entity_ids))

        tracked_event_types = cfg.get(CONF_TRACKED_EVENT_TYPE)
        if tracked_event_types is not None:
            tracked_event_types = list(set(tracked_event_types))

        query = cfg.get(CONF_QUERY)
        column = cfg.get(CONF_COLUMN)

        session = hass.data[recorder.DATA_INSTANCE].get_session()

        entities.append(
            Variable(hass, object_id, initial_value, value_template, session,
                     query, column, unit, restore, force_update, friendly_name,
                     friendly_name_template, icon, icon_template,
                     entity_picture, entity_picture_template,
                     tracked_entity_ids, tracked_event_types))

    if not entities:
        return False

    component.async_register_entity_service(SERVICE_SET, SERVICE_SET_SCHEMA,
                                            'async_set')

    component.async_register_entity_service(SERVICE_UPDATE,
                                            SERVICE_UPDATE_SCHEMA,
                                            'async_force_update')

    await component.async_add_entities(entities)
    return True
Exemplo n.º 44
0
def setup(hass, config):
    """Set up the Wink component."""
    import pywink
    from pubnubsubhandler import PubNubSubscriptionHandler

    if hass.data.get(DOMAIN) is None:
        hass.data[DOMAIN] = {
            'unique_ids': [],
            'entities': {},
            'oauth': {},
            'configuring': {},
            'pubnub': None,
            'configurator': False
        }

    if config.get(DOMAIN) is not None:
        client_id = config[DOMAIN].get(ATTR_CLIENT_ID)
        client_secret = config[DOMAIN].get(ATTR_CLIENT_SECRET)
        email = config[DOMAIN].get(CONF_EMAIL)
        password = config[DOMAIN].get(CONF_PASSWORD)
        local_control = config[DOMAIN].get(CONF_LOCAL_CONTROL)
    else:
        client_id = None
        client_secret = None
        email = None
        password = None
        local_control = None
        hass.data[DOMAIN]['configurator'] = True
    if None not in [client_id, client_secret]:
        _LOGGER.info("Using legacy OAuth authentication")
        if not local_control:
            pywink.disable_local_control()
        hass.data[DOMAIN]["oauth"]["client_id"] = client_id
        hass.data[DOMAIN]["oauth"]["client_secret"] = client_secret
        hass.data[DOMAIN]["oauth"]["email"] = email
        hass.data[DOMAIN]["oauth"]["password"] = password
        pywink.legacy_set_wink_credentials(email, password, client_id,
                                           client_secret)
    else:
        _LOGGER.info("Using OAuth authentication")
        if not local_control:
            pywink.disable_local_control()
        config_path = hass.config.path(WINK_CONFIG_FILE)
        if os.path.isfile(config_path):
            config_file = load_json(config_path)
            if config_file == DEFAULT_CONFIG:
                _request_app_setup(hass, config)
                return True
            # else move on because the user modified the file
        else:
            save_json(config_path, DEFAULT_CONFIG)
            _request_app_setup(hass, config)
            return True

        if DOMAIN in hass.data[DOMAIN]['configuring']:
            _configurator = hass.data[DOMAIN]['configuring']
            hass.components.configurator.request_done(
                _configurator.pop(DOMAIN))

        # Using oauth
        access_token = config_file.get(ATTR_ACCESS_TOKEN)
        refresh_token = config_file.get(ATTR_REFRESH_TOKEN)

        # This will be called after authorizing Home-Assistant
        if None not in (access_token, refresh_token):
            pywink.set_wink_credentials(config_file.get(ATTR_CLIENT_ID),
                                        config_file.get(ATTR_CLIENT_SECRET),
                                        access_token=access_token,
                                        refresh_token=refresh_token)
        # This is called to create the redirect so the user can Authorize
        # Home .
        else:

            redirect_uri = '{}{}'.format(hass.config.api.base_url,
                                         WINK_AUTH_CALLBACK_PATH)

            wink_auth_start_url = pywink.get_authorization_url(
                config_file.get(ATTR_CLIENT_ID), redirect_uri)
            hass.http.register_redirect(WINK_AUTH_START, wink_auth_start_url)
            hass.http.register_view(
                WinkAuthCallbackView(config, config_file,
                                     pywink.request_token))
            _request_oauth_completion(hass, config)
            return True

    pywink.set_user_agent(USER_AGENT)
    hass.data[DOMAIN]['pubnub'] = PubNubSubscriptionHandler(
        pywink.get_subscription_key())

    def _subscribe():
        hass.data[DOMAIN]['pubnub'].subscribe()

    # Call subscribe after the user sets up wink via the configurator
    # All other methods will complete setup before
    # EVENT_HOMEASSISTANT_START is called meaning they
    # will call subscribe via the method below. (start_subscription)
    if hass.data[DOMAIN]['configurator']:
        _subscribe()

    def keep_alive_call(event_time):
        """Call the Wink API endpoints to keep PubNub working."""
        _LOGGER.info("Polling the Wink API to keep PubNub updates flowing")
        pywink.set_user_agent(str(int(time.time())))
        _temp_response = pywink.get_user()
        _LOGGER.debug(str(json.dumps(_temp_response)))
        time.sleep(1)
        pywink.set_user_agent(USER_AGENT)
        _temp_response = pywink.wink_api_fetch()
        _LOGGER.debug(str(json.dumps(_temp_response)))

    # Call the Wink API every hour to keep PubNub updates flowing
    track_time_interval(hass, keep_alive_call, timedelta(minutes=60))

    def start_subscription(event):
        """Start the PubNub subscription."""
        _subscribe()

    hass.bus.listen(EVENT_HOMEASSISTANT_START, start_subscription)

    def stop_subscription(event):
        """Stop the PubNub subscription."""
        hass.data[DOMAIN]['pubnub'].unsubscribe()
        hass.data[DOMAIN]['pubnub'] = None

    hass.bus.listen(EVENT_HOMEASSISTANT_STOP, stop_subscription)

    def save_credentials(event):
        """Save currently set OAuth credentials."""
        if hass.data[DOMAIN]["oauth"].get("email") is None:
            config_path = hass.config.path(WINK_CONFIG_FILE)
            _config = pywink.get_current_oauth_credentials()
            save_json(config_path, _config)

    hass.bus.listen(EVENT_HOMEASSISTANT_STOP, save_credentials)

    # Save the users potentially updated oauth credentials at a regular
    # interval to prevent them from being expired after a HA reboot.
    track_time_interval(hass, save_credentials, timedelta(minutes=60))

    def force_update(call):
        """Force all devices to poll the Wink API."""
        _LOGGER.info("Refreshing Wink states from API")
        for entity_list in hass.data[DOMAIN]['entities'].values():
            # Throttle the calls to Wink API
            for entity in entity_list:
                time.sleep(1)
                entity.schedule_update_ha_state(True)

    hass.services.register(DOMAIN, SERVICE_REFRESH_STATES, force_update)

    def pull_new_devices(call):
        """Pull new devices added to users Wink account since startup."""
        _LOGGER.info("Getting new devices from Wink API")
        for _component in WINK_COMPONENTS:
            discovery.load_platform(hass, _component, DOMAIN, {}, config)

    hass.services.register(DOMAIN, SERVICE_ADD_NEW_DEVICES, pull_new_devices)

    def set_pairing_mode(call):
        """Put the hub in provided pairing mode."""
        hub_name = call.data.get('hub_name')
        pairing_mode = call.data.get('pairing_mode')
        kidde_code = call.data.get('kidde_radio_code')
        for hub in WINK_HUBS:
            if hub.name() == hub_name:
                hub.pair_new_device(pairing_mode, kidde_radio_code=kidde_code)

    def rename_device(call):
        """Set specified device's name."""
        # This should only be called on one device at a time.
        found_device = None
        entity_id = call.data.get('entity_id')[0]
        all_devices = []
        for list_of_devices in hass.data[DOMAIN]['entities'].values():
            all_devices += list_of_devices
        for device in all_devices:
            if device.entity_id == entity_id:
                found_device = device
        if found_device is not None:
            name = call.data.get('name')
            found_device.wink.set_name(name)

    hass.services.register(DOMAIN,
                           SERVICE_RENAME_DEVICE,
                           rename_device,
                           schema=RENAME_DEVICE_SCHEMA)

    def delete_device(call):
        """Delete specified device."""
        # This should only be called on one device at a time.
        found_device = None
        entity_id = call.data.get('entity_id')[0]
        all_devices = []
        for list_of_devices in hass.data[DOMAIN]['entities'].values():
            all_devices += list_of_devices
        for device in all_devices:
            if device.entity_id == entity_id:
                found_device = device
        if found_device is not None:
            found_device.wink.remove_device()

    hass.services.register(DOMAIN,
                           SERVICE_DELETE_DEVICE,
                           delete_device,
                           schema=DELETE_DEVICE_SCHEMA)

    hubs = pywink.get_hubs()
    for hub in hubs:
        if hub.device_manufacturer() == 'wink':
            WINK_HUBS.append(hub)

    if WINK_HUBS:
        hass.services.register(DOMAIN,
                               SERVICE_SET_PAIRING_MODE,
                               set_pairing_mode,
                               schema=SET_PAIRING_MODE_SCHEMA)

    def service_handle(service):
        """Handle services."""
        entity_ids = service.data.get('entity_id')
        all_sirens = []
        for switch in hass.data[DOMAIN]['entities']['switch']:
            if isinstance(switch, WinkSirenDevice):
                all_sirens.append(switch)
        sirens_to_set = []
        if entity_ids is None:
            sirens_to_set = all_sirens
        else:
            for siren in all_sirens:
                if siren.entity_id in entity_ids:
                    sirens_to_set.append(siren)

        for siren in sirens_to_set:
            _man = siren.wink.device_manufacturer()
            if (service.service != SERVICE_SET_AUTO_SHUTOFF
                    and service.service != SERVICE_ENABLE_SIREN
                    and (_man != 'dome' and _man != 'wink')):
                _LOGGER.error("Service only valid for Dome or Wink sirens")
                return

            if service.service == SERVICE_ENABLE_SIREN:
                siren.wink.set_state(service.data.get(ATTR_ENABLED))
            elif service.service == SERVICE_SET_AUTO_SHUTOFF:
                siren.wink.set_auto_shutoff(
                    service.data.get(ATTR_AUTO_SHUTOFF))
            elif service.service == SERVICE_SET_CHIME_VOLUME:
                siren.wink.set_chime_volume(service.data.get(ATTR_VOLUME))
            elif service.service == SERVICE_SET_SIREN_VOLUME:
                siren.wink.set_siren_volume(service.data.get(ATTR_VOLUME))
            elif service.service == SERVICE_SET_SIREN_TONE:
                siren.wink.set_siren_sound(service.data.get(ATTR_TONE))
            elif service.service == SERVICE_ENABLE_CHIME:
                siren.wink.set_chime(service.data.get(ATTR_TONE))
            elif service.service == SERVICE_SIREN_STROBE_ENABLED:
                siren.wink.set_siren_strobe_enabled(
                    service.data.get(ATTR_ENABLED))
            elif service.service == SERVICE_CHIME_STROBE_ENABLED:
                siren.wink.set_chime_strobe_enabled(
                    service.data.get(ATTR_ENABLED))

    # Load components for the devices in Wink that we support
    for wink_component in WINK_COMPONENTS:
        hass.data[DOMAIN]['entities'][wink_component] = []
        discovery.load_platform(hass, wink_component, DOMAIN, {}, config)

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    sirens = []
    has_dome_or_wink_siren = False
    for siren in pywink.get_sirens():
        _man = siren.device_manufacturer()
        if _man == "dome" or _man == "wink":
            has_dome_or_wink_siren = True
        _id = siren.object_id() + siren.name()
        if _id not in hass.data[DOMAIN]['unique_ids']:
            sirens.append(WinkSirenDevice(siren, hass))

    if sirens:

        hass.services.register(DOMAIN,
                               SERVICE_SET_AUTO_SHUTOFF,
                               service_handle,
                               schema=SET_AUTO_SHUTOFF_SCHEMA)

        hass.services.register(DOMAIN,
                               SERVICE_ENABLE_SIREN,
                               service_handle,
                               schema=ENABLED_SIREN_SCHEMA)

    if has_dome_or_wink_siren:

        hass.services.register(DOMAIN,
                               SERVICE_SET_SIREN_TONE,
                               service_handle,
                               schema=SET_SIREN_TONE_SCHEMA)

        hass.services.register(DOMAIN,
                               SERVICE_ENABLE_CHIME,
                               service_handle,
                               schema=SET_CHIME_MODE_SCHEMA)

        hass.services.register(DOMAIN,
                               SERVICE_SET_SIREN_VOLUME,
                               service_handle,
                               schema=SET_VOLUME_SCHEMA)

        hass.services.register(DOMAIN,
                               SERVICE_SET_CHIME_VOLUME,
                               service_handle,
                               schema=SET_VOLUME_SCHEMA)

        hass.services.register(DOMAIN,
                               SERVICE_SIREN_STROBE_ENABLED,
                               service_handle,
                               schema=SET_STROBE_ENABLED_SCHEMA)

        hass.services.register(DOMAIN,
                               SERVICE_CHIME_STROBE_ENABLED,
                               service_handle,
                               schema=SET_STROBE_ENABLED_SCHEMA)

    component.add_entities(sirens)

    return True
Exemplo n.º 45
0
async def async_setup(hass, config):
    """Set up all groups found defined in the configuration."""
    component = hass.data.get(DOMAIN)

    if component is None:
        component = hass.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, hass)

    await _async_process_config(hass, config, component)

    async def reload_service_handler(service):
        """Remove all user-defined groups and load new ones from config."""
        auto = list(filter(lambda e: not e.user_defined, component.entities))

        conf = await component.async_prepare_reload()
        if conf is None:
            return
        await _async_process_config(hass, conf, component)

        await component.async_add_entities(auto)

    hass.services.async_register(DOMAIN,
                                 SERVICE_RELOAD,
                                 reload_service_handler,
                                 schema=RELOAD_SERVICE_SCHEMA)

    async def groups_service_handler(service):
        """Handle dynamic group service functions."""
        object_id = service.data[ATTR_OBJECT_ID]
        entity_id = ENTITY_ID_FORMAT.format(object_id)
        group = component.get_entity(entity_id)

        # new group
        if service.service == SERVICE_SET and group is None:
            entity_ids = service.data.get(ATTR_ENTITIES) or \
                service.data.get(ATTR_ADD_ENTITIES) or None

            extra_arg = {
                attr: service.data[attr]
                for attr in (ATTR_VISIBLE, ATTR_ICON, ATTR_VIEW, ATTR_CONTROL)
                if service.data.get(attr) is not None
            }

            await Group.async_create_group(hass,
                                           service.data.get(
                                               ATTR_NAME, object_id),
                                           object_id=object_id,
                                           entity_ids=entity_ids,
                                           user_defined=False,
                                           **extra_arg)
            return

        if group is None:
            _LOGGER.warning("%s:Group '%s' doesn't exist!", service.service,
                            object_id)
            return

        # update group
        if service.service == SERVICE_SET:
            need_update = False

            if ATTR_ADD_ENTITIES in service.data:
                delta = service.data[ATTR_ADD_ENTITIES]
                entity_ids = set(group.tracking) | set(delta)
                await group.async_update_tracked_entity_ids(entity_ids)

            if ATTR_ENTITIES in service.data:
                entity_ids = service.data[ATTR_ENTITIES]
                await group.async_update_tracked_entity_ids(entity_ids)

            if ATTR_NAME in service.data:
                group.name = service.data[ATTR_NAME]
                need_update = True

            if ATTR_VISIBLE in service.data:
                group.visible = service.data[ATTR_VISIBLE]
                need_update = True

            if ATTR_ICON in service.data:
                group.icon = service.data[ATTR_ICON]
                need_update = True

            if ATTR_CONTROL in service.data:
                group.control = service.data[ATTR_CONTROL]
                need_update = True

            if ATTR_VIEW in service.data:
                group.view = service.data[ATTR_VIEW]
                need_update = True

            if need_update:
                await group.async_update_ha_state()

            return

        # remove group
        if service.service == SERVICE_REMOVE:
            await component.async_remove_entity(entity_id)

    hass.services.async_register(DOMAIN,
                                 SERVICE_SET,
                                 groups_service_handler,
                                 schema=SET_SERVICE_SCHEMA)

    hass.services.async_register(DOMAIN,
                                 SERVICE_REMOVE,
                                 groups_service_handler,
                                 schema=REMOVE_SERVICE_SCHEMA)

    async def visibility_service_handler(service):
        """Change visibility of a group."""
        visible = service.data.get(ATTR_VISIBLE)

        tasks = []
        for group in component.async_extract_from_service(service,
                                                          expand_group=False):
            group.visible = visible
            tasks.append(group.async_update_ha_state())

        if tasks:
            await asyncio.wait(tasks, loop=hass.loop)

    hass.services.async_register(DOMAIN,
                                 SERVICE_SET_VISIBILITY,
                                 visibility_service_handler,
                                 schema=SET_VISIBILITY_SERVICE_SCHEMA)

    return True
Exemplo n.º 46
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up an Utility Meter."""
    hass.data[DATA_LEGACY_COMPONENT] = EntityComponent(_LOGGER, DOMAIN, hass)

    hass.data[DATA_UTILITY] = {}

    async def async_reset_meters(service_call):
        """Reset all sensors of a meter."""
        meters = service_call.data["entity_id"]

        for meter in meters:
            _LOGGER.debug("resetting meter %s", meter)
            domain, entity = split_entity_id(meter)
            # backward compatibility up to 2022.07:
            if domain == DOMAIN:
                async_dispatcher_send(hass, SIGNAL_RESET_METER,
                                      f"{SELECT_DOMAIN}.{entity}")
            else:
                async_dispatcher_send(hass, SIGNAL_RESET_METER, meter)

    hass.services.async_register(
        DOMAIN,
        SERVICE_RESET,
        async_reset_meters,
        vol.Schema({ATTR_ENTITY_ID: vol.All(cv.ensure_list, [cv.entity_id])}),
    )

    if DOMAIN not in config:
        return True

    for meter, conf in config[DOMAIN].items():
        _LOGGER.debug("Setup %s.%s", DOMAIN, meter)

        hass.data[DATA_UTILITY][meter] = conf
        hass.data[DATA_UTILITY][meter][DATA_TARIFF_SENSORS] = []

        if not conf[CONF_TARIFFS]:
            # only one entity is required
            name = conf.get(CONF_NAME, meter)
            hass.async_create_task(
                discovery.async_load_platform(
                    hass,
                    SENSOR_DOMAIN,
                    DOMAIN,
                    {name: {
                        CONF_METER: meter,
                        CONF_NAME: name
                    }},
                    config,
                ))
        else:
            # create tariff selection
            hass.async_create_task(
                discovery.async_load_platform(
                    hass,
                    SELECT_DOMAIN,
                    DOMAIN,
                    {
                        CONF_METER: meter,
                        CONF_TARIFFS: conf[CONF_TARIFFS]
                    },
                    config,
                ))

            hass.data[DATA_UTILITY][meter][
                CONF_TARIFF_ENTITY] = "{}.{}".format(SELECT_DOMAIN, meter)

            # add one meter for each tariff
            tariff_confs = {}
            for tariff in conf[CONF_TARIFFS]:
                name = f"{meter} {tariff}"
                tariff_confs[name] = {
                    CONF_METER: meter,
                    CONF_NAME: name,
                    CONF_TARIFF: tariff,
                }

            hass.async_create_task(
                discovery.async_load_platform(hass, SENSOR_DOMAIN, DOMAIN,
                                              tariff_confs, config))

    return True
Exemplo n.º 47
0
def setup(hass, config):
    """Setup zigate platform."""
    port = config[DOMAIN].get(CONF_PORT)
    host = config[DOMAIN].get(CONF_HOST)
    gpio = config[DOMAIN].get('gpio', False)
    enable_led = config[DOMAIN].get('enable_led', True)
    polling = config[DOMAIN].get('polling', True)
    channel = config[DOMAIN].get('channel')
    scan_interval = datetime.timedelta(
        seconds=config[DOMAIN].get(CONF_SCAN_INTERVAL, SCAN_INTERVAL))
    admin_panel = config[DOMAIN].get('admin_panel', True)

    persistent_file = os.path.join(hass.config.config_dir, 'zigate.json')

    _LOGGER.debug('Port : %s', port)
    _LOGGER.debug('Host : %s', host)
    _LOGGER.debug('GPIO : %s', gpio)
    _LOGGER.debug('Led : %s', enable_led)
    _LOGGER.debug('Channel : %s', channel)
    _LOGGER.debug('Scan interval : %s', scan_interval)

    myzigate = zigate.connect(port=port,
                              host=host,
                              path=persistent_file,
                              auto_start=False,
                              gpio=gpio)
    _LOGGER.debug('ZiGate object created %s', myzigate)

    hass.data[DOMAIN] = myzigate
    hass.data[DATA_ZIGATE_DEVICES] = {}
    hass.data[DATA_ZIGATE_ATTRS] = {}

    component = EntityComponent(_LOGGER, DOMAIN, hass, scan_interval)
    #     component.setup(config)
    entity = ZiGateComponentEntity(myzigate)
    hass.data[DATA_ZIGATE_DEVICES]['zigate'] = entity
    component.add_entities([entity])

    def device_added(**kwargs):
        device = kwargs['device']
        _LOGGER.debug('Add device {}'.format(device))
        ieee = device.ieee
        if ieee not in hass.data[DATA_ZIGATE_DEVICES]:
            hass.data[DATA_ZIGATE_DEVICES][ieee] = None  # reserve
            entity = ZiGateDeviceEntity(hass, device, polling)
            hass.data[DATA_ZIGATE_DEVICES][ieee] = entity
            component.add_entities([entity])
            if 'signal' in kwargs:
                hass.components.persistent_notification.create(
                    ('A new ZiGate device "{}"'
                     ' has been added !').format(device),
                    title='ZiGate')

    def device_removed(**kwargs):
        # component.async_remove_entity
        device = kwargs['device']
        ieee = device.ieee
        hass.components.persistent_notification.create(
            'The ZiGate device {}({}) is gone.'.format(device.ieee,
                                                       device.addr),
            title='ZiGate')
        entity = hass.data[DATA_ZIGATE_DEVICES][ieee]
        component.async_remove_entity(entity.entity_id)
        del hass.data[DATA_ZIGATE_DEVICES][ieee]

    def device_need_discovery(**kwargs):
        device = kwargs['device']
        hass.components.persistent_notification.create(
            ('The ZiGate device {}({}) needs to be discovered'
             ' (missing important'
             ' information)').format(device.ieee, device.addr),
            title='ZiGate')

    zigate.dispatcher.connect(device_added,
                              zigate.ZIGATE_DEVICE_ADDED,
                              weak=False)
    zigate.dispatcher.connect(device_removed,
                              zigate.ZIGATE_DEVICE_REMOVED,
                              weak=False)
    zigate.dispatcher.connect(device_need_discovery,
                              zigate.ZIGATE_DEVICE_NEED_DISCOVERY,
                              weak=False)

    def attribute_updated(**kwargs):
        device = kwargs['device']
        ieee = device.ieee
        attribute = kwargs['attribute']
        _LOGGER.debug('Update attribute for device {} {}'.format(
            device, attribute))
        entity = hass.data[DATA_ZIGATE_DEVICES].get(ieee)
        event_data = attribute.copy()
        if type(event_data.get('type')) == type:
            event_data['type'] = event_data['type'].__name__
        event_data['ieee'] = device.ieee
        event_data['addr'] = device.addr
        event_data['device_type'] = device.get_property_value('type')
        if entity:
            event_data['entity_id'] = entity.entity_id
        hass.bus.fire('zigate.attribute_updated', event_data)

    zigate.dispatcher.connect(attribute_updated,
                              zigate.ZIGATE_ATTRIBUTE_UPDATED,
                              weak=False)

    def device_updated(**kwargs):
        device = kwargs['device']
        _LOGGER.debug('Update device {}'.format(device))
        ieee = device.ieee
        entity = hass.data[DATA_ZIGATE_DEVICES].get(ieee)
        if not entity:
            _LOGGER.debug('Device not found {}, adding it'.format(device))
            device_added(device=device)
        event_data = {}
        event_data['ieee'] = device.ieee
        event_data['addr'] = device.addr
        event_data['device_type'] = device.get_property_value('type')
        if entity:
            event_data['entity_id'] = entity.entity_id
        hass.bus.fire('zigate.device_updated', event_data)

    zigate.dispatcher.connect(device_updated,
                              zigate.ZIGATE_DEVICE_UPDATED,
                              weak=False)
    zigate.dispatcher.connect(device_updated,
                              zigate.ZIGATE_ATTRIBUTE_ADDED,
                              weak=False)
    zigate.dispatcher.connect(device_updated,
                              zigate.ZIGATE_DEVICE_ADDRESS_CHANGED,
                              weak=False)

    def zigate_reset(service):
        myzigate.reset()

    def permit_join(service):
        myzigate.permit_join()

    def zigate_cleanup(service):
        '''
        Remove missing device
        '''
        myzigate.cleanup_devices()

    def start_zigate(service_event=None):
        myzigate.autoStart(channel)
        myzigate.start_auto_save()
        myzigate.set_led(enable_led)
        version = myzigate.get_version_text()
        if version < '3.1a':
            hass.components.persistent_notification.create(
                ('Your zigate firmware is outdated, '
                 'Please upgrade to 3.1a or later !'),
                title='ZiGate')
        # first load
        for device in myzigate.devices:
            device_added(device=device)

        for platform in SUPPORTED_PLATFORMS:
            load_platform(hass, platform, DOMAIN, {}, config)

        hass.bus.fire('zigate.started')

    def stop_zigate(service=None):
        myzigate.save_state()
        myzigate.close()

        hass.bus.fire('zigate.stopped')

    def refresh_devices_list(service):
        myzigate.get_devices_list()

    def generate_templates(service):
        myzigate.generate_templates(hass.config.config_dir)

    def _get_addr_from_service_request(service):
        entity_id = service.data.get(ATTR_ENTITY_ID)
        ieee = service.data.get(IEEE)
        addr = service.data.get(ADDR)
        if entity_id:
            entity = component.get_entity(entity_id)
            if entity:
                addr = entity._device.addr
        elif ieee:
            device = myzigate.get_device_from_ieee(ieee)
            if device:
                addr = device.addr
        return addr

    def _to_int(value):
        '''
        convert str to int
        '''
        if 'x' in value:
            return int(value, 16)
        return int(value)

    def refresh_device(service):
        full = service.data.get('full', False)
        addr = _get_addr_from_service_request(service)
        if addr:
            myzigate.refresh_device(addr, full=full)
        else:
            for device in myzigate.devices:
                device.refresh_device(full=full)

    def discover_device(service):
        addr = _get_addr_from_service_request(service)
        if addr:
            myzigate.discover_device(addr, True)

    def network_scan(service):
        myzigate.start_network_scan()

    def raw_command(service):
        cmd = _to_int(service.data.get('cmd'))
        data = service.data.get('data', '')
        myzigate.send_data(cmd, data)

    def identify_device(service):
        addr = _get_addr_from_service_request(service)
        myzigate.identify_device(addr)

    def remove_device(service):
        addr = _get_addr_from_service_request(service)
        myzigate.remove_device(addr)

    def initiate_touchlink(service):
        myzigate.initiate_touchlink()

    def touchlink_factory_reset(service):
        myzigate.touchlink_factory_reset()

    def read_attribute(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint'))
        cluster = _to_int(service.data.get('cluster'))
        attribute_id = _to_int(service.data.get('attribute_id'))
        manufacturer_code = _to_int(service.data.get('manufacturer_code', '0'))
        myzigate.read_attribute_request(addr,
                                        endpoint,
                                        cluster,
                                        attribute_id,
                                        manufacturer_code=manufacturer_code)

    def write_attribute(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint'))
        cluster = _to_int(service.data.get('cluster'))
        attribute_id = _to_int(service.data.get('attribute_id'))
        attribute_type = _to_int(service.data.get('attribute_type'))
        value = _to_int(service.data.get('value'))
        attributes = [(attribute_id, attribute_type, value)]
        manufacturer_code = _to_int(service.data.get('manufacturer_code', '0'))
        myzigate.write_attribute_request(addr,
                                         endpoint,
                                         cluster,
                                         attributes,
                                         manufacturer_code=manufacturer_code)

    def add_group(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint'))
        groupaddr = service.data.get('group_addr')
        myzigate.add_group(addr, endpoint, groupaddr)

    def remove_group(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint'))
        groupaddr = service.data.get('group_addr')
        myzigate.remove_group(addr, endpoint, groupaddr)

    def get_group_membership(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint'))
        myzigate.get_group_membership(addr, endpoint)

    def action_onoff(service):
        addr = _get_addr_from_service_request(service)
        onoff = _to_int(service.data.get('onoff'))
        endpoint = _to_int(service.data.get('endpoint', '0'))
        ontime = _to_int(service.data.get('on_time', '0'))
        offtime = _to_int(service.data.get('off_time', '0'))
        effect = _to_int(service.data.get('effect', '0'))
        gradient = _to_int(service.data.get('gradient', '0'))
        myzigate.action_onoff(addr, endpoint, onoff, ontime, offtime, effect,
                              gradient)

    def build_network_table(service):
        table = myzigate.build_neighbours_table(
            service.data.get('force', False))
        _LOGGER.debug('Neighbours table {}'.format(table))

    def ota_load_image(service):
        ota_image_path = service.data.get('imagepath')
        myzigate.ota_load_image(ota_image_path)

    def ota_image_notify(service):
        addr = _get_addr_from_service_request(service)
        destination_endpoint = _to_int(
            service.data.get('destination_endpoint', '1'))
        payload_type = _to_int(service.data.get('payload_type', '0'))
        myzigate.ota_image_notify(addr, destination_endpoint, payload_type)

    def get_ota_status(service):
        myzigate.get_ota_status()

    def view_scene(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint', '1'))
        groupaddr = service.data.get('group_addr')
        scene = _to_int(service.data.get('scene'))
        myzigate.view_scene(addr, endpoint, groupaddr, scene)

    def add_scene(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint', '1'))
        groupaddr = service.data.get('group_addr')
        scene = _to_int(service.data.get('scene'))
        name = service.data.get('scene_name')
        transition = _to_int(service.data.get('transition', '0'))
        myzigate.add_scene(addr, endpoint, groupaddr, scene, name, transition)

    def remove_scene(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint', '1'))
        groupaddr = service.data.get('group_addr')
        scene = _to_int(service.data.get('scene', -1))
        if scene == -1:
            scene = None
        myzigate.remove_scene(addr, endpoint, groupaddr, scene)

    def store_scene(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint', '1'))
        groupaddr = service.data.get('group_addr')
        scene = _to_int(service.data.get('scene'))
        myzigate.store_scene(addr, endpoint, groupaddr, scene)

    def recall_scene(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint', '1'))
        groupaddr = service.data.get('group_addr')
        scene = _to_int(service.data.get('scene'))
        myzigate.recall_scene(addr, endpoint, groupaddr, scene)

    def scene_membership_request(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint', '1'))
        groupaddr = service.data.get('group_addr')
        myzigate.scene_membership_request(addr, endpoint, groupaddr)

    def copy_scene(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint', '1'))
        fromgroupaddr = service.data.get('from_group_addr')
        fromscene = _to_int(service.data.get('from_scene'))
        togroupaddr = service.data.get('to_group_addr')
        toscene = _to_int(service.data.get('to_scene'))
        myzigate.copy_scene(addr, endpoint, fromgroupaddr, fromscene,
                            togroupaddr, toscene)

    def ias_warning(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint', '1'))
        mode = service.data.get('mode', 'burglar')
        strobe = service.data.get('strobe', True)
        level = service.data.get('level', 'low')
        duration = service.data.get('duration', 60)
        strobe_cycle = service.data.get('strobe_cycle', 10)
        strobe_level = service.data.get('strobe_level', 'low')
        myzigate.action_ias_warning(addr, endpoint, mode, strobe, level,
                                    duration, strobe_cycle, strobe_level)

    def ias_squawk(service):
        addr = _get_addr_from_service_request(service)
        endpoint = _to_int(service.data.get('endpoint', '1'))
        mode = service.data.get('mode', 'armed')
        strobe = service.data.get('strobe', True)
        level = service.data.get('level', 'low')
        myzigate.action_ias_squawk(addr, endpoint, mode, strobe, level)

    def upgrade_firmware(service):
        from zigate.flasher import flash
        from zigate.firmware import download_latest
        port = myzigate._port
        pizigate = False
        if isinstance(myzigate, zigate.ZiGateGPIO):
            pizigate = True
        if myzigate._started and not pizigate:
            msg = 'You should stop zigate first using service zigate.stop_zigate and put zigate in download mode.'
            hass.components.persistent_notification.create(msg, title='ZiGate')
            return
        if pizigate:
            stop_zigate()
            myzigate.set_bootloader_mode()
        backup_filename = 'zigate_backup_{:%Y%m%d%H%M%S}.bin'.format(
            datetime.datetime.now())
        backup_filename = os.path.join(hass.config.config_dir, backup_filename)
        flash(port, save=backup_filename)
        msg = 'ZiGate backup created {}'.format(backup_filename)
        hass.components.persistent_notification.create(msg, title='ZiGate')
        firmware_path = service.data.get('path')
        if not firmware_path:
            firmware_path = download_latest()
        flash(port, write=firmware_path)
        msg = 'ZiGate flashed with {}'.format(firmware_path)
        hass.components.persistent_notification.create(msg, title='ZiGate')
        myzigate._version = None
        if pizigate:
            myzigate.set_running_mode()
            start_zigate()
        else:
            msg = 'Now you have to unplug/replug the ZiGate USB key and then call service zigate.start_zigate'
            hass.components.persistent_notification.create(msg, title='ZiGate')

    hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zigate)
    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zigate)

    hass.services.register(DOMAIN, 'refresh_devices_list',
                           refresh_devices_list)
    hass.services.register(DOMAIN, 'generate_templates', generate_templates)
    hass.services.register(DOMAIN, 'reset', zigate_reset)
    hass.services.register(DOMAIN, 'permit_join', permit_join)
    hass.services.register(DOMAIN, 'start_zigate', start_zigate)
    hass.services.register(DOMAIN, 'stop_zigate', stop_zigate)
    hass.services.register(DOMAIN, 'cleanup_devices', zigate_cleanup)
    hass.services.register(DOMAIN,
                           'refresh_device',
                           refresh_device,
                           schema=REFRESH_DEVICE_SCHEMA)
    hass.services.register(DOMAIN,
                           'discover_device',
                           discover_device,
                           schema=DISCOVER_DEVICE_SCHEMA)
    hass.services.register(DOMAIN, 'network_scan', network_scan)
    hass.services.register(DOMAIN,
                           'raw_command',
                           raw_command,
                           schema=RAW_COMMAND_SCHEMA)
    hass.services.register(DOMAIN,
                           'identify_device',
                           identify_device,
                           schema=IDENTIFY_SCHEMA)
    hass.services.register(DOMAIN,
                           'remove_device',
                           remove_device,
                           schema=REMOVE_SCHEMA)
    hass.services.register(DOMAIN, 'initiate_touchlink', initiate_touchlink)
    hass.services.register(DOMAIN, 'touchlink_factory_reset',
                           touchlink_factory_reset)
    hass.services.register(DOMAIN,
                           'read_attribute',
                           read_attribute,
                           schema=READ_ATTRIBUTE_SCHEMA)
    hass.services.register(DOMAIN,
                           'write_attribute',
                           write_attribute,
                           schema=WRITE_ATTRIBUTE_SCHEMA)
    hass.services.register(DOMAIN,
                           'add_group',
                           add_group,
                           schema=ADD_GROUP_SCHEMA)
    hass.services.register(DOMAIN,
                           'get_group_membership',
                           get_group_membership,
                           schema=GET_GROUP_MEMBERSHIP_SCHEMA)
    hass.services.register(DOMAIN,
                           'remove_group',
                           remove_group,
                           schema=REMOVE_GROUP_SCHEMA)
    hass.services.register(DOMAIN,
                           'action_onoff',
                           action_onoff,
                           schema=ACTION_ONOFF_SCHEMA)
    hass.services.register(DOMAIN,
                           'build_network_table',
                           build_network_table,
                           schema=BUILD_NETWORK_TABLE_SCHEMA)
    hass.services.register(DOMAIN,
                           'ias_warning',
                           ias_warning,
                           schema=ACTION_IAS_WARNING_SCHEMA)
    hass.services.register(DOMAIN,
                           'ias_squawk',
                           ias_squawk,
                           schema=ACTION_IAS_SQUAWK_SCHEMA)

    hass.services.register(DOMAIN,
                           'ota_load_image',
                           ota_load_image,
                           schema=OTA_LOAD_IMAGE_SCHEMA)
    hass.services.register(DOMAIN,
                           'ota_image_notify',
                           ota_image_notify,
                           schema=OTA_IMAGE_NOTIFY_SCHEMA)
    hass.services.register(DOMAIN, 'ota_get_status', get_ota_status)
    hass.services.register(DOMAIN,
                           'view_scene',
                           view_scene,
                           schema=VIEW_SCENE_SCHEMA)
    hass.services.register(DOMAIN,
                           'add_scene',
                           add_scene,
                           schema=ADD_SCENE_SCHEMA)
    hass.services.register(DOMAIN,
                           'remove_scene',
                           remove_scene,
                           schema=REMOVE_SCENE_SCHEMA)
    hass.services.register(DOMAIN,
                           'store_scene',
                           store_scene,
                           schema=STORE_SCENE_SCHEMA)
    hass.services.register(DOMAIN,
                           'recall_scene',
                           recall_scene,
                           schema=RECALL_SCENE_SCHEMA)
    hass.services.register(DOMAIN,
                           'scene_membership_request',
                           scene_membership_request,
                           schema=SCENE_MEMBERSHIP_REQUEST_SCHEMA)
    hass.services.register(DOMAIN,
                           'copy_scene',
                           copy_scene,
                           schema=COPY_SCENE_SCHEMA)
    hass.services.register(DOMAIN, 'upgrade_firmware', upgrade_firmware)
    track_time_change(hass, refresh_devices_list, hour=0, minute=0, second=0)

    if admin_panel:
        _LOGGER.debug('Start ZiGate Admin Panel on port 9998')
        myzigate.start_adminpanel()
        # myzigate.start_adminpanel(mount='/zigateproxy')
        # adminpanel_setup(hass, 'zigateproxy')

#     hass.async_create_task(
#         hass.config_entries.flow.async_init(
#             DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={}
#         )
#     )

    return True
Exemplo n.º 48
0
def async_setup(hass, config):
    """Track states and offer events for remotes."""
    component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL,
                                GROUP_NAME_ALL_REMOTES)
    yield from component.async_setup(config)

    @asyncio.coroutine
    def async_handle_remote_service(service):
        """Handle calls to the remote services."""
        target_remotes = component.async_extract_from_service(service)

        activity_id = service.data.get(ATTR_ACTIVITY)
        device = service.data.get(ATTR_DEVICE)
        command = service.data.get(ATTR_COMMAND)
        num_repeats = service.data.get(ATTR_NUM_REPEATS)
        delay_secs = service.data.get(ATTR_DELAY_SECS)

        update_tasks = []
        for remote in target_remotes:
            if service.service == SERVICE_TURN_ON:
                yield from remote.async_turn_on(activity=activity_id)
            elif service.service == SERVICE_TOGGLE:
                yield from remote.async_toggle(activity=activity_id)
            elif service.service == SERVICE_SEND_COMMAND:
                yield from remote.async_send_command(device=device,
                                                     command=command,
                                                     num_repeats=num_repeats,
                                                     delay_secs=delay_secs)
            else:
                yield from remote.async_turn_off(activity=activity_id)

            if not remote.should_poll:
                continue
            update_tasks.append(remote.async_update_ha_state(True))

        if update_tasks:
            yield from asyncio.wait(update_tasks, loop=hass.loop)

    descriptions = yield from hass.async_add_job(
        load_yaml_config_file,
        os.path.join(os.path.dirname(__file__), 'services.yaml'))
    hass.services.async_register(DOMAIN,
                                 SERVICE_TURN_OFF,
                                 async_handle_remote_service,
                                 descriptions.get(SERVICE_TURN_OFF),
                                 schema=REMOTE_SERVICE_ACTIVITY_SCHEMA)
    hass.services.async_register(DOMAIN,
                                 SERVICE_TURN_ON,
                                 async_handle_remote_service,
                                 descriptions.get(SERVICE_TURN_ON),
                                 schema=REMOTE_SERVICE_ACTIVITY_SCHEMA)
    hass.services.async_register(DOMAIN,
                                 SERVICE_TOGGLE,
                                 async_handle_remote_service,
                                 descriptions.get(SERVICE_TOGGLE),
                                 schema=REMOTE_SERVICE_ACTIVITY_SCHEMA)
    hass.services.async_register(DOMAIN,
                                 SERVICE_SEND_COMMAND,
                                 async_handle_remote_service,
                                 descriptions.get(SERVICE_SEND_COMMAND),
                                 schema=REMOTE_SERVICE_SEND_COMMAND_SCHEMA)

    return True
Exemplo n.º 49
0
def setup(hass, config):
    """Setup zigate platform."""
    from homeassistant.components import persistent_notification
    import zigate

    port = config.get(CONF_PORT)
    host = config.get(CONF_HOST)
    persistent_file = os.path.join(hass.config.config_dir, 'zigate.json')
    _LOGGER.debug('Persistent file {}'.format(persistent_file))

    if host:
        if not port:
            port = 9999
        z = zigate.ZiGateWiFi(host,
                              port,
                              path=persistent_file,
                              auto_start=False)
    else:
        z = zigate.ZiGate(port, path=persistent_file, auto_start=False)

    hass.data[DOMAIN] = z
    hass.data[DATA_ZIGATE_DEVICES] = {}
    hass.data[DATA_ZIGATE_ATTRS] = {}

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    def device_added(**kwargs):
        device = kwargs['device']
        _LOGGER.debug('Add device {}'.format(device))
        if device.addr not in hass.data[DATA_ZIGATE_DEVICES]:
            entity = ZiGateDeviceEntity(device)
            hass.data[DATA_ZIGATE_DEVICES][device.addr] = entity
            component.add_entities([entity])
            if 'signal' in kwargs:
                persistent_notification.create(
                    hass, ('A new ZiGate device "{}"'
                           ' has been added !').format(device),
                    title='ZiGate')

    def device_removed(**kwargs):
        # component.async_remove_entity
        pass

    def device_need_refresh(**kwargs):
        device = kwargs['device']
        persistent_notification.create(hass,
                                       ('The ZiGate device {} needs some'
                                        ' refresh (missing important'
                                        ' information)').format(device.addr),
                                       title='ZiGate')

    zigate.dispatcher.connect(device_added,
                              zigate.ZIGATE_DEVICE_ADDED,
                              weak=False)
    zigate.dispatcher.connect(device_removed,
                              zigate.ZIGATE_DEVICE_REMOVED,
                              weak=False)
    zigate.dispatcher.connect(device_need_refresh,
                              zigate.ZIGATE_DEVICE_NEED_REFRESH,
                              weak=False)

    def attribute_updated(**kwargs):
        device = kwargs['device']
        attribute = kwargs['attribute']
        _LOGGER.debug('Update attribute for device {} {}'.format(
            device, attribute))
        key = '{}-{}-{}-{}'.format(
            device.addr,
            attribute['endpoint'],
            attribute['cluster'],
            attribute['attribute'],
        )
        entity = hass.data[DATA_ZIGATE_ATTRS].get(key)
        if entity:
            if entity.hass:
                entity.schedule_update_ha_state()
        key = '{}-{}-{}'.format(
            device.addr,
            'switch',
            attribute['endpoint'],
        )
        entity = hass.data[DATA_ZIGATE_ATTRS].get(key)
        if entity:
            if entity.hass:
                entity.schedule_update_ha_state()
        key = '{}-{}-{}'.format(
            device.addr,
            'light',
            attribute['endpoint'],
        )
        entity = hass.data[DATA_ZIGATE_ATTRS].get(key)
        if entity:
            if entity.hass:
                entity.schedule_update_ha_state()
        entity = hass.data[DATA_ZIGATE_DEVICES].get(device.addr)
        if entity:
            if entity.hass:
                entity.schedule_update_ha_state()

    zigate.dispatcher.connect(attribute_updated,
                              zigate.ZIGATE_ATTRIBUTE_UPDATED,
                              weak=False)

    def device_updated(**kwargs):
        device = kwargs['device']
        _LOGGER.debug('Update device {}'.format(device))
        entity = hass.data[DATA_ZIGATE_DEVICES].get(device.addr)
        if entity:
            if entity.hass:
                entity.schedule_update_ha_state()
        else:
            _LOGGER.debug('Device not found {}, adding it'.format(device))
            device_added(device=device)

        zigate.dispatcher.connect(device_updated,
                                  zigate.ZIGATE_DEVICE_UPDATED,
                                  weak=False)
        zigate.dispatcher.connect(device_updated,
                                  zigate.ZIGATE_ATTRIBUTE_ADDED,
                                  weak=False)

    def zigate_reset(service):
        z.reset()

    def permit_join(service):
        z.permit_join()

    def zigate_cleanup(service):
        '''
        Remove missing device
        '''
        z.cleanup_devices()

    def start_zigate(service_event):
        z.autoStart()
        z.start_auto_save()
        # firt load
        for device in z.devices:
            device_added(device=device)

        load_platform(hass, 'sensor', DOMAIN, {}, config)
        load_platform(hass, 'binary_sensor', DOMAIN, {}, config)
        load_platform(hass, 'switch', DOMAIN, {}, config)
        load_platform(hass, 'light', DOMAIN, {}, config)

    def stop_zigate(service_event):
        z.save_state()
        z.close()

    def refresh_devices_list(service):
        z.get_devices_list()

    def refresh_device(service):
        addr = service.data.get(ADDR)
        if addr:
            z.refresh_device(addr)
        else:
            for device in z.devices:
                device.refresh_device()

    def network_scan(service):
        z.start_network_scan()

    def raw_command(service):
        cmd = int(service.data.get('cmd'))
        data = service.data.get('data', '')
        z.send_data(cmd, data)

    def identify_device(service):
        addr = service.data.get('addr')
        z.identify_device(addr)

    def initiate_touchlink(service):
        z.initiate_touchlink()

    def touchlink_factory_reset(service):
        z.touchlink_factory_reset()

    hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zigate)
    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zigate)

    hass.services.register(DOMAIN, 'refresh_devices_list',
                           refresh_devices_list)
    hass.services.register(DOMAIN, 'reset', zigate_reset)
    hass.services.register(DOMAIN, 'permit_join', permit_join)
    hass.services.register(DOMAIN, 'start_zigate', start_zigate)
    hass.services.register(DOMAIN, 'stop_zigate', stop_zigate)
    hass.services.register(DOMAIN, 'cleanup_devices', zigate_cleanup)
    hass.services.register(DOMAIN,
                           'refresh_device',
                           refresh_device,
                           schema=REFRESH_DEVICE_SCHEMA)
    hass.services.register(DOMAIN, 'network_scan', network_scan)
    hass.services.register(DOMAIN,
                           'raw_command',
                           raw_command,
                           schema=RAW_COMMAND_SCHEMA)
    hass.services.register(DOMAIN,
                           'identify_device',
                           identify_device,
                           schema=IDENTIFY_SCHEMA)
    hass.services.register(DOMAIN, 'initiate_touchlink', initiate_touchlink)
    hass.services.register(DOMAIN, 'touchlink_factory_reset',
                           touchlink_factory_reset)

    track_time_change(hass, refresh_devices_list, hour=0, minute=0, second=0)

    return True
Exemplo n.º 50
0
async def async_setup(hass, config):
    """Set up all groups found defined in the configuration."""
    if (component := hass.data.get(DOMAIN)) is None:
        component = hass.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, hass)
Exemplo n.º 51
0
async def async_setup(hass, config):
    """Set up all groups found defined in the configuration."""
    component = hass.data.get(DOMAIN)

    if component is None:
        component = hass.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, hass)

    hass.data[REG_KEY] = GroupIntegrationRegistry()

    await async_process_integration_platforms(hass, DOMAIN, _process_group_platform)

    await _async_process_config(hass, config, component)

    async def reload_service_handler(service):
        """Remove all user-defined groups and load new ones from config."""
        # auto = list(filter(lambda e: not e.user_defined, component.entities))
        # fix for ais-dom groups defined in packages
        auto = list(component.entities)

        conf = await component.async_prepare_reload()
        if conf is None:
            return
        await _async_process_config(hass, conf, component)

        await component.async_add_entities(auto)

        await async_reload_integration_platforms(hass, DOMAIN, PLATFORMS)

    hass.services.async_register(
        DOMAIN, SERVICE_RELOAD, reload_service_handler, schema=vol.Schema({})
    )

    service_lock = asyncio.Lock()

    async def locked_service_handler(service):
        """Handle a service with an async lock."""
        async with service_lock:
            await groups_service_handler(service)

    async def groups_service_handler(service):
        """Handle dynamic group service functions."""
        object_id = service.data[ATTR_OBJECT_ID]
        entity_id = f"{DOMAIN}.{object_id}"
        group = component.get_entity(entity_id)

        # new group
        if service.service == SERVICE_SET and group is None:
            entity_ids = (
                service.data.get(ATTR_ENTITIES)
                or service.data.get(ATTR_ADD_ENTITIES)
                or None
            )

            extra_arg = {
                attr: service.data[attr]
                for attr in (ATTR_ICON,)
                if service.data.get(attr) is not None
            }

            await Group.async_create_group(
                hass,
                service.data.get(ATTR_NAME, object_id),
                object_id=object_id,
                entity_ids=entity_ids,
                user_defined=False,
                mode=service.data.get(ATTR_ALL),
                **extra_arg,
            )
            return

        if group is None:
            _LOGGER.warning("%s:Group '%s' doesn't exist!", service.service, object_id)
            return

        # update group
        if service.service == SERVICE_SET:
            need_update = False

            if ATTR_ADD_ENTITIES in service.data:
                delta = service.data[ATTR_ADD_ENTITIES]
                entity_ids = set(group.tracking) | set(delta)
                await group.async_update_tracked_entity_ids(entity_ids)

            if ATTR_ENTITIES in service.data:
                entity_ids = service.data[ATTR_ENTITIES]
                await group.async_update_tracked_entity_ids(entity_ids)

            if ATTR_NAME in service.data:
                group.name = service.data[ATTR_NAME]
                need_update = True

            if ATTR_ICON in service.data:
                group.icon = service.data[ATTR_ICON]
                need_update = True

            if ATTR_ALL in service.data:
                group.mode = all if service.data[ATTR_ALL] else any
                need_update = True

            if need_update:
                group.async_write_ha_state()

            return

        # remove group
        if service.service == SERVICE_REMOVE:
            await component.async_remove_entity(entity_id)

    hass.services.async_register(
        DOMAIN,
        SERVICE_SET,
        locked_service_handler,
        schema=vol.All(
            vol.Schema(
                {
                    vol.Required(ATTR_OBJECT_ID): cv.slug,
                    vol.Optional(ATTR_NAME): cv.string,
                    vol.Optional(ATTR_ICON): cv.string,
                    vol.Optional(ATTR_ALL): cv.boolean,
                    vol.Exclusive(ATTR_ENTITIES, "entities"): cv.entity_ids,
                    vol.Exclusive(ATTR_ADD_ENTITIES, "entities"): cv.entity_ids,
                }
            )
        ),
    )

    hass.services.async_register(
        DOMAIN,
        SERVICE_REMOVE,
        groups_service_handler,
        schema=vol.Schema({vol.Required(ATTR_OBJECT_ID): cv.slug}),
    )

    return True
Exemplo n.º 52
0
def async_setup(hass, config):
    """Expose light control via statemachine and services."""
    component = EntityComponent(
        _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_LIGHTS)
    yield from component.async_setup(config)

    # load profiles from files
    profiles_valid = yield from Profiles.load_profiles(hass)
    if not profiles_valid:
        return False

    @asyncio.coroutine
    def async_handle_light_service(service):
        """Hande a turn light on or off service call."""
        # Get the validated data
        params = service.data.copy()

        # Convert the entity ids to valid light ids
        target_lights = component.async_extract_from_service(service)
        params.pop(ATTR_ENTITY_ID, None)

        preprocess_turn_on_alternatives(params)

        for light in target_lights:
            if service.service == SERVICE_TURN_ON:
                yield from light.async_turn_on(**params)
            elif service.service == SERVICE_TURN_OFF:
                yield from light.async_turn_off(**params)
            else:
                yield from light.async_toggle(**params)

        update_tasks = []

        for light in target_lights:
            if not light.should_poll:
                continue

            update_coro = hass.async_add_job(
                light.async_update_ha_state(True))
            if hasattr(light, 'async_update'):
                update_tasks.append(update_coro)
            else:
                yield from update_coro

        if update_tasks:
            yield from asyncio.wait(update_tasks, loop=hass.loop)

    # Listen for light on and light off service calls.
    descriptions = yield from hass.async_add_job(
        load_yaml_config_file, os.path.join(
            os.path.dirname(__file__), 'services.yaml'))

    hass.services.async_register(
        DOMAIN, SERVICE_TURN_ON, async_handle_light_service,
        descriptions.get(SERVICE_TURN_ON), schema=LIGHT_TURN_ON_SCHEMA)

    hass.services.async_register(
        DOMAIN, SERVICE_TURN_OFF, async_handle_light_service,
        descriptions.get(SERVICE_TURN_OFF), schema=LIGHT_TURN_OFF_SCHEMA)

    hass.services.async_register(
        DOMAIN, SERVICE_TOGGLE, async_handle_light_service,
        descriptions.get(SERVICE_TOGGLE), schema=LIGHT_TOGGLE_SCHEMA)

    return True
Exemplo n.º 53
0
def setup(hass, config):
    """Setup the Homematic component."""
    from pyhomematic import HMConnection

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    hass.data[DATA_DELAY] = config[DOMAIN].get(CONF_DELAY)
    hass.data[DATA_DEVINIT] = {}
    hass.data[DATA_STORE] = []

    # create hosts list for pyhomematic
    remotes = {}
    hosts = {}
    for rname, rconfig in list(config[DOMAIN][CONF_HOSTS].items()):
        server = rconfig.get(CONF_IP)

        remotes[rname] = {}
        remotes[rname][CONF_IP] = server
        remotes[rname][CONF_PORT] = rconfig.get(CONF_PORT)
        remotes[rname][CONF_RESOLVENAMES] = rconfig.get(CONF_RESOLVENAMES)
        remotes[rname][CONF_USERNAME] = rconfig.get(CONF_USERNAME)
        remotes[rname][CONF_PASSWORD] = rconfig.get(CONF_PASSWORD)

        if server not in hosts or rconfig.get(CONF_PRIMARY):
            hosts[server] = {
                CONF_VARIABLES: rconfig.get(CONF_VARIABLES),
                CONF_NAME: rname,
            }
        hass.data[DATA_DEVINIT][rname] = rconfig.get(CONF_DEVICES)

    # Create server thread
    bound_system_callback = partial(_system_callback_handler, hass, config)
    hass.data[DATA_HOMEMATIC] = HMConnection(
        local=config[DOMAIN].get(CONF_LOCAL_IP),
        localport=config[DOMAIN].get(CONF_LOCAL_PORT),
        remotes=remotes,
        systemcallback=bound_system_callback,
        interface_id="homeassistant")

    # Start server thread, connect to peer, initialize to receive events
    hass.data[DATA_HOMEMATIC].start()

    # Stops server when Homeassistant is shutting down
    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP,
                         hass.data[DATA_HOMEMATIC].stop)
    hass.config.components.append(DOMAIN)

    # init homematic hubs
    hub_entities = []
    for _, hub_data in list(hosts.items()):
        hub_entities.append(
            HMHub(hass, component, hub_data[CONF_NAME],
                  hub_data[CONF_VARIABLES]))
    component.add_entities(hub_entities)

    # regeister homematic services
    descriptions = load_yaml_config_file(
        os.path.join(os.path.dirname(__file__), 'services.yaml'))

    def _hm_service_virtualkey(service):
        """Service handle virtualkey services."""
        address = service.data.get(ATTR_ADDRESS)
        channel = service.data.get(ATTR_CHANNEL)
        param = service.data.get(ATTR_PARAM)

        # device not found
        hmdevice = _device_from_servicecall(hass, service)
        if hmdevice is None:
            _LOGGER.error("%s not found for service virtualkey!", address)
            return

        # if param exists for this device
        if param not in hmdevice.ACTIONNODE:
            _LOGGER.error("%s not datapoint in hm device %s", param, address)
            return

        # channel exists?
        if channel not in hmdevice.ACTIONNODE[param]:
            _LOGGER.error("%i is not a channel in hm device %s", channel,
                          address)
            return

        # call key
        hmdevice.actionNodeData(param, True, channel)

    hass.services.register(DOMAIN,
                           SERVICE_VIRTUALKEY,
                           _hm_service_virtualkey,
                           descriptions[DOMAIN][SERVICE_VIRTUALKEY],
                           schema=SCHEMA_SERVICE_VIRTUALKEY)

    def _service_handle_value(service):
        """Set value on homematic variable object."""
        variable_list = component.extract_from_service(service)

        value = service.data[ATTR_VALUE]

        for hm_variable in variable_list:
            if isinstance(hm_variable, HMVariable):
                hm_variable.hm_set(value)

    hass.services.register(DOMAIN,
                           SERVICE_SET_VAR_VALUE,
                           _service_handle_value,
                           descriptions[DOMAIN][SERVICE_SET_VAR_VALUE],
                           schema=SCHEMA_SERVICE_SET_VAR_VALUE)

    def _service_handle_reconnect(service):
        """Reconnect to all homematic hubs."""
        hass.data[DATA_HOMEMATIC].reconnect()

    hass.services.register(DOMAIN,
                           SERVICE_RECONNECT,
                           _service_handle_reconnect,
                           descriptions[DOMAIN][SERVICE_RECONNECT],
                           schema=SCHEMA_SERVICE_RECONNECT)

    def _service_handle_device(service):
        """Service handle set_dev_value services."""
        address = service.data.get(ATTR_ADDRESS)
        channel = service.data.get(ATTR_CHANNEL)
        param = service.data.get(ATTR_PARAM)
        value = service.data.get(ATTR_VALUE)

        # device not found
        hmdevice = _device_from_servicecall(hass, service)
        if hmdevice is None:
            _LOGGER.error("%s not found!", address)
            return

        # call key
        hmdevice.setValue(param, value, channel)

    hass.services.register(DOMAIN,
                           SERVICE_SET_DEV_VALUE,
                           _service_handle_device,
                           descriptions[DOMAIN][SERVICE_SET_DEV_VALUE],
                           schema=SCHEMA_SERVICE_SET_DEV_VALUE)

    return True
Exemplo n.º 54
0
def setup(hass, config):
    """Setup the OpenAlpr component."""
    engine = config[DOMAIN].get(CONF_ENGINE)
    region = config[DOMAIN].get(CONF_REGION)
    confidence = config[DOMAIN].get(CONF_CONFIDENCE)
    api_key = config[DOMAIN].get(CONF_API_KEY)
    binary = config[DOMAIN].get(CONF_ALPR_BINARY)
    use_render_fffmpeg = False

    component = EntityComponent(_LOGGER, DOMAIN, hass)
    openalpr_device = []

    for device in config[DOMAIN].get(CONF_ENTITIES):
        input_source = device.get(CONF_INPUT)
        render = device.get(CONF_RENDER)

        ##
        # create api
        if engine == ENGINE_LOCAL:
            alpr_api = OpenalprApiLocal(
                confidence=confidence,
                region=region,
                binary=binary,
            )
        else:
            alpr_api = OpenalprApiCloud(
                confidence=confidence,
                region=region,
                api_key=api_key,
            )

        ##
        # Create Alpr device / render engine
        if render == RENDER_FFMPEG:
            use_render_fffmpeg = True
            if not run_test(hass, input_source):
                _LOGGER.error("'%s' is not valid ffmpeg input", input_source)
                continue

            alpr_dev = OpenalprDeviceFFmpeg(
                name=device.get(CONF_NAME),
                interval=device.get(CONF_INTERVAL),
                api=alpr_api,
                input_source=input_source,
                extra_arguments=device.get(CONF_EXTRA_ARGUMENTS),
            )
        else:
            alpr_dev = OpenalprDeviceImage(
                name=device.get(CONF_NAME),
                interval=device.get(CONF_INTERVAL),
                api=alpr_api,
                input_source=input_source,
                username=device.get(CONF_USERNAME),
                password=device.get(CONF_PASSWORD),
            )

        # register shutdown event
        openalpr_device.append(alpr_dev)
        hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, alpr_dev.shutdown)

    component.add_entities(openalpr_device)

    descriptions = load_yaml_config_file(
        os.path.join(os.path.dirname(__file__), 'services.yaml'))

    def _handle_service_scan(service):
        """Handle service for immediately scan."""
        device_list = component.extract_from_service(service)

        for device in device_list:
            device.scan()

    hass.services.register(DOMAIN,
                           SERVICE_SCAN,
                           _handle_service_scan,
                           descriptions[DOMAIN][SERVICE_SCAN],
                           schema=SERVICE_SCAN_SCHEMA)

    # Add restart service only if a device use ffmpeg as render
    if not use_render_fffmpeg:
        return True

    def _handle_service_restart(service):
        """Handle service for restart ffmpeg process."""
        device_list = component.extract_from_service(service)

        for device in device_list:
            device.restart()

    hass.services.register(DOMAIN,
                           SERVICE_RESTART,
                           _handle_service_restart,
                           descriptions[DOMAIN][SERVICE_RESTART],
                           schema=SERVICE_RESTART_SCHEMA)

    return True
Exemplo n.º 55
0
def async_setup(hass, config):
    """Expose light control via statemachine and services."""
    component = EntityComponent(
        _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_LIGHTS)
    yield from component.async_setup(config)

    # load profiles from files
    profiles = yield from hass.loop.run_in_executor(
        None, _load_profile_data, hass)

    if profiles is None:
        return False

    @asyncio.coroutine
    def async_handle_light_service(service):
        """Hande a turn light on or off service call."""
        # Get the validated data
        params = service.data.copy()

        # Convert the entity ids to valid light ids
        target_lights = component.async_extract_from_service(service)
        params.pop(ATTR_ENTITY_ID, None)

        # Processing extra data for turn light on request.
        profile = profiles.get(params.pop(ATTR_PROFILE, None))

        if profile:
            params.setdefault(ATTR_XY_COLOR, profile[:2])
            params.setdefault(ATTR_BRIGHTNESS, profile[2])

        color_name = params.pop(ATTR_COLOR_NAME, None)

        if color_name is not None:
            params[ATTR_RGB_COLOR] = color_util.color_name_to_rgb(color_name)

        for light in target_lights:
            if service.service == SERVICE_TURN_ON:
                yield from light.async_turn_on(**params)
            elif service.service == SERVICE_TURN_OFF:
                yield from light.async_turn_off(**params)
            else:
                yield from light.async_toggle(**params)

        update_tasks = []

        for light in target_lights:
            if not light.should_poll:
                continue

            update_coro = hass.loop.create_task(
                light.async_update_ha_state(True))
            if hasattr(light, 'async_update'):
                update_tasks.append(update_coro)
            else:
                yield from update_coro

        if update_tasks:
            yield from asyncio.wait(update_tasks, loop=hass.loop)

    # Listen for light on and light off service calls.
    descriptions = yield from hass.loop.run_in_executor(
        None, load_yaml_config_file, os.path.join(
            os.path.dirname(__file__), 'services.yaml'))

    hass.services.async_register(
        DOMAIN, SERVICE_TURN_ON, async_handle_light_service,
        descriptions.get(SERVICE_TURN_ON), schema=LIGHT_TURN_ON_SCHEMA)

    hass.services.async_register(
        DOMAIN, SERVICE_TURN_OFF, async_handle_light_service,
        descriptions.get(SERVICE_TURN_OFF), schema=LIGHT_TURN_OFF_SCHEMA)

    hass.services.async_register(
        DOMAIN, SERVICE_TOGGLE, async_handle_light_service,
        descriptions.get(SERVICE_TOGGLE), schema=LIGHT_TOGGLE_SCHEMA)

    return True
Exemplo n.º 56
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the weather component."""
    component = hass.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, hass,
                                                    SCAN_INTERVAL)
    await component.async_setup(config)
    return True
Exemplo n.º 57
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
    """Set up an input datetime."""
    component = EntityComponent(_LOGGER, DOMAIN, hass)
    id_manager = collection.IDManager()

    yaml_collection = collection.YamlCollection(
        logging.getLogger(f"{__name__}.yaml_collection"), id_manager)
    collection.sync_entity_lifecycle(hass, DOMAIN, DOMAIN, component,
                                     yaml_collection, InputDatetime.from_yaml)

    storage_collection = DateTimeStorageCollection(
        Store(hass, STORAGE_VERSION, STORAGE_KEY),
        logging.getLogger(f"{__name__}.storage_collection"),
        id_manager,
    )
    collection.sync_entity_lifecycle(hass, DOMAIN, DOMAIN, component,
                                     storage_collection, InputDatetime)

    await yaml_collection.async_load([{
        CONF_ID: id_,
        **cfg
    } for id_, cfg in config.get(DOMAIN, {}).items()])
    await storage_collection.async_load()

    collection.StorageCollectionWebsocket(storage_collection, DOMAIN, DOMAIN,
                                          CREATE_FIELDS,
                                          UPDATE_FIELDS).async_setup(hass)

    async def reload_service_handler(service_call: ServiceCallType) -> None:
        """Reload yaml entities."""
        conf = await component.async_prepare_reload(skip_reset=True)
        if conf is None:
            conf = {DOMAIN: {}}
        await yaml_collection.async_load([{
            CONF_ID: id_,
            **cfg
        } for id_, cfg in conf.get(DOMAIN, {}).items()])

    homeassistant.helpers.service.async_register_admin_service(
        hass,
        DOMAIN,
        SERVICE_RELOAD,
        reload_service_handler,
        schema=RELOAD_SERVICE_SCHEMA,
    )

    component.async_register_entity_service(
        "set_datetime",
        vol.All(
            vol.Schema(
                {
                    vol.Optional(ATTR_DATE): cv.date,
                    vol.Optional(ATTR_TIME): cv.time,
                    vol.Optional(ATTR_DATETIME): cv.datetime,
                    vol.Optional(ATTR_TIMESTAMP): vol.Coerce(float),
                },
                extra=vol.ALLOW_EXTRA,
            ),
            cv.has_at_least_one_key(ATTR_DATE, ATTR_TIME, ATTR_DATETIME,
                                    ATTR_TIMESTAMP),
            validate_set_datetime_attrs,
        ),
        "async_set_datetime",
    )

    return True
Exemplo n.º 58
0
def setup(hass, config):
    """Expose light control via statemachine and services."""
    component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL,
                                GROUP_NAME_ALL_LIGHTS)
    component.setup(config)

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

    for profile_path in profile_paths:
        if not os.path.isfile(profile_path):
            continue
        with open(profile_path) as inp:
            reader = csv.reader(inp)

            # Skip the header
            next(reader, None)

            try:
                for rec in reader:
                    profile, color_x, color_y, brightness = PROFILE_SCHEMA(rec)
                    profiles[profile] = (color_x, color_y, brightness)
            except vol.MultipleInvalid as ex:
                _LOGGER.error("Error parsing light profile from %s: %s",
                              profile_path, ex)
                return False

    def handle_light_service(service):
        """Hande a turn light on or off service call."""
        # Get the validated data
        params = service.data.copy()

        # Convert the entity ids to valid light ids
        target_lights = component.extract_from_service(service)
        params.pop(ATTR_ENTITY_ID, None)

        service_fun = None
        if service.service == SERVICE_TURN_OFF:
            service_fun = 'turn_off'
        elif service.service == SERVICE_TOGGLE:
            service_fun = 'toggle'

        if service_fun:
            for light in target_lights:
                getattr(light, service_fun)(**params)

            for light in target_lights:
                if light.should_poll:
                    light.update_ha_state(True)
            return

        # Processing extra data for turn light on request.
        profile = profiles.get(params.pop(ATTR_PROFILE, None))

        if profile:
            params.setdefault(ATTR_XY_COLOR, profile[:2])
            params.setdefault(ATTR_BRIGHTNESS, profile[2])

        color_name = params.pop(ATTR_COLOR_NAME, None)

        if color_name is not None:
            params[ATTR_RGB_COLOR] = color_util.color_name_to_rgb(color_name)

        for light in target_lights:
            light.turn_on(**params)

        for light in target_lights:
            if light.should_poll:
                light.update_ha_state(True)

    # Listen for light on and light off service calls.
    descriptions = load_yaml_config_file(
        os.path.join(os.path.dirname(__file__), 'services.yaml'))
    hass.services.register(DOMAIN,
                           SERVICE_TURN_ON,
                           handle_light_service,
                           descriptions.get(SERVICE_TURN_ON),
                           schema=LIGHT_TURN_ON_SCHEMA)

    hass.services.register(DOMAIN,
                           SERVICE_TURN_OFF,
                           handle_light_service,
                           descriptions.get(SERVICE_TURN_OFF),
                           schema=LIGHT_TURN_OFF_SCHEMA)

    hass.services.register(DOMAIN,
                           SERVICE_TOGGLE,
                           handle_light_service,
                           descriptions.get(SERVICE_TOGGLE),
                           schema=LIGHT_TOGGLE_SCHEMA)

    return True
Exemplo n.º 59
0
async def async_setup(hass, config):
    """Track states and offer events for sensors."""
    component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)

    await component.async_setup(config)
    return True
Exemplo n.º 60
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
    """Set up an input slider."""
    component = EntityComponent(_LOGGER, DOMAIN, hass)
    id_manager = collection.IDManager()

    yaml_collection = collection.YamlCollection(
        logging.getLogger(f"{__name__}.yaml_collection"), id_manager)
    collection.attach_entity_component_collection(
        component, yaml_collection,
        lambda cfg: TemplateNumber.from_yaml(cfg, hass))

    storage_collection = NumberStorageCollection(
        Store(hass, STORAGE_VERSION, STORAGE_KEY),
        logging.getLogger(f"{__name__}.storage_collection"),
        id_manager,
    )
    collection.attach_entity_component_collection(component,
                                                  storage_collection,
                                                  TemplateNumber)

    await yaml_collection.async_load([{
        CONF_ID: id_,
        **(conf or {})
    } for id_, conf in config.get(DOMAIN, {}).items()])
    await storage_collection.async_load()

    collection.StorageCollectionWebsocket(storage_collection, DOMAIN, DOMAIN,
                                          CREATE_FIELDS,
                                          UPDATE_FIELDS).async_setup(hass)

    collection.attach_entity_registry_cleaner(hass, DOMAIN, DOMAIN,
                                              yaml_collection)
    collection.attach_entity_registry_cleaner(hass, DOMAIN, DOMAIN,
                                              storage_collection)

    async def reload_service_handler(service_call: ServiceCallType) -> None:
        """Reload yaml entities."""
        conf = await component.async_prepare_reload(skip_reset=True)
        if conf is None:
            conf = {DOMAIN: {}}
        await yaml_collection.async_load([{
            CONF_ID: id_,
            **conf
        } for id_, conf in conf.get(DOMAIN, {}).items()])

    homeassistant.helpers.service.async_register_admin_service(
        hass,
        DOMAIN,
        SERVICE_RELOAD,
        reload_service_handler,
        schema=RELOAD_SERVICE_SCHEMA,
    )

    component.async_register_entity_service(
        SERVICE_SET_VALUE,
        {vol.Required(ATTR_VALUE): vol.Coerce(float)},
        "async_set_value",
    )

    component.async_register_entity_service(SERVICE_INCREMENT, {},
                                            "async_increment")

    component.async_register_entity_service(SERVICE_DECREMENT, {},
                                            "async_decrement")

    # (Start) Template Number
    component.async_register_entity_service(
        SERVICE_SET_VALUE_NO_SCRIPT,
        {vol.Required(ATTR_VALUE): vol.Coerce(float)},
        "async_set_value_no_script",
    )
    # (End) Template Number

    return True