async def _async_check_and_create(self, step_id, user_input):
        """Validate input, proceed to create."""
        user_input[CONF_URL] = url_normalize(
            user_input[CONF_URL], default_scheme="http"
        )
        if "://" not in user_input[CONF_URL]:
            return await self._async_show_form(
                step_id=step_id, user_input=user_input, errors={CONF_URL: "invalid_url"}
            )

        # If we don't have a unique id, copy one from existing entry with same URL
        if not self.unique_id:
            for existing_entry in (
                x
                for x in self._async_current_entries()
                if x.data[CONF_URL] == user_input[CONF_URL] and x.unique_id
            ):
                await self.async_set_unique_id(existing_entry.unique_id)
                break

        session = aiohttp_client.async_get_clientsession(self.hass)
        printer = SyncThru(
            user_input[CONF_URL], session, connection_mode=ConnectionMode.API
        )
        errors = {}
        try:
            await printer.update()
            if not user_input.get(CONF_NAME):
                user_input[CONF_NAME] = DEFAULT_NAME_TEMPLATE.format(
                    printer.model() or DEFAULT_MODEL
                )
        except SyncThruAPINotSupported:
            errors[CONF_URL] = "syncthru_not_supported"
        else:
            if printer.is_unknown_state():
                errors[CONF_URL] = "unknown_state"

        if errors:
            return await self._async_show_form(
                step_id=step_id, user_input=user_input, errors=errors
            )

        return self.async_create_entry(
            title=user_input.get(CONF_NAME),
            data=user_input,
        )
Exemple #2
0
async def async_setup_entry(hass, config_entry, async_add_entities):
    """Set up from config entry."""

    session = aiohttp_client.async_get_clientsession(hass)

    printer = SyncThru(config_entry.data[CONF_URL], session)
    # Test if the discovered device actually is a syncthru printer
    # and fetch the available toner/drum/etc
    try:
        # No error is thrown when the device is off
        # (only after user added it manually)
        # therefore additional catches are inside the Sensor below
        await printer.update()
        supp_toner = printer.toner_status(filter_supported=True)
        supp_drum = printer.drum_status(filter_supported=True)
        supp_tray = printer.input_tray_status(filter_supported=True)
        supp_output_tray = printer.output_tray_status()
    except ValueError as ex:
        raise SyncThruNotSupported from ex
    else:
        if printer.is_unknown_state():
            raise PlatformNotReady

    name = config_entry.data[CONF_NAME]
    devices = [SyncThruMainSensor(printer, name)]

    for key in supp_toner:
        devices.append(SyncThruTonerSensor(printer, name, key))
    for key in supp_drum:
        devices.append(SyncThruDrumSensor(printer, name, key))
    for key in supp_tray:
        devices.append(SyncThruInputTraySensor(printer, name, key))
    for key in supp_output_tray:
        devices.append(SyncThruOutputTraySensor(printer, name, key))

    async_add_entities(devices, True)
Exemple #3
0
class NonSyncthruWebTest(unittest.TestCase):

    server = None
    server_control = None  # type: Server
    port = 0
    url = "http://localhost:80"
    syncthru = None  # type: SyncThru

    def test_no_syncthru(self) -> None:
        """Test that an error is thrown when no syncthru is supported"""
        # Create an arbitrary subclass of TCP Server as the server to be started
        # Here, it is an Simple HTTP file serving server
        handler = SyncThruRequestHandler

        max_retries = 10
        r = 0
        while not self.server:
            try:
                # Connect to any open port
                self.server = SyncThruServer((ADDRESS, 0), handler)
            except OSError:
                if r < max_retries:
                    r += 1
                else:
                    raise
                time.sleep(1)

        self.server_control = Server(self.server)
        self.port = self.server_control.get_port()
        self.url = "{}:{}".format(ADDRESS, self.port)
        # Start test server before running any tests
        self.server_control.start_server()

        # Block server to make sure we get "no support"
        self.server.set_blocked()

        try:

            async def fetch() -> None:
                async with aiohttp.ClientSession() as session:
                    self.syncthru = SyncThru(
                        self.url, session, connection_mode=ConnectionMode.API
                    )
                    await self.syncthru.update()

            loop = asyncio.get_event_loop()
            loop.run_until_complete(fetch())
            self.fail(
                "No error thrown when noticing that the host does not support Syncthru"
            )
        except SyncThruAPINotSupported:
            pass

    def test_offline_unknown(self) -> None:
        """Test that nothing is returned when syncthru is offline"""

        async def fetch() -> None:
            async with aiohttp.ClientSession() as session:
                self.syncthru = SyncThru(
                    self.url, session, connection_mode=ConnectionMode.API
                )
                await self.syncthru.update()

        loop = asyncio.get_event_loop()
        loop.run_until_complete(fetch())
        self.assertFalse(self.syncthru.is_online())
        self.assertTrue(self.syncthru.is_unknown_state())