Пример #1
0
def raop_conf_fixture(raop_device, raop_properties):
    service = ManualService("raop_id", Protocol.RAOP,
                            raop_device.get_port(Protocol.RAOP),
                            raop_properties)
    conf = AppleTV("127.0.0.1", "Apple TV")
    conf.add_service(service)
    yield conf
Пример #2
0
async def mock_pairing(event_loop):
    obj = MagicMock()

    service = ManualService(None, Protocol.DMAP, 0, {})
    config = AppleTV("Apple TV", "127.0.0.1")
    config.add_service(service)
    zeroconf = zeroconf_stub.stub(pairing)

    async def _start(pin_code=PIN_CODE,
                     pairing_guid=PAIRING_GUID,
                     name=REMOTE_NAME,
                     addresses=None):
        options = {"zeroconf": zeroconf}
        if pairing_guid:
            options["pairing_guid"] = pairing_guid
        if name:
            options["name"] = name
        if addresses:
            options["addresses"] = addresses

        obj.pairing = pairing.DmapPairingHandler(config, service, await
                                                 http.create_session(),
                                                 event_loop, **options)
        await obj.pairing.begin()
        obj.pairing.pin(pin_code)
        return obj.pairing, zeroconf, service

    yield _start
    await obj.pairing.finish()
    await obj.pairing.close()
Пример #3
0
    async def test_connect_only_companion(self):
        conf = AppleTV(IPv4Address("127.0.0.1"), "Test device")
        conf.add_service(
            CompanionService(self.fake_atv.get_port(Protocol.Companion)))

        with pytest.raises(exceptions.DeviceIdMissingError):
            await pyatv.connect(conf, loop=self.loop)
Пример #4
0
def _manual_device(args):
    config = AppleTV(IPv4Address(args.address), args.name)
    service = ManualService(args.id, args.protocol, args.port, {})
    service.credentials = getattr(args, f"{args.protocol.name.lower()}_credentials")
    service.password = args.raop_password
    config.add_service(service)
    return config
Пример #5
0
 async def setUpAsync(self):
     self.service = CompanionService(self.fake_atv.get_port(Protocol.Companion))
     self.conf = AppleTV(IPv4Address("127.0.0.1"), "Test device")
     self.conf.add_service(
         MrpService("mrp_id", self.fake_atv.get_port(Protocol.MRP))
     )
     self.conf.add_service(self.service)
Пример #6
0
    def setUp(self):
        AioHTTPTestCase.setUp(self)

        self.service = MrpService(CLIENT_IDENTIFIER,
                                  self.fake_atv.get_port(Protocol.MRP))
        self.conf = AppleTV("127.0.0.1", "Apple TV")
        self.conf.add_service(self.service)
Пример #7
0
 async def setUpAsync(self):
     await super().setUpAsync()
     self.conf = AppleTV('127.0.0.1', 'Test device')
     self.conf.add_service(MrpService('mrp_id', self.fake_atv.port))
     self.conf.add_service(
         AirPlayService('airplay_id', self.server.port, DEVICE_CREDENTIALS))
     self.atv = await self.get_connected_device()
Пример #8
0
    def setUp(self):
        AioHTTPTestCase.setUp(self)
        self.pairing = None

        self.service = AirPlayService("airplay_id", port=self.server.port)
        self.conf = AppleTV("127.0.0.1", "Apple TV")
        self.conf.add_service(self.service)
Пример #9
0
    def setUp(self):
        AioHTTPTestCase.setUp(self)
        self.pairing = None

        self.service = AirPlayService('airplay_id', port=self.server.port)
        self.conf = AppleTV('127.0.0.1', 'Apple TV')
        self.conf.add_service(self.service)
Пример #10
0
 async def setUpAsync(self):
     await super().setUpAsync()
     self.conf = AppleTV(IPv4Address("127.0.0.1"), "Test device")
     self.conf.add_service(
         MrpService("mrp_id", self.fake_atv.get_port(Protocol.MRP)))
     self.conf.add_service(
         AirPlayService("airplay_id", self.server.port, DEVICE_CREDENTIALS))
     self.atv = await self.get_connected_device()
Пример #11
0
 async def get_connected_device(self, hsgid):
     self.dmap_service = DmapService("dmapid", hsgid, port=self.server.port)
     self.airplay_service = AirPlayService("airplay_id", self.server.port,
                                           DEVICE_CREDENTIALS)
     self.conf = AppleTV(ipaddress.IPv4Address("127.0.0.1"), "Apple TV")
     self.conf.add_service(self.dmap_service)
     self.conf.add_service(self.airplay_service)
     return await connect(self.conf, self.loop)
Пример #12
0
async def test_connect_only_companion(event_loop):
    service = ManualService(None, Protocol.Companion, 0,
                            {})  # connect never happens
    conf = AppleTV("127.0.0.1", "Apple TV")
    conf.add_service(service)

    with pytest.raises(exceptions.DeviceIdMissingError):
        await pyatv.connect(conf, loop=event_loop)
Пример #13
0
class DmapPairFunctionalTest(AioHTTPTestCase):
    def setUp(self):
        AioHTTPTestCase.setUp(self)
        self.pairing = None

        self.service = DmapService("dmap_id",
                                   PAIRING_GUID,
                                   port=self.server.port)
        self.conf = AppleTV("127.0.0.1", "Apple TV")
        self.conf.add_service(self.service)

        # TODO: currently stubs internal method, should provide stub
        # for netifaces later
        pairing._get_private_ip_addresses = lambda: [
            ipaddress.ip_address("10.0.0.1")
        ]

        self.zeroconf = zeroconf_stub.stub(pyatv.dmap.pairing)

    async def tearDownAsync(self):
        await self.pairing.close()
        await super().tearDownAsync()

    async def get_application(self, loop=None):
        self.fake_atv = FakeAppleTV(HSGID, PAIRING_GUID, SESSION_ID)
        self.usecase = AppleTVUseCases(self.fake_atv)
        return self.fake_atv.app

    async def initiate_pairing(self,
                               name=REMOTE_NAME,
                               pairing_guid=PAIRING_GUID):
        self.usecase.pairing_response(REMOTE_NAME, PAIRINGCODE)

        options = {
            "zeroconf": self.zeroconf,
            "name": name,
            "pairing_guid": pairing_guid,
        }

        self.pairing = await pyatv.pair(self.conf, Protocol.DMAP, self.loop,
                                        **options)

    @unittest_run_loop
    async def test_pairing_with_device(self):
        await self.initiate_pairing()

        self.assertFalse(self.pairing.device_provides_pin)

        await self.pairing.begin()
        self.pairing.pin(PIN_CODE)

        await self.usecase.act_on_bonjour_services(self.zeroconf)

        await self.pairing.finish()

        self.assertTrue(self.pairing.has_paired)
        self.assertEqual(self.service.credentials, PAIRING_GUID)
Пример #14
0
class PairFunctionalTest(AioHTTPTestCase):
    def setUp(self):
        AioHTTPTestCase.setUp(self)
        self.pairing = None

        self.service = AirPlayService('airplay_id', port=self.server.port)
        self.conf = AppleTV('127.0.0.1', 'Apple TV')
        self.conf.add_service(self.service)

    async def tearDownAsync(self):
        await self.pairing.close()
        await super().tearDownAsync()

    async def get_application(self, loop=None):
        self.fake_atv = FakeAirPlayDevice(self)
        self.usecase = AirPlayUseCases(self.fake_atv)
        return self.fake_atv.app

    async def do_pairing(self, pin=DEVICE_PIN):
        self.usecase.airplay_require_authentication()

        self.pairing = await pair(self.conf, Protocol.AirPlay, self.loop)

        self.assertTrue(self.pairing.device_provides_pin)

        await self.pairing.begin()
        if pin:
            self.pairing.pin(pin)

        self.assertFalse(self.pairing.has_paired)

        await self.pairing.finish()
        self.assertTrue(self.pairing.has_paired)
        self.assertEqual(self.service.credentials, DEVICE_CREDENTIALS)

    @unittest_run_loop
    async def test_pairing_exception_invalid_pin(self):
        with self.assertRaises(exceptions.PairingError):
            await self.do_pairing(9999)

    @unittest_run_loop
    async def test_pairing_exception_no_pin(self):
        with self.assertRaises(exceptions.PairingError):
            await self.do_pairing(None)

    @unittest_run_loop
    @patch('os.urandom')
    async def test_pairing_with_device_new_credentials(self, rand_func):
        rand_func.side_effect = predetermined_key
        await self.do_pairing()

    @unittest_run_loop
    async def test_pairing_with_device_existing_credentials(self):
        self.conf.get_service(
            Protocol.AirPlay).credentials = DEVICE_CREDENTIALS
        await self.do_pairing()
Пример #15
0
 async def get_connected_device(self, hsgid):
     self.dmap_service = DmapService('dmap_id',
                                     hsgid,
                                     port=self.server.port)
     self.airplay_service = AirPlayService('airplay_id', self.server.port,
                                           DEVICE_CREDENTIALS)
     self.conf = AppleTV('127.0.0.1', 'Apple TV')
     self.conf.add_service(self.dmap_service)
     self.conf.add_service(self.airplay_service)
     return await pyatv.connect(self.conf, self.loop)
Пример #16
0
    async def test_play_url_no_service(self):
        conf = AppleTV("127.0.0.1", "Apple TV")
        conf.add_service(self.dmap_service)

        atv = await connect(conf, self.loop)

        with self.assertRaises(exceptions.NotSupportedError):
            await atv.stream.play_url("http://123")

        atv.close()
Пример #17
0
 async def setUpAsync(self):
     await super().setUpAsync()
     self.conf = AppleTV(IPv4Address("127.0.0.1"), "Test device")
     self.conf.add_service(
         MrpService("mrp_id", self.fake_atv.get_port(Protocol.MRP)))
     self.conf.add_service(
         CompanionService(
             self.fake_atv.get_port(Protocol.Companion),
             credentials=CLIENT_CREDENTIALS,
         ))
     self.atv = await self.get_connected_device()
Пример #18
0
    def setUp(self):
        AioHTTPTestCase.setUp(self)
        self.pairing = None

        self.service = DmapService("dmap_id",
                                   PAIRING_GUID,
                                   port=self.server.port)
        self.conf = AppleTV("127.0.0.1", "Apple TV")
        self.conf.add_service(self.service)

        self.zeroconf = zeroconf_stub.stub(pyatv.dmap.pairing)
Пример #19
0
class MrpAuthFunctionalTest(AioHTTPTestCase):
    def setUp(self):
        AioHTTPTestCase.setUp(self)

        self.service = MrpService(CLIENT_IDENTIFIER, self.fake_atv.port)
        self.conf = AppleTV('127.0.0.1', 'Apple TV')
        self.conf.add_service(self.service)

    async def tearDownAsync(self):
        await self.handle.close()
        await super().tearDownAsync()

    async def get_application(self, loop=None):
        self.fake_atv = FakeAppleTV(self, self.loop)
        self.usecase = AppleTVUseCases(self.fake_atv)
        return self.fake_atv.app

    @unittest_run_loop
    async def test_pairing_with_device(self):
        self.handle = await pyatv.pair(self.conf, Protocol.MRP, self.loop)

        self.assertTrue(self.handle.device_provides_pin)

        await self.handle.begin()
        self.handle.pin(PIN_CODE)

        await self.handle.finish()

        self.assertTrue(self.handle.has_paired)
        self.assertTrue(self.fake_atv.has_paired)

    @unittest_run_loop
    async def test_pairing_with_bad_pin(self):
        self.handle = await pyatv.pair(self.conf, Protocol.MRP, self.loop)

        self.assertTrue(self.handle.device_provides_pin)

        await self.handle.begin()
        self.handle.pin(PIN_CODE + 1)

        with self.assertRaises(exceptions.PairingError):
            await self.handle.finish()

        self.assertFalse(self.handle.has_paired)
        self.assertFalse(self.fake_atv.has_paired)

    @unittest_run_loop
    async def test_pairing_authentication(self):
        self.service.credentials = CLIENT_CREDENTIALS

        self.handle = await pyatv.connect(self.conf, self.loop)

        self.assertTrue(self.fake_atv.has_authenticated)
Пример #20
0
 async def setUpAsync(self):
     await super().setUpAsync()
     self.service = ManualService(
         None, Protocol.Companion, self.fake_atv.get_port(Protocol.Companion), {}
     )
     self.conf = AppleTV(IPv4Address("127.0.0.1"), "Test device")
     self.conf.add_service(
         ManualService(
             "mrp_id", Protocol.MRP, self.fake_atv.get_port(Protocol.MRP), {}
         )
     )
     self.conf.add_service(self.service)
Пример #21
0
def companion_conf_fixture(companion_device):
    airplay = ManualService("airplayid", Protocol.AirPlay, 0, {})
    service = ManualService(
        None,
        Protocol.Companion,
        companion_device.get_port(Protocol.Companion),
        {},
        credentials=CLIENT_CREDENTIALS,
    )
    conf = AppleTV("127.0.0.1", "Apple TV")
    conf.add_service(service)
    conf.add_service(airplay)
    yield conf
Пример #22
0
    async def test_scan_mrp(self):
        zeroconf_stub.stub(pyatv, MRP_SERVICE_1, MRP_SERVICE_2)

        atvs = await pyatv.scan_for_apple_tvs(self.loop,
                                              only_usable=False,
                                              timeout=0)
        self.assertEqual(len(atvs), 2)

        dev1 = AppleTV(ipaddress.ip_address('10.0.0.4'), 'Apple TV 4')
        self.assertIn(dev1, atvs)

        dev2 = AppleTV(ipaddress.ip_address('10.0.0.5'), 'Apple TV 5')
        self.assertIn(dev2, atvs)
Пример #23
0
 async def setUpAsync(self):
     await super().setUpAsync()
     self.conf = AppleTV(IPv4Address("127.0.0.1"), "Test device")
     self.conf.add_service(
         ManualService("mrp_id", Protocol.MRP,
                       self.fake_atv.get_port(Protocol.MRP), {}))
     airplay_service = ManualService(
         "airplay_id",
         Protocol.AirPlay,
         self.server.port,
         properties={"features": "0x1"},  # AirPlayVideoV1 supported
     )
     airplay_service.credentials = DEVICE_CREDENTIALS
     self.conf.add_service(airplay_service)
     self.atv = await self.get_connected_device()
Пример #24
0
async def connect(
    config: conf.AppleTV,
    loop: asyncio.AbstractEventLoop,
    protocol: Protocol = None,
    session: aiohttp.ClientSession = None,
) -> interface.AppleTV:
    """Connect to a device based on a configuration."""
    if config.identifier is None:
        raise exceptions.DeviceIdMissingError("no device identifier")

    service = config.main_service(protocol=protocol)

    implementation = {Protocol.DMAP: DmapAppleTV, Protocol.MRP: MrpAppleTV}.get(
        service.protocol
    )

    if not implementation:
        raise exceptions.UnsupportedProtocolError(str(service.protocol))

    # AirPlay stream API is the same for both DMAP and MRP
    airplay = AirPlayStreamAPI(config, loop)

    atv = implementation(loop, await net.create_session(session), config, airplay)
    await atv.connect()
    return atv
Пример #25
0
    def __init__(
        self,
        loop: asyncio.AbstractEventLoop,
        session_manager: ClientSessionManager,
        config: conf.AppleTV,
        airplay: Stream,
    ) -> None:
        """Initialize a new Apple TV."""
        super().__init__()

        self._session_manager = session_manager
        self._config = config
        self._mrp_service = config.get_service(Protocol.MRP)
        assert self._mrp_service is not None

        self._connection = MrpConnection(config.address,
                                         self._mrp_service.port,
                                         loop,
                                         atv=self)
        self._srp = SRPAuthHandler()
        self._protocol = MrpProtocol(self._connection, self._srp,
                                     self._mrp_service)
        self._psm = PlayerStateManager(self._protocol, loop)

        self._mrp_remote = MrpRemoteControl(loop, self._psm, self._protocol)
        self._mrp_metadata = MrpMetadata(self._protocol, self._psm,
                                         config.identifier)
        self._mrp_power = MrpPower(loop, self._protocol, self._mrp_remote)
        self._mrp_push_updater = MrpPushUpdater(loop, self._mrp_metadata,
                                                self._psm)
        self._mrp_features = MrpFeatures(self._config, self._psm)
        self._airplay = airplay
Пример #26
0
def setup(
    loop: asyncio.AbstractEventLoop,
    config: conf.AppleTV,
    interfaces: Dict[Any, Relayer],
    device_listener: StateProducer,
    session_manager: ClientSessionManager,
) -> Optional[Tuple[Callable[[], Awaitable[None]], Callable[[], None],
                    Set[FeatureName]]]:
    """Set up a new AirPlay service."""
    service = config.get_service(Protocol.AirPlay)
    assert service is not None

    # TODO: Split up in connect/protocol and Stream implementation
    stream = AirPlayStream(config)

    interfaces[Features].register(
        AirPlayFeatures(cast(conf.AirPlayService, service)), Protocol.AirPlay)
    interfaces[Stream].register(stream, Protocol.AirPlay)

    async def _connect() -> None:
        pass

    def _close() -> None:
        stream.close()

    return _connect, _close, set([FeatureName.PlayUrl])
Пример #27
0
    def __init__(
        self,
        loop,
        session_manager: ClientSessionManager,
        config: conf.AppleTV,
        airplay: Stream,
    ) -> None:
        """Initialize a new Apple TV."""
        super().__init__()
        self._session_manager = session_manager
        self._config = config
        self._dmap_service = config.get_service(Protocol.DMAP)
        assert self._dmap_service is not None
        daap_http = net.HttpSession(
            session_manager.session,
            f"http://{config.address}:{self._dmap_service.port}/",
        )
        self._requester = DaapRequester(daap_http,
                                        self._dmap_service.credentials)

        self._apple_tv = BaseDmapAppleTV(self._requester)
        self._dmap_remote = DmapRemoteControl(self._apple_tv)
        self._dmap_metadata = DmapMetadata(config.identifier, self._apple_tv)
        self._dmap_power = DmapPower()
        self._dmap_push_updater = DmapPushUpdater(loop, self._apple_tv, self)
        self._dmap_features = DmapFeatures(config, self._apple_tv)
        self._airplay = airplay
Пример #28
0
    def setUp(self):
        AioHTTPTestCase.setUp(self)
        self.pairing = None

        self.service = DmapService('dmap_id',
                                   PAIRING_GUID,
                                   port=self.server.port)
        self.conf = AppleTV('127.0.0.1', 'Apple TV')
        self.conf.add_service(self.service)

        # TODO: currently stubs internal method, should provide stub
        # for netifaces later
        pairing._get_private_ip_addresses = \
            lambda: [ipaddress.ip_address('10.0.0.1')]

        self.zeroconf = zeroconf_stub.stub(pyatv.dmap.pairing)
Пример #29
0
class MRPFunctionalTest(common_functional_tests.CommonFunctionalTests):
    async def setUpAsync(self):
        await super().setUpAsync()
        self.conf = AppleTV('127.0.0.1', 'Test device')
        self.conf.add_service(MrpService('mrp_id', self.fake_atv.port))
        self.conf.add_service(
            AirPlayService('airplay_id', self.server.port, DEVICE_CREDENTIALS))
        self.atv = await self.get_connected_device()

    async def tearDownAsync(self):
        await self.atv.close()
        await super().tearDownAsync()

    async def get_application(self, loop=None):
        self.fake_atv = FakeAppleTV(self, self.loop)
        self.usecase = AppleTVUseCases(self.fake_atv)
        return self.fake_atv.app

    async def get_connected_device(self):
        return await pyatv.connect(self.conf, loop=self.loop)

    @unittest_run_loop
    async def test_button_home(self):
        await self.atv.remote_control.home()
        await until(lambda: self.fake_atv.last_button_pressed == 'home')

    @unittest_run_loop
    async def test_button_volume_up(self):
        await self.atv.remote_control.volume_up()
        await until(lambda: self.fake_atv.last_button_pressed == 'volume_up')

    @unittest_run_loop
    async def test_button_volume_down(self):
        await self.atv.remote_control.volume_down()
        await until(lambda: self.fake_atv.last_button_pressed == 'volume_down')

    @unittest_run_loop
    async def test_button_suspend(self):
        await self.atv.remote_control.suspend()
        await until(lambda: self.fake_atv.last_button_pressed == 'suspend')

    @unittest_run_loop
    async def test_button_wakeup(self):
        await self.atv.remote_control.wakeup()
        await until(lambda: self.fake_atv.last_button_pressed == 'wakeup')
Пример #30
0
    async def test_scan_for_apple_tvs(self):
        zeroconf_stub.stub(pyatv, HOMESHARING_SERVICE_1, HOMESHARING_SERVICE_2,
                           MRP_SERVICE_1, AIRPLAY_SERVICE_1)

        atvs = await pyatv.scan_for_apple_tvs(self.loop, timeout=0)
        self.assertEqual(len(atvs), 3)

        # First device
        dev1 = AppleTV(ipaddress.ip_address('10.0.0.1'), 'Apple TV 1')
        self.assertIn(dev1, atvs)

        # Second device
        dev2 = AppleTV(ipaddress.ip_address('10.0.0.2'), 'Apple TV 2')
        self.assertIn(dev2, atvs)

        # Third device
        dev3 = AppleTV(ipaddress.ip_address('10.0.0.4'), 'Apple TV 4')
        self.assertIn(dev3, atvs)