Beispiel #1
0
    def device_info(self) -> DeviceInfo:
        """Return general device information."""
        properties = self._all_properties()

        if Protocol.MRP in self._services:
            os_type = OperatingSystem.TvOS
        elif Protocol.DMAP in self._services:
            os_type = OperatingSystem.Legacy
        else:
            os_type = OperatingSystem.Unknown

        build = properties.get("SystemBuildVersion")
        version = properties.get("osvers", lookup_version(build))

        model_name: Optional[str] = properties.get("model", None)
        if model_name:
            model = lookup_model(model_name)
        else:
            model = self._model

        mac = properties.get("macAddress", properties.get("deviceid"))
        if mac:
            mac = mac.upper()

        return DeviceInfo(os_type, version, build, model, mac)
Beispiel #2
0
def test_device_info_empty_input(properties, os, version, build_number, model,
                                 mac):
    dev_info = DeviceInfo(properties)
    assert dev_info.operating_system == os
    assert dev_info.version == version
    assert dev_info.build_number == build_number
    assert dev_info.model == model
    assert dev_info.mac == mac
Beispiel #3
0
def test_device_info_homepod_mini_str():
    dev_info = DeviceInfo({
        DeviceInfo.OPERATING_SYSTEM: OperatingSystem.TvOS,
        DeviceInfo.VERSION: "1.2.3",
        DeviceInfo.BUILD_NUMBER: "19A123",
        DeviceInfo.MODEL: DeviceModel.HomePodMini,
        DeviceInfo.MAC: "aa:bb:cc:dd:ee:ff",
    })

    assert str(dev_info) == "HomePod Mini, tvOS 1.2.3 build 19A123"
Beispiel #4
0
def test_device_info_apple_tv_3_str():
    dev_info = DeviceInfo({
        DeviceInfo.OPERATING_SYSTEM: OperatingSystem.Legacy,
        DeviceInfo.VERSION: "2.2.3",
        DeviceInfo.BUILD_NUMBER: "13D333",
        DeviceInfo.MODEL: DeviceModel.Gen3,
        DeviceInfo.MAC: "aa:bb:cc:dd:ee:ff",
    })

    assert str(dev_info) == "Apple TV 3, ATV SW 2.2.3 build 13D333"
Beispiel #5
0
async def test_service_info_pairing(raop_props, devinfo, pairing_req):
    raop_service = MutableService("id", Protocol.RAOP, 0, raop_props)

    assert raop_service.pairing == PairingRequirement.Unsupported

    await service_info(
        raop_service,
        DeviceInfo(devinfo),
        {Protocol.RAOP: raop_service},
    )

    assert raop_service.pairing == pairing_req
Beispiel #6
0
async def test_service_info_pairing(airplay_props, devinfo, pairing_req):
    airplay_service = MutableService("id", Protocol.AirPlay, 0, airplay_props)

    assert airplay_service.pairing == PairingRequirement.Unsupported

    await service_info(
        airplay_service,
        DeviceInfo(devinfo),
        {Protocol.AirPlay: airplay_service},
    )

    assert airplay_service.pairing == pairing_req
Beispiel #7
0
async def test_service_info_pairing_acl():
    raop_service = MutableService("id", Protocol.RAOP, 0, {})
    airplay_props = MutableService("id", Protocol.AirPlay, 0, {"acl": "1"})

    await service_info(
        raop_service,
        DeviceInfo({}),
        {
            Protocol.RAOP: raop_service,
            Protocol.AirPlay: airplay_props
        },
    )

    assert raop_service.pairing == PairingRequirement.Disabled
Beispiel #8
0
    def device_info(self) -> DeviceInfo:
        """Return general device information."""
        properties = self._all_properties()

        build: Optional[str] = properties.get("systembuildversion")
        version = properties.get("ov")
        if not version:
            version = properties.get("osvers", lookup_version(build))

        model_name: Optional[str] = properties.get("model",
                                                   properties.get("am"))
        if model_name:
            model = lookup_model(model_name)
        else:
            model = self._model

        # MRP devices run tvOS (as far as we know now) as well as HomePods for
        # some reason
        if Protocol.MRP in self._services or model in [
                DeviceModel.HomePod,
                DeviceModel.HomePodMini,
        ]:
            os_type = OperatingSystem.TvOS
        elif Protocol.DMAP in self._services:
            os_type = OperatingSystem.Legacy
        elif model in [
                DeviceModel.AirPortExpress, DeviceModel.AirPortExpressGen2
        ]:
            os_type = OperatingSystem.AirPortOS
        else:
            os_type = OperatingSystem.Unknown

        mac = properties.get("macaddress", properties.get("deviceid"))
        if mac:
            mac = mac.upper()

        # The waMA property comes from the _airport._tcp.local service, announced by
        # AirPort Expresses (used by the admin tool). It contains various information,
        # for instance MAC address and software version.
        wama = properties.get("wama")
        if wama:
            props: Mapping[str, str] = dict(
                cast(Tuple[str, str], prop.split("=", maxsplit=1))
                for prop in ("macaddress=" + wama).split(","))
            if not mac:
                mac = props["macaddress"].replace("-", ":").upper()
            version = props.get("syVs")

        return DeviceInfo(os_type, version, build, model, mac)
Beispiel #9
0
 def __init__(
     self,
     address: IPv4Address,
     name: str,
     deep_sleep: bool = False,
     properties: Optional[Mapping[str, Mapping[str, str]]] = None,
     device_info: Optional[DeviceInfo] = None,
 ) -> None:
     """Initialize a new AppleTV."""
     super().__init__(properties or {})
     self._address = address
     self._name = name
     self._deep_sleep = deep_sleep
     self._services: Dict[Protocol, BaseService] = {}
     self._device_info = device_info or DeviceInfo({})
Beispiel #10
0
async def test_service_info_pairing(dmap_props, mrp_props, pairing_req):
    dmap_service = MutableService("id", Protocol.DMAP, 0, dmap_props)
    mrp_service = MutableService("mrp", Protocol.MRP, 0, mrp_props)

    assert dmap_service.pairing == PairingRequirement.Unsupported
    assert mrp_service.pairing == PairingRequirement.Unsupported

    await service_info(
        dmap_service,
        DeviceInfo({}),
        {Protocol.MRP: mrp_service, Protocol.DMAP: dmap_service},
    )

    assert dmap_service.pairing == pairing_req
    assert mrp_service.pairing == PairingRequirement.Unsupported
Beispiel #11
0
async def test_service_info_pairing(airplay_props, mrp_props, pairing_req):
    mrp_service = MutableService("mrp", Protocol.MRP, 0, mrp_props)
    airplay_service = MutableService("id", Protocol.AirPlay, 0, airplay_props)

    assert mrp_service.pairing == PairingRequirement.Unsupported
    assert airplay_service.pairing == PairingRequirement.Unsupported

    await service_info(
        mrp_service,
        DeviceInfo({}),
        {
            Protocol.MRP: mrp_service,
            Protocol.AirPlay: airplay_service
        },
    )

    assert mrp_service.pairing == pairing_req
    assert airplay_service.pairing == PairingRequirement.Unsupported
Beispiel #12
0
async def test_service_info_password(raop_props, mrp_props, requires_password):
    raop_service = MutableService("id", Protocol.RAOP, 0, raop_props)
    mrp_service = MutableService("mrp", Protocol.MRP, 0, mrp_props)

    assert not raop_service.requires_password
    assert not mrp_service.requires_password

    await service_info(
        raop_service,
        DeviceInfo({}),
        {
            Protocol.MRP: mrp_service,
            Protocol.RAOP: raop_service
        },
    )

    assert raop_service.requires_password == requires_password
    assert not mrp_service.requires_password
Beispiel #13
0
    def _get_device_info(self, device: FoundDevice) -> DeviceInfo:
        device_info: Dict[str, Any] = {}

        # Extract device info from all service responses
        device_properties = self._properties[device.address]
        for service_name, service_properties in device_properties.items():
            service_info = self._services.get(service_name)
            if service_info:
                _, extractor = service_info
                dict_merge(device_info,
                           extractor(service_name, service_properties))

        # If model was discovered via _device-info._tcp.local, manually add that
        # to the device info
        if device.model != DeviceModel.Unknown:
            dict_merge(device_info, {DeviceInfo.MODEL: device.model})

        return DeviceInfo(device_info)
Beispiel #14
0
async def test_service_info_password(airplay_props, mrp_props,
                                     requires_password):
    airplay_service = MutableService("id", Protocol.AirPlay, 0, airplay_props)
    mrp_service = MutableService("mrp", Protocol.MRP, 0, mrp_props)

    assert not airplay_service.requires_password
    assert not mrp_service.requires_password

    await service_info(
        airplay_service,
        DeviceInfo({}),
        {
            Protocol.MRP: mrp_service,
            Protocol.AirPlay: airplay_service
        },
    )

    assert airplay_service.requires_password == requires_password
    assert not mrp_service.requires_password
Beispiel #15
0
def test_device_info_unknown_str():
    dev_info = DeviceInfo({})

    assert str(dev_info) == "Unknown, Unknown OS"
Beispiel #16
0
async def test_service_info_pairing(properties, expected):
    service = MutableService(None, Protocol.Companion, 0, properties)

    assert service.pairing == PairingRequirement.Unsupported
    await service_info(service, DeviceInfo({}), {Protocol.Companion: service})
    assert service.pairing == expected
Beispiel #17
0
def test_device_info_bad_types(properties):
    with pytest.raises(TypeError):
        DeviceInfo(properties)
Beispiel #18
0
def test_device_info_guess_os(properties, expected_os):
    """Try to make educated guess of OS on device."""
    assert DeviceInfo(properties).operating_system == expected_os
Beispiel #19
0
def test_device_info_resolve_version_from_build_number(properties, expected):
    assert DeviceInfo(properties).version == expected
Beispiel #20
0
def test_device_info_raw_model():
    assert DeviceInfo({DeviceInfo.RAW_MODEL: "raw"}).raw_model == "raw"
Beispiel #21
0
def test_device_info_raw_model_str():
    dev_info = DeviceInfo({DeviceInfo.RAW_MODEL: "raw"})

    assert str(dev_info) == "raw, Unknown OS"