async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): """Set up Nest from a config entry with dispatch between old/new flows.""" if DATA_SDM not in entry.data: return await async_setup_legacy_entry(hass, entry) implementation = ( await config_entry_oauth2_flow.async_get_config_entry_implementation( hass, entry)) config = hass.data[DOMAIN][DATA_NEST_CONFIG] session = config_entry_oauth2_flow.OAuth2Session(hass, entry, implementation) auth = api.AsyncConfigEntryAuth( aiohttp_client.async_get_clientsession(hass), session, API_URL, ) subscriber = GoogleNestSubscriber(auth, config[CONF_PROJECT_ID], config[CONF_SUBSCRIBER_ID]) subscriber.set_update_callback(SignalUpdateCallback(hass)) asyncio.create_task(subscriber.start_async()) hass.data[DOMAIN][entry.entry_id] = subscriber for component in PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) return True
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): """Set up Nest from a config entry with dispatch between old/new flows.""" if DATA_SDM not in entry.data: return await async_setup_legacy_entry(hass, entry) implementation = ( await config_entry_oauth2_flow.async_get_config_entry_implementation( hass, entry ) ) config = hass.data[DOMAIN][DATA_NEST_CONFIG] session = config_entry_oauth2_flow.OAuth2Session(hass, entry, implementation) auth = api.AsyncConfigEntryAuth( aiohttp_client.async_get_clientsession(hass), session, config[CONF_CLIENT_ID], config[CONF_CLIENT_SECRET], ) subscriber = GoogleNestSubscriber( auth, config[CONF_PROJECT_ID], config[CONF_SUBSCRIBER_ID] ) callback = SignalUpdateCallback(hass) subscriber.set_update_callback(callback.async_handle_event) try: await subscriber.start_async() except AuthException as err: _LOGGER.debug("Subscriber authentication error: %s", err) raise ConfigEntryAuthFailed from err except ConfigurationException as err: _LOGGER.error("Configuration error: %s", err) subscriber.stop_async() return False except GoogleNestException as err: if DATA_NEST_UNAVAILABLE not in hass.data[DOMAIN]: _LOGGER.error("Subscriber error: %s", err) hass.data[DOMAIN][DATA_NEST_UNAVAILABLE] = True subscriber.stop_async() raise ConfigEntryNotReady from err try: await subscriber.async_get_device_manager() except GoogleNestException as err: if DATA_NEST_UNAVAILABLE not in hass.data[DOMAIN]: _LOGGER.error("Device manager error: %s", err) hass.data[DOMAIN][DATA_NEST_UNAVAILABLE] = True subscriber.stop_async() raise ConfigEntryNotReady from err hass.data[DOMAIN].pop(DATA_NEST_UNAVAILABLE, None) hass.data[DOMAIN][DATA_SUBSCRIBER] = subscriber hass.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def test_subscribe_device_manager_init(aiohttp_server) -> None: subscriber_factory = FakeSubscriberFactory() r = Recorder() handler = NewDeviceHandler( r, [ { "name": "enterprises/project-id1/devices/device-id1", "type": "sdm.devices.types.device-type1", "traits": {}, "parentRelations": [], }, { "name": "enterprises/project-id1/devices/device-id2", "type": "sdm.devices.types.device-type2", "traits": {}, "parentRelations": [], }, ], ) app = aiohttp.web.Application() app.router.add_get("/enterprises/project-id1/devices", handler) app.router.add_get( "/enterprises/project-id1/structures", NewStructureHandler( r, [ { "name": "enterprises/project-id1/structures/structure-id1", } ], ), ) server = await aiohttp_server(app) async with aiohttp.test_utils.TestClient(server) as client: subscriber = GoogleNestSubscriber( FakeAuth(client), PROJECT_ID, SUBSCRIBER_ID, subscriber_factory ) start_async = subscriber.start_async() device_manager = await subscriber.async_get_device_manager() await start_async devices = device_manager.devices assert "enterprises/project-id1/devices/device-id1" in devices assert ( "sdm.devices.types.device-type1" == devices["enterprises/project-id1/devices/device-id1"].type ) assert "enterprises/project-id1/devices/device-id2" in devices assert ( "sdm.devices.types.device-type2" == devices["enterprises/project-id1/devices/device-id2"].type )
async def test_subscriber_watchdog(aiohttp_server) -> None: # Waits for the test to wake up the background thread event1 = asyncio.Event() async def task1(): print("Task1") await event1.wait() return event2 = asyncio.Event() async def task2(): print("Task2") event2.set() subscriber_factory = FakeSubscriberFactory(tasks=[task1, task2]) r = Recorder() handler = NewDeviceHandler( r, [], ) app = aiohttp.web.Application() app.router.add_get("/enterprises/project-id1/devices", NewDeviceHandler(r, [])) app.router.add_get( "/enterprises/project-id1/structures", NewStructureHandler(r, []), ) server = await aiohttp_server(app) async with aiohttp.test_utils.TestClient(server) as client: subscriber = GoogleNestSubscriber( FakeAuth(client), PROJECT_ID, SUBSCRIBER_ID, subscriber_factory=subscriber_factory, watchdog_delay=0.1, ) assert len(subscriber_factory.tasks) == 2 await subscriber.start_async() assert len(subscriber_factory.tasks) == 1 # Wait for the subscriber to start, then shut it down event1.set() # Block until the new subscriber starts, and notifies this to wake up await event2.wait() assert len(subscriber_factory.tasks) == 0 subscriber.stop_async()
def new_subscriber_with_token( hass: HomeAssistant, access_token: str, project_id: str, subscriber_id: str, ) -> GoogleNestSubscriber: """Create a GoogleNestSubscriber with an access token.""" return GoogleNestSubscriber( AccessTokenAuthImpl( aiohttp_client.async_get_clientsession(hass), access_token, ), project_id, subscriber_id, )
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): """Set up Nest from a config entry with dispatch between old/new flows.""" if DATA_SDM not in entry.data: return await async_setup_legacy_entry(hass, entry) implementation = ( await config_entry_oauth2_flow.async_get_config_entry_implementation( hass, entry)) config = hass.data[DOMAIN][DATA_NEST_CONFIG] session = config_entry_oauth2_flow.OAuth2Session(hass, entry, implementation) auth = api.AsyncConfigEntryAuth( aiohttp_client.async_get_clientsession(hass), session, API_URL, ) subscriber = GoogleNestSubscriber(auth, config[CONF_PROJECT_ID], config[CONF_SUBSCRIBER_ID]) subscriber.set_update_callback(SignalUpdateCallback(hass)) try: await subscriber.start_async() except GoogleNestException as err: _LOGGER.error("Subscriber error: %s", err) subscriber.stop_async() raise ConfigEntryNotReady from err try: await subscriber.async_get_device_manager() except GoogleNestException as err: _LOGGER.error("Device Manager error: %s", err) subscriber.stop_async() raise ConfigEntryNotReady from err hass.data[DOMAIN][DATA_SUBSCRIBER] = subscriber for component in PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) return True
async def new_subscriber_with_impl( hass: HomeAssistant, entry: ConfigEntry, subscriber_id: str, implementation: config_entry_oauth2_flow.AbstractOAuth2Implementation, ) -> GoogleNestSubscriber: """Create a GoogleNestSubscriber, used during ConfigFlow.""" config = hass.data[DOMAIN][DATA_NEST_CONFIG] session = config_entry_oauth2_flow.OAuth2Session(hass, entry, implementation) auth = AsyncConfigEntryAuth( aiohttp_client.async_get_clientsession(hass), session, config[CONF_CLIENT_ID], config[CONF_CLIENT_SECRET], ) return GoogleNestSubscriber(auth, config[CONF_PROJECT_ID], subscriber_id)
async def test_subscribe_update_trait(aiohttp_server) -> None: subscriber_factory = FakeSubscriberFactory() r = Recorder() handler = NewDeviceHandler( r, [{ "name": "enterprises/project-id1/devices/device-id1", "type": "sdm.devices.types.device-type1", "traits": { "sdm.devices.traits.Connectivity": { "status": "ONLINE", }, }, "parentRelations": [], }], ) app = aiohttp.web.Application() app.router.add_get("/enterprises/project-id1/devices", handler) app.router.add_get( "/enterprises/project-id1/structures", NewStructureHandler( r, [{ "name": "enterprises/project-id1/structures/structure-id1", }], ), ) server = await aiohttp_server(app) async with aiohttp.test_utils.TestClient(server) as client: subscriber = GoogleNestSubscriber(FakeAuth(client), PROJECT_ID, SUBSCRIBER_ID, subscriber_factory) await subscriber.start_async() device_manager = await subscriber.async_get_device_manager() devices = device_manager.devices assert "enterprises/project-id1/devices/device-id1" in devices device = devices["enterprises/project-id1/devices/device-id1"] trait = device.traits["sdm.devices.traits.Connectivity"] assert "ONLINE" == trait.status event = { "eventId": "6f29332e-5537-47f6-a3f9-840c307340f5", "timestamp": "2020-10-10T07:09:06.851Z", "resourceUpdate": { "name": "enterprises/project-id1/devices/device-id1", "traits": { "sdm.devices.traits.Connectivity": { "status": "OFFLINE", } }, }, "userId": "AVPHwEv75jw4WFshx6-XhBLhotn3r8IXOzCusfSOn5QU", } subscriber_factory.push_event(event) devices = device_manager.devices assert "enterprises/project-id1/devices/device-id1" in devices device = devices["enterprises/project-id1/devices/device-id1"] trait = device.traits["sdm.devices.traits.Connectivity"] assert "OFFLINE" == trait.status subscriber.stop_async()
"""Create a GoogleNestSubscriber.""" implementation = ( await config_entry_oauth2_flow.async_get_config_entry_implementation( hass, entry)) if not isinstance(implementation, config_entry_oauth2_flow.LocalOAuth2Implementation): raise ValueError(f"Unexpected auth implementation {implementation}") if not (subscriber_id := entry.data.get(CONF_SUBSCRIBER_ID)): raise ValueError("Configuration option 'subscriber_id' missing") auth = AsyncConfigEntryAuth( aiohttp_client.async_get_clientsession(hass), config_entry_oauth2_flow.OAuth2Session(hass, entry, implementation), implementation.client_id, implementation.client_secret, ) return GoogleNestSubscriber(auth, entry.data[CONF_PROJECT_ID], subscriber_id) def new_subscriber_with_token( hass: HomeAssistant, access_token: str, project_id: str, subscriber_id: str, ) -> GoogleNestSubscriber: """Create a GoogleNestSubscriber with an access token.""" return GoogleNestSubscriber( AccessTokenAuthImpl( aiohttp_client.async_get_clientsession(hass), access_token, ), project_id,
"""Create a GoogleNestSubscriber.""" implementation = ( await config_entry_oauth2_flow.async_get_config_entry_implementation( hass, entry)) config = hass.data[DOMAIN][DATA_NEST_CONFIG] if not (subscriber_id := entry.data.get(CONF_SUBSCRIBER_ID, config.get(CONF_SUBSCRIBER_ID))): _LOGGER.error("Configuration option 'subscriber_id' required") return None auth = AsyncConfigEntryAuth( aiohttp_client.async_get_clientsession(hass), config_entry_oauth2_flow.OAuth2Session(hass, entry, implementation), config[CONF_CLIENT_ID], config[CONF_CLIENT_SECRET], ) return GoogleNestSubscriber(auth, config[CONF_PROJECT_ID], subscriber_id) def new_subscriber_with_token( hass: HomeAssistant, access_token: str, project_id: str, subscriber_id: str, ) -> GoogleNestSubscriber: """Create a GoogleNestSubscriber with an access token.""" return GoogleNestSubscriber( AccessTokenAuthImpl( aiohttp_client.async_get_clientsession(hass), access_token, ), project_id,