Exemple #1
0
def setup_platform(hass, config, add_entities, discovery_info=None):
    """Find and return myStrom switch."""
    from pymystrom.switch import MyStromPlug, exceptions

    name = config.get(CONF_NAME)
    host = config.get(CONF_HOST)

    try:
        MyStromPlug(host).get_status()
    except exceptions.MyStromConnectionError:
        _LOGGER.error("No route to device: %s", host)
        raise PlatformNotReady()

    add_entities([MyStromSwitch(name, host)])
Exemple #2
0
async def async_setup_platform(hass,
                               config,
                               add_entities,
                               discovery_info=None):
    """Set up a single Sisyphus table."""
    host = discovery_info[CONF_HOST]
    try:
        table_holder = hass.data[DATA_SISYPHUS][host]
        table = await table_holder.get_table()
    except aiohttp.ClientError:
        raise PlatformNotReady()

    add_entities([SisyphusLight(table_holder.name, table)],
                 update_before_add=True)
Exemple #3
0
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
    """Set up the Tibber sensor."""
    if discovery_info is None:
        return

    tibber_connection = hass.data.get(TIBBER_DOMAIN)

    dev = []
    for home in tibber_connection.get_homes(only_active=False):
        try:
            await home.update_info()
        except asyncio.TimeoutError as err:
            _LOGGER.error("Timeout connecting to Tibber home: %s ", err)
            raise PlatformNotReady()
        except aiohttp.ClientError as err:
            _LOGGER.error("Error connecting to Tibber home: %s ", err)
            raise PlatformNotReady()
        if home.has_active_subscription:
            dev.append(TibberSensorElPrice(home))
        if home.has_real_time_consumption:
            dev.append(TibberSensorRT(home))

    async_add_entities(dev, True)
Exemple #4
0
async def async_setup_platform(hass: HomeAssistant,
                               config,
                               async_add_entities,
                               discovery_info=None):
    """Set up DLNA DMR platform."""
    if config.get(CONF_URL) is not None:
        url = config[CONF_URL]
        name = config.get(CONF_NAME)
    elif discovery_info is not None:
        url = discovery_info['ssdp_description']
        name = discovery_info.get('name')

    if DLNA_DMR_DATA not in hass.data:
        hass.data[DLNA_DMR_DATA] = {}

    if 'lock' not in hass.data[DLNA_DMR_DATA]:
        hass.data[DLNA_DMR_DATA]['lock'] = asyncio.Lock()

    # build upnp/aiohttp requester
    from async_upnp_client.aiohttp import AiohttpSessionRequester
    session = async_get_clientsession(hass)
    requester = AiohttpSessionRequester(session, True)

    # ensure event handler has been started
    with await hass.data[DLNA_DMR_DATA]['lock']:
        server_host = config.get(CONF_LISTEN_IP)
        if server_host is None:
            server_host = get_local_ip()
        server_port = config.get(CONF_LISTEN_PORT, DEFAULT_LISTEN_PORT)
        event_handler = await async_start_event_handler(hass,
                                                        server_host,
                                                        server_port,
                                                        requester)

    # create upnp device
    from async_upnp_client import UpnpFactory
    factory = UpnpFactory(requester, disable_state_variable_validation=True)
    try:
        upnp_device = await factory.async_create_device(url)
    except (asyncio.TimeoutError, aiohttp.ClientError):
        raise PlatformNotReady()

    # wrap with DmrDevice
    from async_upnp_client.dlna import DmrDevice
    dlna_device = DmrDevice(upnp_device, event_handler)

    # create our own device
    device = DlnaDmrDevice(dlna_device, name)
    _LOGGER.debug("Adding device: %s", device)
    async_add_entities([device], True)
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the cartridge sensor."""
    host = config.get(CONF_HOST)

    api = EpsonPrinterAPI(host)
    if not api.available:
        raise PlatformNotReady()

    sensors = [
        EpsonPrinterCartridge(api, description) for description in SENSOR_TYPES
        if description.key in config[CONF_MONITORED_CONDITIONS]
    ]

    add_devices(sensors, True)
Exemple #6
0
async def async_setup_platform(hass, config, add_devices_callback, discovery_info=None):
    """Setup."""
    stops = config.get(CONF_STOPS)
    firstnext = config.get(CONF_FIRST_NEXT)
    dev = []
    for stopid in stops:
        api = WienerlinienAPI(async_create_clientsession(hass), hass.loop, stopid)
        data = await api.get_json()
        try:
            name = data["data"]["monitors"][0]["locationStop"]["properties"]["title"]
        except Exception:
            raise PlatformNotReady()
        dev.append(WienerlinienSensor(api, name, firstnext))
    add_devices_callback(dev, True)
Exemple #7
0
async def async_setup_platform(
    hass: HomeAssistant,
    config: ConfigType,
    async_add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType | None = None,
) -> None:
    """Set up the template button."""
    if not discovery_info or "coordinator" in discovery_info:
        raise PlatformNotReady(
            "The template button platform doesn't support trigger entities")

    async_add_entities(await
                       _async_create_entities(hass, discovery_info["entities"],
                                              discovery_info["unique_id"]))
Exemple #8
0
def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the InfluxDB component."""
    try:
        influx = get_influx_connection(config, test_read=True)
    except ConnectionError as exc:
        _LOGGER.error(exc)
        raise PlatformNotReady()

    queries = config[CONF_QUERIES_FLUX if CONF_QUERIES_FLUX in
                     config else CONF_QUERIES]
    entities = [InfluxSensor(hass, influx, query) for query in queries]
    add_entities(entities, update_before_add=True)

    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, lambda _: influx.close())
async def test_setup_entry_platform_not_ready_from_exception(hass, caplog):
    """Test when an entry is not ready yet that includes the causing exception string."""
    original_exception = HomeAssistantError("The device dropped the connection")
    platform_exception = PlatformNotReady()
    platform_exception.__cause__ = original_exception

    async_setup_entry = Mock(side_effect=platform_exception)
    platform = MockPlatform(async_setup_entry=async_setup_entry)
    config_entry = MockConfigEntry()
    ent_platform = MockEntityPlatform(
        hass, platform_name=config_entry.domain, platform=platform
    )

    with patch.object(entity_platform, "async_call_later") as mock_call_later:
        assert not await ent_platform.async_setup_entry(config_entry)

    full_name = f"{ent_platform.domain}.{config_entry.domain}"
    assert full_name not in hass.config.components
    assert len(async_setup_entry.mock_calls) == 1

    assert "Platform test not ready yet" in caplog.text
    assert "The device dropped the connection" in caplog.text
    assert len(mock_call_later.mock_calls) == 1
Exemple #10
0
async def async_setup_entry(
    hass: HomeAssistant,
    config_entry: ConfigEntry,
    async_add_entities: AddEntitiesCallback,
) -> None:
    """Set up the Aladdin Connect platform."""
    acc = hass.data[DOMAIN][config_entry.entry_id]
    doors = await hass.async_add_executor_job(acc.get_doors)

    if doors is None:
        raise PlatformNotReady("Error from Aladdin Connect getting doors")
    async_add_entities(
        (AladdinDevice(acc, door) for door in doors),
        update_before_add=True,
    )
Exemple #11
0
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the cartridge sensor."""
    host = config.get(CONF_HOST)

    from epsonprinter_pkg.epsonprinterapi import EpsonPrinterAPI
    api = EpsonPrinterAPI(host)
    if not api.available:
        raise PlatformNotReady()

    sensors = [
        EpsonPrinterCartridge(api, condition)
        for condition in config[CONF_MONITORED_CONDITIONS]
    ]

    add_devices(sensors, True)
Exemple #12
0
async def async_setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup component."""
    import tibber
    tibber_connection = tibber.Tibber(config.get(CONF_ACCESS_TOKEN),
                                      websession=async_get_clientsession(hass))
    try:
        await tibber_connection.update_info()
        dev = []
        for tibber_home in tibber_connection.get_homes():
            await tibber_home.update_info()
            if 'hamretunet' in tibber_home.info['viewer']['home'][
                    'appNickname'].lower():
                break
    except (asyncio.TimeoutError, aiohttp.ClientError):
        raise PlatformNotReady()
    add_devices([vv(tibber_home, hass)])
async def test_data_manager_call(data_manager: WithingsDataManager) -> None:
    """Test method."""
    # Not authenticated 1.
    test_function = MagicMock(side_effect=UnauthorizedException(401))
    with pytest.raises(NotAuthenticatedError):
        await data_manager.call(test_function)

    # Not authenticated 2.
    test_function = MagicMock(side_effect=TimeoutException(522))
    with pytest.raises(PlatformNotReady):
        await data_manager.call(test_function)

    # Service error.
    test_function = MagicMock(side_effect=PlatformNotReady())
    with pytest.raises(PlatformNotReady):
        await data_manager.call(test_function)
Exemple #14
0
async def async_setup_platform(hass,
                               config,
                               async_add_entities,
                               discovery_info=None):
    """Set up the myStrom switch/plug integration."""
    name = config.get(CONF_NAME)
    host = config.get(CONF_HOST)

    try:
        plug = _MyStromSwitch(host)
        await plug.get_state()
    except MyStromConnectionError:
        _LOGGER.error("No route to myStrom plug: %s", host)
        raise PlatformNotReady()

    async_add_entities([MyStromSwitch(plug, name)])
async def async_setup_platform(hass,
                               config,
                               add_devices_callback,
                               discovery_info=None):
    """Setup."""
    serial_no = config.get(CONF_SERIAL_NO)
    dev = []
    api = CallAPI(async_create_clientsession(hass), hass.loop, serial_no)
    data = await api.update()

    if 'code' not in data or data['code'] != 200:
        raise PlatformNotReady()

    for variable in config[CONF_DISPLAY_OPTIONS]:
        dev.append(SiemensSensor(api, variable))

    add_devices_callback(dev, True)
Exemple #16
0
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
    """Set up the myStrom light integration."""
    host = config.get(CONF_HOST)
    mac = config.get(CONF_MAC)
    name = config.get(CONF_NAME)

    bulb = MyStromBulb(host, mac)
    try:
        await bulb.get_state()
        if bulb.bulb_type != "rgblamp":
            _LOGGER.error("Device %s (%s) is not a myStrom bulb", host, mac)
            return
    except MyStromConnectionError as err:
        _LOGGER.warning("No route to myStrom bulb: %s", host)
        raise PlatformNotReady() from err

    async_add_entities([MyStromLight(bulb, name, mac)], True)
Exemple #17
0
async def async_setup_platform(
    hass: HomeAssistant,
    config: ConfigType,
    add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType | None = None,
) -> None:
    """Set up a single Sisyphus table."""
    if not discovery_info:
        return
    host = discovery_info[CONF_HOST]
    try:
        table_holder = hass.data[DATA_SISYPHUS][host]
        table = await table_holder.get_table()
    except aiohttp.ClientError as err:
        raise PlatformNotReady() from err

    add_entities([SisyphusLight(table_holder.name, table)], update_before_add=True)
async def test_data_manager_call(data_manager):
    """Test method."""

    # Token refreshed.
    def hello_func():
        return "HELLO2"

    function = MagicMock(side_effect=[TokenUpdated("my_token"), hello_func()])
    result = await data_manager.call(function)
    assert result == "HELLO2"
    assert function.call_count == 2

    # Too many token refreshes.
    function = MagicMock(
        side_effect=[TokenUpdated("my_token"),
                     TokenUpdated("my_token")])
    try:
        result = await data_manager.call(function)
        assert False, "This should not have ran."
    except ServiceError:
        assert True
    assert function.call_count == 2

    # Not authenticated 1.
    test_function = MagicMock(side_effect=MissingTokenError("Error Code 401"))
    try:
        result = await data_manager.call(test_function)
        assert False, "An exception should have been thrown."
    except NotAuthenticatedError:
        assert True

    # Not authenticated 2.
    test_function = MagicMock(side_effect=Exception("Error Code 401"))
    try:
        result = await data_manager.call(test_function)
        assert False, "An exception should have been thrown."
    except NotAuthenticatedError:
        assert True

    # Service error.
    test_function = MagicMock(side_effect=PlatformNotReady())
    try:
        result = await data_manager.call(test_function)
        assert False, "An exception should have been thrown."
    except PlatformNotReady:
        assert True
Exemple #19
0
async def async_setup_platform(hass, config, async_add_entities,
                               discovery_info=None):
    """Set up the Tibber sensor."""
    import tibber
    tibber_connection = tibber.Tibber(config[CONF_ACCESS_TOKEN],
                                      websession=async_get_clientsession(hass))

    try:
        await tibber_connection.update_info()
        dev = []
        for home in tibber_connection.get_homes():
            await home.update_info()
            dev.append(TibberSensor(home))
    except (asyncio.TimeoutError, aiohttp.ClientError):
        raise PlatformNotReady()

    async_add_entities(dev, True)
async def async_setup_platform(hass: HomeAssistant,
                               config,
                               async_add_entities,
                               discovery_info=None):
    """Set up DLNA DMR platform."""
    if config.get(CONF_URL) is not None:
        url = config[CONF_URL]
        name = config.get(CONF_NAME)
    elif discovery_info is not None:
        url = discovery_info["ssdp_description"]
        name = discovery_info.get("name")

    if DLNA_DMR_DATA not in hass.data:
        hass.data[DLNA_DMR_DATA] = {}

    if "lock" not in hass.data[DLNA_DMR_DATA]:
        hass.data[DLNA_DMR_DATA]["lock"] = asyncio.Lock()

    # build upnp/aiohttp requester
    session = async_get_clientsession(hass)
    requester = AiohttpSessionRequester(session, True)

    # ensure event handler has been started
    async with hass.data[DLNA_DMR_DATA]["lock"]:
        server_host = config.get(CONF_LISTEN_IP)
        if server_host is None:
            server_host = await async_get_source_ip(hass, PUBLIC_TARGET_IP)
        server_port = config.get(CONF_LISTEN_PORT, DEFAULT_LISTEN_PORT)
        callback_url_override = config.get(CONF_CALLBACK_URL_OVERRIDE)
        event_handler = await async_start_event_handler(
            hass, server_host, server_port, requester, callback_url_override)

    # create upnp device
    factory = UpnpFactory(requester, non_strict=True)
    try:
        upnp_device = await factory.async_create_device(url)
    except (asyncio.TimeoutError, aiohttp.ClientError) as err:
        raise PlatformNotReady() from err

    # wrap with DmrDevice
    dlna_device = DmrDevice(upnp_device, event_handler)

    # create our own device
    device = DlnaDmrDevice(dlna_device, name)
    _LOGGER.debug("Adding device: %s", device)
    async_add_entities([device], True)
Exemple #21
0
    def call(self, function, is_first_call=True, throttle_domain=None):
        """Call an api method and handle the result."""
        throttle_data = self.get_throttle_data(throttle_domain)

        should_throttle = throttle_domain and \
            throttle_data and \
            not throttle_data.is_expired()

        try:
            if should_throttle:
                _LOGGER.debug("Throttling call for domain: %s",
                              throttle_domain)
                result = throttle_data.data
            else:
                _LOGGER.debug("Running call.")
                result = function()

                # Update throttle data.
                self.set_throttle_data(
                    throttle_domain,
                    ThrottleData(self.get_throttle_interval(), result))

            WithingsDataManager.print_service_available()
            return result

        except TokenUpdated:
            WithingsDataManager.print_service_available()
            if not is_first_call:
                raise ServiceError(
                    "Stuck in a token update loop. This should never happen")

            _LOGGER.info("Token updated, re-running call.")
            return self.call(function, False)

        except MissingTokenError as ex:
            raise NotAuthenticatedError(ex)

        except Exception as ex:  # pylint: disable=broad-except
            # Service error, probably not authenticated.
            if NOT_AUTHENTICATED_ERROR.match(str(ex)):
                raise NotAuthenticatedError(ex)

            # Probably a network error.
            WithingsDataManager.print_service_unavailable()
            raise PlatformNotReady(ex)
def setup_platform(
    hass: HomeAssistant,
    config: ConfigType,
    add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType | None = None,
) -> None:
    """Set up the departure sensor."""

    nsapi = ns_api.NSAPI(config[CONF_API_KEY])

    try:
        stations = nsapi.get_stations()
    except (
            requests.exceptions.ConnectionError,
            requests.exceptions.HTTPError,
    ) as error:
        _LOGGER.error("Could not connect to the internet: %s", error)
        raise PlatformNotReady() from error
    except RequestParametersError as error:
        _LOGGER.error(
            "Could not fetch stations, please check configuration: %s", error)
        return

    sensors = []
    for departure in config.get(CONF_ROUTES, {}):
        if not valid_stations(
                stations,
            [
                departure.get(CONF_FROM),
                departure.get(CONF_VIA),
                departure.get(CONF_TO)
            ],
        ):
            continue
        sensors.append(
            NSDepartureSensor(
                nsapi,
                departure.get(CONF_NAME),
                departure.get(CONF_FROM),
                departure.get(CONF_TO),
                departure.get(CONF_VIA),
                departure.get(CONF_TIME),
            ))
    if sensors:
        add_entities(sensors, True)
Exemple #23
0
async def async_setup_platform(
    hass: HomeAssistant,
    config: ConfigType,
    async_add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType | None = None,
) -> None:
    """Set up the myStrom switch/plug integration."""
    name = config.get(CONF_NAME)
    host = config.get(CONF_HOST)

    try:
        plug = _MyStromSwitch(host)
        await plug.get_state()
    except MyStromConnectionError as err:
        _LOGGER.error("No route to myStrom plug: %s", host)
        raise PlatformNotReady() from err

    async_add_entities([MyStromSwitch(plug, name)])
Exemple #24
0
async def async_setup_platform(hass: HomeAssistant,
                               config,
                               async_add_entities,
                               discovery_info=None):
    """Set up the Uptime Robot binary_sensors."""
    uptime_robot_api = UptimeRobot()
    api_key = config[CONF_API_KEY]

    def api_wrapper():
        return uptime_robot_api.getMonitors(api_key)

    async def async_update_data():
        """Fetch data from API UptimeRobot API."""
        async with async_timeout.timeout(10):
            monitors = await hass.async_add_executor_job(api_wrapper)
            if not monitors or monitors.get("stat") != "ok":
                raise UpdateFailed("Error communicating with Uptime Robot API")
            return monitors

    coordinator = DataUpdateCoordinator(
        hass,
        _LOGGER,
        name="uptimerobot",
        update_method=async_update_data,
        update_interval=timedelta(seconds=60),
    )

    await coordinator.async_refresh()

    if not coordinator.data or coordinator.data.get("stat") != "ok":
        _LOGGER.error("Error connecting to Uptime Robot")
        raise PlatformNotReady()

    async_add_entities([
        UptimeRobotBinarySensor(
            coordinator,
            BinarySensorEntityDescription(
                key=monitor["id"],
                name=monitor["friendly_name"],
                device_class=DEVICE_CLASS_CONNECTIVITY,
            ),
            target=monitor["url"],
        ) for monitor in coordinator.data["monitors"]
    ], )
Exemple #25
0
async def test_setup_entry_platform_not_ready_with_message(hass, caplog):
    """Test when an entry is not ready yet that includes a message."""
    async_setup_entry = Mock(side_effect=PlatformNotReady("lp0 on fire"))
    platform = MockPlatform(async_setup_entry=async_setup_entry)
    config_entry = MockConfigEntry()
    ent_platform = MockEntityPlatform(hass,
                                      platform_name=config_entry.domain,
                                      platform=platform)

    with patch.object(entity_platform, "async_call_later") as mock_call_later:
        assert not await ent_platform.async_setup_entry(config_entry)

    full_name = f"{ent_platform.domain}.{config_entry.domain}"
    assert full_name not in hass.config.components
    assert len(async_setup_entry.mock_calls) == 1

    assert "Platform test not ready yet" in caplog.text
    assert "lp0 on fire" in caplog.text
    assert len(mock_call_later.mock_calls) == 1
Exemple #26
0
async def async_setup_platform(hass,
                               config,
                               async_add_entities,
                               discovery_info=None):
    """Setups the ferienapidotde platform."""
    _, _ = hass, discovery_info  # Fake usage
    state_code = config.get(CONF_STATE)
    name = config.get(CONF_NAME)

    try:
        data_object = VacationData(state_code)
        await data_object.async_update()
    except Exception:
        import traceback

        _LOGGER.warning(traceback.format_exc())
        raise PlatformNotReady()

    async_add_entities([VacationSensor(name, data_object)], True)
def setup_platform(
    hass: HomeAssistant,
    config: ConfigType,
    add_devices: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType | None = None,
) -> None:
    """Set up the cartridge sensor."""
    host = config.get(CONF_HOST)

    api = EpsonPrinterAPI(host)
    if not api.available:
        raise PlatformNotReady()

    sensors = [
        EpsonPrinterCartridge(api, description) for description in SENSOR_TYPES
        if description.key in config[CONF_MONITORED_CONDITIONS]
    ]

    add_devices(sensors, True)
Exemple #28
0
    async def _get_latest_video_url(self):
        """Retrieve the latest video file from the customized Yi FTP server."""
        from aioftp import Client, StatusCodeError

        ftp = Client()
        try:
            await ftp.connect(self.host)
            await ftp.login(self.user, self.passwd)
        except (ConnectionRefusedError, StatusCodeError) as err:
            raise PlatformNotReady(err)

        try:
            await ftp.change_directory(self.path)
            dirs = []
            for path, attrs in await ftp.list():
                if attrs["type"] == "dir" and "." not in str(path):
                    dirs.append(path)
            latest_dir = dirs[-1]
            await ftp.change_directory(latest_dir)

            videos = []
            for path, _ in await ftp.list():
                videos.append(path)
            if not videos:
                _LOGGER.info('Video folder "%s" empty; delaying', latest_dir)
                return None

            await ftp.quit()
            self._is_on = True
            return "ftp://{0}:{1}@{2}:{3}{4}/{5}/{6}".format(
                self.user,
                self.passwd,
                self.host,
                self.port,
                self.path,
                latest_dir,
                videos[-1],
            )
        except (ConnectionRefusedError, StatusCodeError) as err:
            _LOGGER.error("Error while fetching video: %s", err)
            self._is_on = False
            return None
async def async_setup(hass, config):
    """Setup the Meross manager, register the event handler (EventHandlerWrapper) and starts it and"""
    try:
        conf = config.get(DOMAIN)

        # The following call can cause am UnauthorizedException if bad login credentials are provided
        # or if a network exception occurs.
        manager = MerossManager(meross_email=conf.get(CONF_USERNAME),
                                meross_password=conf.get(CONF_PASSWORD))

        wrapper = EventHandlerWrapper(hass, conf)

        manager.register_event_handler(wrapper.event_handler)

        hass.data[DOMAIN] = {}
        hass.data[DOMAIN][MANAGER] = manager
        hass.data[DOMAIN][SENSORS] = {}

        # Setup a set for keeping track of enrolled devices
        hass.data[DOMAIN][ENROLLED_DEVICES] = set()

        _LOGGER.info("Starting meross manager")
        manager.start()

        return True

    except UnauthorizedException as e:
        notify_error(
            hass, "http_connection", "Meross Cloud",
            "Could not connect to the Meross cloud. Please check"
            " your internet connection and your Meross credentials")
        _LOGGER.error(
            "Your Meross login credentials are invalid or the network could not be reached "
            "at the moment.")

        raise PlatformNotReady()

    except Exception as e:
        _LOGGER.exception(
            "An exception occurred while setting up the meross manager.")
        return False
Exemple #30
0
async def async_setup_platform(hass, config, async_add_entities,
                               discovery_info=None):
    """Set up the Tibber sensor."""
    if discovery_info is None:
        _LOGGER.error("Tibber sensor configuration has changed."
                      " Check https://home-assistant.io/components/tibber/")
        return

    tibber_connection = hass.data.get(TIBBER_DOMAIN)

    try:
        dev = []
        for home in tibber_connection.get_homes():
            await home.update_info()
            dev.append(TibberSensorElPrice(home))
            if home.has_real_time_consumption:
                dev.append(TibberSensorRT(home))
    except (asyncio.TimeoutError, aiohttp.ClientError):
        raise PlatformNotReady()

    async_add_entities(dev, True)