Example #1
0
    def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry,
                 api: DeconzSession) -> None:
        """Initialize the system."""
        self.hass = hass
        self.config_entry = config_entry
        self.api = api

        api.add_device_callback = self.async_add_device_callback
        api.connection_status_callback = self.async_connection_status_callback

        self.available = True
        self.ignore_state_updates = False

        self.signal_reachable = f"deconz-reachable-{config_entry.entry_id}"
        self.signal_reload_groups = f"deconz_reload_group_{config_entry.entry_id}"

        self.signal_new_light = f"deconz_new_light_{config_entry.entry_id}"
        self.signal_new_sensor = f"deconz_new_sensor_{config_entry.entry_id}"

        self.deconz_resource_type_to_signal_new_device = {
            ResourceGroup.LIGHT.value: self.signal_new_light,
            ResourceGroup.SENSOR.value: self.signal_new_sensor,
        }

        self.deconz_ids: dict[str, str] = {}
        self.entities: dict[str, set[str]] = {}
        self.events: list[DeconzAlarmEvent | DeconzEvent] = []

        self._option_allow_deconz_groups = self.config_entry.options.get(
            CONF_ALLOW_DECONZ_GROUPS, DEFAULT_ALLOW_DECONZ_GROUPS)
Example #2
0
    def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry,
                 api: DeconzSession) -> None:
        """Initialize the system."""
        self.hass = hass
        self.config_entry = config_entry
        self.api = api

        api.add_device_callback = self.async_add_device_callback
        api.connection_status_callback = self.async_connection_status_callback

        self.available = True
        self.ignore_state_updates = False

        self.signal_reachable = f"deconz-reachable-{config_entry.entry_id}"

        self.signal_new_group = f"deconz_new_group_{config_entry.entry_id}"
        self.signal_new_light = f"deconz_new_light_{config_entry.entry_id}"
        self.signal_new_scene = f"deconz_new_scene_{config_entry.entry_id}"
        self.signal_new_sensor = f"deconz_new_sensor_{config_entry.entry_id}"

        self.deconz_resource_type_to_signal_new_device = {
            group.RESOURCE_TYPE: self.signal_new_group,
            light.RESOURCE_TYPE: self.signal_new_light,
            group.RESOURCE_TYPE_SCENE: self.signal_new_scene,
            sensor.RESOURCE_TYPE: self.signal_new_sensor,
        }

        self.deconz_ids: dict[str, str] = {}
        self.entities: dict[str, set[str]] = {}
        self.events: list[DeconzAlarmEvent | DeconzEvent] = []
Example #3
0
def async_setup_deconz(hass, config, deconz_config):
    """Set up a deCONZ session.

    Load config, group, light and sensor data for server information.
    Start websocket for push notification of state changes from deCONZ.
    """
    _LOGGER.debug("deCONZ config %s", deconz_config)
    from pydeconz import DeconzSession
    websession = async_get_clientsession(hass)
    deconz = DeconzSession(hass.loop, websession, **deconz_config)
    result = yield from deconz.async_load_parameters()
    if result is False:
        _LOGGER.error("Failed to communicate with deCONZ")
        return False

    hass.data[DOMAIN] = deconz
    hass.data[DATA_DECONZ_ID] = {}

    for component in ['binary_sensor', 'light', 'scene', 'sensor']:
        hass.async_add_job(
            discovery.async_load_platform(hass, component, DOMAIN, {}, config))
    deconz.start()

    @asyncio.coroutine
    def async_configure(call):
        """Set attribute of device in deCONZ.

        Field is a string representing a specific device in deCONZ
        e.g. field='/lights/1/state'.
        Entity_id can be used to retrieve the proper field.
        Data is a json object with what data you want to alter
        e.g. data={'on': true}.
        {
            "field": "/lights/1/state",
            "data": {"on": true}
        }
        See Dresden Elektroniks REST API documentation for details:
        http://dresden-elektronik.github.io/deconz-rest-doc/rest/
        """
        field = call.data.get(SERVICE_FIELD)
        entity_id = call.data.get(SERVICE_ENTITY)
        data = call.data.get(SERVICE_DATA)
        deconz = hass.data[DOMAIN]
        if entity_id:
            entities = hass.data.get(DATA_DECONZ_ID)
            if entities:
                field = entities.get(entity_id)
            if field is None:
                _LOGGER.error('Could not find the entity %s', entity_id)
                return
        yield from deconz.async_put_state(field, data)

    hass.services.async_register(DOMAIN,
                                 'configure',
                                 async_configure,
                                 schema=SERVICE_SCHEMA)

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, deconz.close)
    return True
Example #4
0
async def get_deconz_session(
    hass: HomeAssistant,
    config: MappingProxyType[str, Any],
) -> DeconzSession:
    """Create a gateway object and verify configuration."""
    session = aiohttp_client.async_get_clientsession(hass)

    deconz_session = DeconzSession(
        session,
        config[CONF_HOST],
        config[CONF_PORT],
        config[CONF_API_KEY],
    )
    try:
        async with async_timeout.timeout(10):
            await deconz_session.refresh_state()
        return deconz_session

    except errors.Unauthorized as err:
        LOGGER.warning("Invalid key for deCONZ at %s", config[CONF_HOST])
        raise AuthenticationRequired from err

    except (asyncio.TimeoutError, errors.RequestError) as err:
        LOGGER.error("Error connecting to deCONZ gateway at %s",
                     config[CONF_HOST])
        raise CannotConnect from err
Example #5
0
async def main(loop, **kwargs):
    """
    """
    if 'api_key' not in kwargs:
        api_key = await async_get_api_key(loop, **kwargs)
        kwargs['api_key'] = api_key
        print(api_key)
    websession = aiohttp.ClientSession(loop=loop)
    deconz = DeconzSession(loop, websession, **kwargs)
    result = await deconz.async_load_parameters()
    if result is False:
        print('Failed to setup deCONZ')
        return False
    deconz.start()
    from pprint import pprint
    pprint(deconz.__dict__)
Example #6
0
async def setup_gateway(hass, data, allow_clip_sensor=True):
    """Load the deCONZ binary sensor platform."""
    from pydeconz import DeconzSession

    loop = Mock()
    session = Mock()

    ENTRY_OPTIONS[deconz.const.CONF_ALLOW_CLIP_SENSOR] = allow_clip_sensor

    config_entry = config_entries.ConfigEntry(
        1,
        deconz.DOMAIN,
        "Mock Title",
        ENTRY_CONFIG,
        "test",
        config_entries.CONN_CLASS_LOCAL_PUSH,
        system_options={},
        options=ENTRY_OPTIONS,
    )
    gateway = deconz.DeconzGateway(hass, config_entry)
    gateway.api = DeconzSession(loop, session, **config_entry.data)
    gateway.api.config = Mock()
    hass.data[deconz.DOMAIN] = {gateway.bridgeid: gateway}

    with patch("pydeconz.DeconzSession.async_get_state",
               return_value=mock_coro(data)):
        await gateway.api.async_load_parameters()

    await hass.config_entries.async_forward_entry_setup(
        config_entry, "binary_sensor")
    # To flush out the service call to update the group
    await hass.async_block_till_done()
    return gateway
Example #7
0
async def setup_gateway(hass, data):
    """Load the deCONZ cover platform."""
    from pydeconz import DeconzSession

    loop = Mock()
    session = Mock()

    config_entry = config_entries.ConfigEntry(
        1,
        deconz.DOMAIN,
        "Mock Title",
        ENTRY_CONFIG,
        "test",
        config_entries.CONN_CLASS_LOCAL_PUSH,
    )
    gateway = deconz.DeconzGateway(hass, config_entry)
    gateway.api = DeconzSession(loop, session, **config_entry.data)
    gateway.api.config = Mock()
    hass.data[deconz.DOMAIN] = {gateway.bridgeid: gateway}

    with patch("pydeconz.DeconzSession.async_get_state", return_value=mock_coro(data)):
        await gateway.api.async_load_parameters()

    await hass.config_entries.async_forward_entry_setup(config_entry, "cover")
    # To flush out the service call to update the group
    await hass.async_block_till_done()
    return gateway
Example #8
0
async def setup_gateway(hass, data, allow_clip_sensor=True):
    """Load the deCONZ sensor platform."""
    from pydeconz import DeconzSession

    response = Mock(status=200,
                    json=asynctest.CoroutineMock(),
                    text=asynctest.CoroutineMock())
    response.content_type = 'application/json'

    session = Mock(put=asynctest.CoroutineMock(return_value=response))

    ENTRY_CONFIG[deconz.const.CONF_ALLOW_CLIP_SENSOR] = allow_clip_sensor

    config_entry = config_entries.ConfigEntry(
        1, deconz.DOMAIN, 'Mock Title', ENTRY_CONFIG, 'test',
        config_entries.CONN_CLASS_LOCAL_PUSH)
    gateway = deconz.DeconzGateway(hass, config_entry)
    gateway.api = DeconzSession(hass.loop, session, **config_entry.data)
    gateway.api.config = Mock()
    hass.data[deconz.DOMAIN] = {gateway.bridgeid: gateway}

    with patch('pydeconz.DeconzSession.async_get_state',
               return_value=mock_coro(data)):
        await gateway.api.async_load_parameters()

    await hass.config_entries.async_forward_entry_setup(
        config_entry, 'climate')
    # To flush out the service call to update the group
    await hass.async_block_till_done()
    return gateway
Example #9
0
async def get_gateway(hass, config, async_add_device_callback,
                      async_connection_status_callback) -> DeconzSession:
    """Create a gateway object and verify configuration."""
    session = aiohttp_client.async_get_clientsession(hass)

    deconz = DeconzSession(
        session,
        config[CONF_HOST],
        config[CONF_PORT],
        config[CONF_API_KEY],
        async_add_device=async_add_device_callback,
        connection_status=async_connection_status_callback,
    )
    try:
        with async_timeout.timeout(10):
            await deconz.initialize()
        return deconz

    except errors.Unauthorized as err:
        LOGGER.warning("Invalid key for deCONZ at %s", config[CONF_HOST])
        raise AuthenticationRequired from err

    except (asyncio.TimeoutError, errors.RequestError) as err:
        LOGGER.error("Error connecting to deCONZ gateway at %s",
                     config[CONF_HOST])
        raise CannotConnect from err
Example #10
0
    def __init__(
        self, hass: HomeAssistant, config_entry: ConfigEntry, api: DeconzSession
    ) -> None:
        """Initialize the system."""
        self.hass = hass
        self.config_entry = config_entry
        self.api = api

        api.connection_status_callback = self.async_connection_status_callback

        self.available = True
        self.ignore_state_updates = False

        self.signal_reachable = f"deconz-reachable-{config_entry.entry_id}"
        self.signal_reload_groups = f"deconz_reload_group_{config_entry.entry_id}"
        self.signal_reload_clip_sensors = f"deconz_reload_clip_{config_entry.entry_id}"

        self.deconz_ids: dict[str, str] = {}
        self.entities: dict[str, set[str]] = {}
        self.events: list[DeconzAlarmEvent | DeconzEvent] = []
        self.ignored_devices: set[tuple[Callable[[EventType, str], None], str]] = set()

        self._option_allow_deconz_groups = self.config_entry.options.get(
            CONF_ALLOW_DECONZ_GROUPS, DEFAULT_ALLOW_DECONZ_GROUPS
        )
        self.option_allow_new_devices = self.config_entry.options.get(
            CONF_ALLOW_NEW_DEVICES, DEFAULT_ALLOW_NEW_DEVICES
        )
Example #11
0
async def get_gateway(hass, config, async_add_device_callback,
                      async_connection_status_callback):
    """Create a gateway object and verify configuration."""
    session = aiohttp_client.async_get_clientsession(hass)

    deconz = DeconzSession(
        hass.loop,
        session,
        **config,
        async_add_device=async_add_device_callback,
        connection_status=async_connection_status_callback,
    )
    try:
        with async_timeout.timeout(10):
            await deconz.async_load_parameters()
        return deconz

    except errors.Unauthorized:
        _LOGGER.warning("Invalid key for deCONZ at %s", config[CONF_HOST])
        raise AuthenticationRequired

    except (asyncio.TimeoutError, errors.RequestError):
        _LOGGER.error("Error connecting to deCONZ gateway at %s",
                      config[CONF_HOST])
        raise CannotConnect
Example #12
0
def async_setup_deconz(hass, config, deconz_config):
    """Set up a deCONZ session.

    Load config, group, light and sensor data for server information.
    Start websocket for push notification of state changes from deCONZ.
    """
    _LOGGER.debug("deCONZ config %s", deconz_config)
    from pydeconz import DeconzSession
    websession = async_get_clientsession(hass)
    deconz = DeconzSession(hass.loop, websession, **deconz_config)
    result = yield from deconz.async_load_parameters()
    if result is False:
        _LOGGER.error("Failed to communicate with deCONZ")
        return False

    hass.data[DOMAIN] = deconz

    for component in ['binary_sensor', 'light', 'scene', 'sensor']:
        hass.async_add_job(discovery.async_load_platform(
            hass, component, DOMAIN, {}, config))
    deconz.start()

    @asyncio.coroutine
    def async_configure(call):
        """Set attribute of device in deCONZ.

        Field is a string representing a specific device in deCONZ
        e.g. field='/lights/1/state'.
        Data is a json object with what data you want to alter
        e.g. data={'on': true}.
        {
            "field": "/lights/1/state",
            "data": {"on": true}
        }
        See Dresden Elektroniks REST API documentation for details:
        http://dresden-elektronik.github.io/deconz-rest-doc/rest/
        """
        deconz = hass.data[DOMAIN]
        field = call.data.get(SERVICE_FIELD)
        data = call.data.get(SERVICE_DATA)
        yield from deconz.async_put_state(field, data)
    hass.services.async_register(
        DOMAIN, 'configure', async_configure, schema=SERVICE_SCHEMA)

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, deconz.close)
    return True
Example #13
0
def main(loop, **kwargs):
    """
    """
    if 'api_key' not in kwargs:
        api_key = yield from async_get_api_key(loop, **kwargs)
        kwargs['api_key'] = api_key
        print(api_key)
    websession = aiohttp.ClientSession(loop=loop)
    deconz = DeconzSession(loop, websession, **kwargs)
    result = yield from deconz.async_load_parameters()
    if result is False:
        print('Failed to setup deCONZ')
        return False
    deconz.start()
    from pprint import pprint
    for dev_id, dev in deconz.sensors.items():
        pprint(dev.__dict__)
Example #14
0
async def setup_bridge(hass, data):
    """Load the deCONZ switch platform."""
    from pydeconz import DeconzSession
    loop = Mock()
    session = Mock()
    entry = Mock()
    entry.data = {'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'}
    bridge = DeconzSession(loop, session, **entry.data)
    bridge.config = Mock()
    with patch('pydeconz.DeconzSession.async_get_state',
               return_value=mock_coro(data)):
        await bridge.async_load_parameters()
    hass.data[deconz.DOMAIN] = bridge
    hass.data[deconz.DATA_DECONZ_UNSUB] = []
    hass.data[deconz.DATA_DECONZ_ID] = {}
    config_entry = config_entries.ConfigEntry(
        1, deconz.DOMAIN, 'Mock Title', {'host': 'mock-host'}, 'test',
        config_entries.CONN_CLASS_LOCAL_PUSH)
    await hass.config_entries.async_forward_entry_setup(config_entry, 'switch')
    # To flush out the service call to update the group
    await hass.async_block_till_done()
Example #15
0
async def get_gateway(hass, config, async_add_device_callback):
    """Create a gateway object and verify configuration."""
    from pydeconz import DeconzSession

    session = aiohttp_client.async_get_clientsession(hass)
    deconz = DeconzSession(hass.loop,
                           session,
                           **config,
                           async_add_device=async_add_device_callback)
    result = await deconz.async_load_parameters()

    if result:
        return deconz
    return result
Example #16
0
def main(loop, **kwargs):
    """
    """
    if 'api_key' not in kwargs:
        api_key = yield from get_api_key(loop, **kwargs)
        kwargs['api_key'] = api_key
        print(api_key)

    deconz = DeconzSession(loop, **kwargs)
    result = yield from deconz.populate_config()
    result = yield from deconz.populate_lights()
    result = yield from deconz.populate_sensors()
    deconz.start()
Example #17
0
async def setup_gateway(hass, data, allow_deconz_groups=True):
    """Load the deCONZ light platform."""
    from pydeconz import DeconzSession
    loop = Mock()
    session = Mock()

    ENTRY_CONFIG[deconz.const.CONF_ALLOW_DECONZ_GROUPS] = allow_deconz_groups

    config_entry = config_entries.ConfigEntry(
        1, deconz.DOMAIN, 'Mock Title', ENTRY_CONFIG, 'test',
        config_entries.CONN_CLASS_LOCAL_PUSH)
    gateway = deconz.DeconzGateway(hass, config_entry)
    gateway.api = DeconzSession(loop, session, **config_entry.data)
    gateway.api.config = Mock()
    hass.data[deconz.DOMAIN] = gateway

    with patch('pydeconz.DeconzSession.async_get_state',
               return_value=mock_coro(data)):
        await gateway.api.async_load_parameters()

    await hass.config_entries.async_forward_entry_setup(config_entry, 'light')
    # To flush out the service call to update the group
    await hass.async_block_till_done()
Example #18
0
def session() -> DeconzSession:
    """Returns the session object."""
    loop = Mock()
    session = Mock()

    return DeconzSession(loop, session, IP, PORT, API_KEY)
Example #19
0
async def async_setup_entry(hass, config_entry):
    """Set up a deCONZ bridge for a config entry.

    Load config, group, light and sensor data for server information.
    Start websocket for push notification of state changes from deCONZ.
    """
    from pydeconz import DeconzSession
    if DOMAIN in hass.data:
        _LOGGER.error(
            "Config entry failed since one deCONZ instance already exists")
        return False

    @callback
    def async_add_device_callback(device_type, device):
        """Handle event of new device creation in deCONZ."""
        async_dispatcher_send(hass, 'deconz_new_{}'.format(device_type),
                              [device])

    session = aiohttp_client.async_get_clientsession(hass)
    deconz = DeconzSession(hass.loop,
                           session,
                           **config_entry.data,
                           async_add_device=async_add_device_callback)
    result = await deconz.async_load_parameters()
    if result is False:
        _LOGGER.error("Failed to communicate with deCONZ")
        return False

    hass.data[DOMAIN] = deconz
    hass.data[DATA_DECONZ_ID] = {}
    hass.data[DATA_DECONZ_EVENT] = []
    hass.data[DATA_DECONZ_UNSUB] = []

    for component in ['binary_sensor', 'light', 'scene', 'sensor', 'switch']:
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(
                config_entry, component))

    @callback
    def async_add_remote(sensors):
        """Set up remote from deCONZ."""
        from pydeconz.sensor import SWITCH as DECONZ_REMOTE
        allow_clip_sensor = config_entry.data.get(CONF_ALLOW_CLIP_SENSOR, True)
        for sensor in sensors:
            if sensor.type in DECONZ_REMOTE and \
               not (not allow_clip_sensor and sensor.type.startswith('CLIP')):
                hass.data[DATA_DECONZ_EVENT].append(DeconzEvent(hass, sensor))

    hass.data[DATA_DECONZ_UNSUB].append(
        async_dispatcher_connect(hass, 'deconz_new_sensor', async_add_remote))

    async_add_remote(deconz.sensors.values())

    deconz.start()

    async def async_configure(call):
        """Set attribute of device in deCONZ.

        Field is a string representing a specific device in deCONZ
        e.g. field='/lights/1/state'.
        Entity_id can be used to retrieve the proper field.
        Data is a json object with what data you want to alter
        e.g. data={'on': true}.
        {
            "field": "/lights/1/state",
            "data": {"on": true}
        }
        See Dresden Elektroniks REST API documentation for details:
        http://dresden-elektronik.github.io/deconz-rest-doc/rest/
        """
        field = call.data.get(SERVICE_FIELD)
        entity_id = call.data.get(SERVICE_ENTITY)
        data = call.data.get(SERVICE_DATA)
        deconz = hass.data[DOMAIN]
        if entity_id:
            entities = hass.data.get(DATA_DECONZ_ID)
            if entities:
                field = entities.get(entity_id)
            if field is None:
                _LOGGER.error('Could not find the entity %s', entity_id)
                return
        await deconz.async_put_state(field, data)

    hass.services.async_register(DOMAIN,
                                 SERVICE_DECONZ,
                                 async_configure,
                                 schema=SERVICE_SCHEMA)

    @callback
    def deconz_shutdown(event):
        """
        Wrap the call to deconz.close.

        Used as an argument to EventBus.async_listen_once - EventBus calls
        this method with the event as the first argument, which should not
        be passed on to deconz.close.
        """
        deconz.close()

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, deconz_shutdown)
    return True
Example #20
0
async def async_setup_entry(hass, config_entry):
    """Set up a deCONZ bridge for a config entry.

    Load config, group, light and sensor data for server information.
    Start websocket for push notification of state changes from deCONZ.
    """
    from pydeconz import DeconzSession
    if DOMAIN in hass.data:
        _LOGGER.error(
            "Config entry failed since one deCONZ instance already exists")
        return False

    @callback
    def async_add_device_callback(device_type, device):
        """Handle event of new device creation in deCONZ."""
        if not isinstance(device, list):
            device = [device]
        async_dispatcher_send(hass, 'deconz_new_{}'.format(device_type),
                              device)

    session = aiohttp_client.async_get_clientsession(hass)
    deconz = DeconzSession(hass.loop,
                           session,
                           **config_entry.data,
                           async_add_device=async_add_device_callback)
    result = await deconz.async_load_parameters()

    if result is False:
        return False

    hass.data[DOMAIN] = deconz
    hass.data[DATA_DECONZ_ID] = {}
    hass.data[DATA_DECONZ_EVENT] = []
    hass.data[DATA_DECONZ_UNSUB] = []

    for component in SUPPORTED_PLATFORMS:
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(
                config_entry, component))

    @callback
    def async_add_remote(sensors):
        """Set up remote from deCONZ."""
        from pydeconz.sensor import SWITCH as DECONZ_REMOTE
        allow_clip_sensor = config_entry.data.get(CONF_ALLOW_CLIP_SENSOR, True)
        for sensor in sensors:
            if sensor.type in DECONZ_REMOTE and \
               not (not allow_clip_sensor and sensor.type.startswith('CLIP')):
                hass.data[DATA_DECONZ_EVENT].append(DeconzEvent(hass, sensor))

    hass.data[DATA_DECONZ_UNSUB].append(
        async_dispatcher_connect(hass, 'deconz_new_sensor', async_add_remote))

    async_add_remote(deconz.sensors.values())

    deconz.start()

    device_registry = await \
        hass.helpers.device_registry.async_get_registry()
    device_registry.async_get_or_create(config_entry_id=config_entry.entry_id,
                                        connections={(CONNECTION_NETWORK_MAC,
                                                      deconz.config.mac)},
                                        identifiers={(DOMAIN,
                                                      deconz.config.bridgeid)},
                                        manufacturer='Dresden Elektronik',
                                        model=deconz.config.modelid,
                                        name=deconz.config.name,
                                        sw_version=deconz.config.swversion)

    async def async_configure(call):
        """Set attribute of device in deCONZ.

        Field is a string representing a specific device in deCONZ
        e.g. field='/lights/1/state'.
        Entity_id can be used to retrieve the proper field.
        Data is a json object with what data you want to alter
        e.g. data={'on': true}.
        {
            "field": "/lights/1/state",
            "data": {"on": true}
        }
        See Dresden Elektroniks REST API documentation for details:
        http://dresden-elektronik.github.io/deconz-rest-doc/rest/
        """
        field = call.data.get(SERVICE_FIELD)
        entity_id = call.data.get(SERVICE_ENTITY)
        data = call.data.get(SERVICE_DATA)
        deconz = hass.data[DOMAIN]
        if entity_id:

            entities = hass.data.get(DATA_DECONZ_ID)

            if entities:
                field = entities.get(entity_id)

            if field is None:
                _LOGGER.error('Could not find the entity %s', entity_id)
                return

        await deconz.async_put_state(field, data)

    hass.services.async_register(DOMAIN,
                                 SERVICE_DECONZ,
                                 async_configure,
                                 schema=SERVICE_SCHEMA)

    async def async_refresh_devices(call):
        """Refresh available devices from deCONZ."""
        deconz = hass.data[DOMAIN]

        groups = list(deconz.groups.keys())
        lights = list(deconz.lights.keys())
        scenes = list(deconz.scenes.keys())
        sensors = list(deconz.sensors.keys())

        if not await deconz.async_load_parameters():
            return

        async_add_device_callback('group', [
            group for group_id, group in deconz.groups.items()
            if group_id not in groups
        ])

        async_add_device_callback('light', [
            light for light_id, light in deconz.lights.items()
            if light_id not in lights
        ])

        async_add_device_callback('scene', [
            scene for scene_id, scene in deconz.scenes.items()
            if scene_id not in scenes
        ])

        async_add_device_callback('sensor', [
            sensor for sensor_id, sensor in deconz.sensors.items()
            if sensor_id not in sensors
        ])

    hass.services.async_register(DOMAIN, SERVICE_DEVICE_REFRESH,
                                 async_refresh_devices)

    @callback
    def deconz_shutdown(event):
        """
        Wrap the call to deconz.close.

        Used as an argument to EventBus.async_listen_once - EventBus calls
        this method with the event as the first argument, which should not
        be passed on to deconz.close.
        """
        deconz.close()

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, deconz_shutdown)
    return True
Example #21
0
async def async_setup_entry(hass, config_entry):
    """Set up a deCONZ bridge for a config entry.

    Load config, group, light and sensor data for server information.
    Start websocket for push notification of state changes from deCONZ.
    """
    from pydeconz import DeconzSession
    if DOMAIN in hass.data:
        _LOGGER.error(
            "Config entry failed since one deCONZ instance already exists")
        return False

    @callback
    def async_add_device_callback(device_type, device):
        """Called when a new device has been created in deCONZ."""
        async_dispatcher_send(
            hass, 'deconz_new_{}'.format(device_type), [device])

    session = aiohttp_client.async_get_clientsession(hass)
    deconz = DeconzSession(hass.loop, session, **config_entry.data,
                           async_add_device=async_add_device_callback)
    result = await deconz.async_load_parameters()
    if result is False:
        _LOGGER.error("Failed to communicate with deCONZ")
        return False

    hass.data[DOMAIN] = deconz
    hass.data[DATA_DECONZ_ID] = {}
    hass.data[DATA_DECONZ_EVENT] = []
    hass.data[DATA_DECONZ_UNSUB] = []

    for component in ['binary_sensor', 'light', 'scene', 'sensor', 'switch']:
        hass.async_create_task(hass.config_entries.async_forward_entry_setup(
            config_entry, component))

    @callback
    def async_add_remote(sensors):
        """Setup remote from deCONZ."""
        from pydeconz.sensor import SWITCH as DECONZ_REMOTE
        allow_clip_sensor = config_entry.data.get(CONF_ALLOW_CLIP_SENSOR, True)
        for sensor in sensors:
            if sensor.type in DECONZ_REMOTE and \
               not (not allow_clip_sensor and sensor.type.startswith('CLIP')):
                hass.data[DATA_DECONZ_EVENT].append(DeconzEvent(hass, sensor))
    hass.data[DATA_DECONZ_UNSUB].append(
        async_dispatcher_connect(hass, 'deconz_new_sensor', async_add_remote))

    async_add_remote(deconz.sensors.values())

    deconz.start()

    async def async_configure(call):
        """Set attribute of device in deCONZ.

        Field is a string representing a specific device in deCONZ
        e.g. field='/lights/1/state'.
        Entity_id can be used to retrieve the proper field.
        Data is a json object with what data you want to alter
        e.g. data={'on': true}.
        {
            "field": "/lights/1/state",
            "data": {"on": true}
        }
        See Dresden Elektroniks REST API documentation for details:
        http://dresden-elektronik.github.io/deconz-rest-doc/rest/
        """
        field = call.data.get(SERVICE_FIELD)
        entity_id = call.data.get(SERVICE_ENTITY)
        data = call.data.get(SERVICE_DATA)
        deconz = hass.data[DOMAIN]
        if entity_id:
            entities = hass.data.get(DATA_DECONZ_ID)
            if entities:
                field = entities.get(entity_id)
            if field is None:
                _LOGGER.error('Could not find the entity %s', entity_id)
                return
        await deconz.async_put_state(field, data)
    hass.services.async_register(
        DOMAIN, SERVICE_DECONZ, async_configure, schema=SERVICE_SCHEMA)

    @callback
    def deconz_shutdown(event):
        """
        Wrap the call to deconz.close.

        Used as an argument to EventBus.async_listen_once - EventBus calls
        this method with the event as the first argument, which should not
        be passed on to deconz.close.
        """
        deconz.close()

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, deconz_shutdown)
    return True
Example #22
0
async def async_setup_deconz(hass, config, deconz_config):
    """Set up a deCONZ session.

    Load config, group, light and sensor data for server information.
    Start websocket for push notification of state changes from deCONZ.
    """
    _LOGGER.debug("deCONZ config %s", deconz_config)
    from pydeconz import DeconzSession
    websession = async_get_clientsession(hass)
    deconz = DeconzSession(hass.loop, websession, **deconz_config)
    result = await deconz.async_load_parameters()
    if result is False:
        _LOGGER.error("Failed to communicate with deCONZ")
        return False

    hass.data[DOMAIN] = deconz
    hass.data[DATA_DECONZ_ID] = {}

    for component in ['binary_sensor', 'light', 'scene', 'sensor']:
        hass.async_add_job(discovery.async_load_platform(
            hass, component, DOMAIN, {}, config))
    deconz.start()

    async def async_configure(call):
        """Set attribute of device in deCONZ.

        Field is a string representing a specific device in deCONZ
        e.g. field='/lights/1/state'.
        Entity_id can be used to retrieve the proper field.
        Data is a json object with what data you want to alter
        e.g. data={'on': true}.
        {
            "field": "/lights/1/state",
            "data": {"on": true}
        }
        See Dresden Elektroniks REST API documentation for details:
        http://dresden-elektronik.github.io/deconz-rest-doc/rest/
        """
        field = call.data.get(SERVICE_FIELD)
        entity_id = call.data.get(SERVICE_ENTITY)
        data = call.data.get(SERVICE_DATA)
        deconz = hass.data[DOMAIN]
        if entity_id:
            entities = hass.data.get(DATA_DECONZ_ID)
            if entities:
                field = entities.get(entity_id)
            if field is None:
                _LOGGER.error('Could not find the entity %s', entity_id)
                return
        await deconz.async_put_state(field, data)
    hass.services.async_register(
        DOMAIN, 'configure', async_configure, schema=SERVICE_SCHEMA)

    @callback
    def deconz_shutdown(event):
        """
        Wrap the call to deconz.close.

        Used as an argument to EventBus.async_listen_once - EventBus calls
        this method with the event as the first argument, which should not
        be passed on to deconz.close.
        """
        deconz.close()

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, deconz_shutdown)
    return True