Repository: postlund/pyatv
Pull request #1777 (2022-06-28 07:30:51)

raop: Fallback to pk as unique id
If device id is not present in the Zeroconf name, use public key of
device as unique identifier (if present).

Relates to #1747

<a href="https://gitpod.io/#https://github.com/postlund/pyatv/pull/1777"><img src="https://gitpod.io/button/open-in-gitpod.svg"/></a>



codecov[bot]: # [Codecov](https://codecov.io/gh/postlund/pyatv/pull/1777?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl) Report
> Merging [#1777](https://codecov.io/gh/postlund/pyatv/pull/1777?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl) (67b307b) into [master](https://codecov.io/gh/postlund/pyatv/commit/5805f2c900ac068e1993dc03ed099c6f88b70749?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl) (5805f2c) will **decrease** coverage by `0.17%`.
> The diff coverage is `100.00%`.

```diff
@@            Coverage Diff             @@
##           master    #1777      +/-   ##
==========================================
- Coverage   88.21%   88.03%   -0.18%     
==========================================
  Files         151      151              
  Lines       10077    10081       +4     
==========================================
- Hits         8889     8875      -14     
- Misses       1188     1206      +18     
```


| [Impacted Files](https://codecov.io/gh/postlund/pyatv/pull/1777?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl) | Coverage Δ | |
|---|---|---|
| [pyatv/helpers.py](https://codecov.io/gh/postlund/pyatv/pull/1777/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvaGVscGVycy5weQ==) | `100.00% <100.00%> (ø)` | |
| [pyatv/protocols/raop/\_\_init\_\_.py](https://codecov.io/gh/postlund/pyatv/pull/1777/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL3Jhb3AvX19pbml0X18ucHk=) | `94.52% <100.00%> (+0.02%)` | :arrow_up: |
| [pyatv/protocols/raop/raop.py](https://codecov.io/gh/postlund/pyatv/pull/1777/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL3Jhb3AvcmFvcC5weQ==) | `88.45% <0.00%> (-2.71%)` | :arrow_down: |
| [pyatv/support/net.py](https://codecov.io/gh/postlund/pyatv/pull/1777/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvc3VwcG9ydC9uZXQucHk=) | `93.65% <0.00%> (-1.59%)` | :arrow_down: |
| [pyatv/protocols/raop/audio\_source.py](https://codecov.io/gh/postlund/pyatv/pull/1777/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL3Jhb3AvYXVkaW9fc291cmNlLnB5) | `61.83% <0.00%> (-1.53%)` | :arrow_down: |
| [pyatv/support/http.py](https://codecov.io/gh/postlund/pyatv/pull/1777/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvc3VwcG9ydC9odHRwLnB5) | `93.39% <0.00%> (-0.67%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/postlund/pyatv/pull/1777?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/postlund/pyatv/pull/1777?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl). Last update [5805f2c...67b307b](https://codecov.io/gh/postlund/pyatv/pull/1777?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl).


Patch:
diff --git a/chickn.yaml b/chickn.yaml
index 29201232..835fa99a 100644
--- a/chickn.yaml
+++ b/chickn.yaml
@@ -63,7 +63,6 @@ pipeline:
       run: mypy --python-executable "{python_executable}" --ignore-missing-imports --follow-imports=skip pyatv
     - name: pytest
       run: pytest -n auto --log-level=debug -q -d --timeout=30 --durations=10 --cov --cov-report=term-missing --cov-report=xml tests
-      retries: 1
   post:
     - name: report
       run:
diff --git a/pyatv/helpers.py b/pyatv/helpers.py
index db4a0d07..eba0cddb 100644
--- a/pyatv/helpers.py
+++ b/pyatv/helpers.py
@@ -50,7 +50,7 @@ async def auto_connect(
     await _handle(loop)
 
 
-def get_unique_id(
+def get_unique_id(  # pylint: disable=too-many-return-statements
     service_type: str, service_name: str, properties: Mapping[str, str]
 ) -> Optional[str]:
     """Return unique identifier from a Zeroconf service.
@@ -70,7 +70,15 @@ def get_unique_id(
     if service_type == AIRPLAY_SERVICE:
         return properties.get("deviceid")
     if service_type == RAOP_SERVICE:
-        return service_name.split("@", maxsplit=1)[0]
+        split = service_name.split("@", maxsplit=1)
+
+        # Normally a RAOP devices announces with "id@name" as zeroconf name. But some
+        # devices seems to break from this behavior and just use "name", thus leaving
+        # out the id. Some of these devices however have the public key ("pk")
+        # available as an attribute so that can be used as an identifier in that case.
+        if len(split) == 2:
+            return split[0]
+        return properties.get("pk")
     return None
 
 
diff --git a/pyatv/protocols/raop/__init__.py b/pyatv/protocols/raop/__init__.py
index a6b97f44..b712d9e6 100644
--- a/pyatv/protocols/raop/__init__.py
+++ b/pyatv/protocols/raop/__init__.py
@@ -426,11 +426,17 @@ class RaopRemoteControl(RemoteControl):
         await self.audio.set_volume(max(self.audio.volume - 5.0, 0.0))
 
 
+def raop_name_from_service_name(service_name: str) -> str:
+    """Convert an raop service name to a name."""
+    split = service_name.split("@", maxsplit=1)
+    return split[1] if len(split) == 2 else split[0]
+
+
 def raop_service_handler(
     mdns_service: mdns.Service, response: mdns.Response
 ) -> Optional[ScanHandlerReturn]:
     """Parse and return a new RAOP service."""
-    _, name = mdns_service.name.split("@", maxsplit=1)
+    name = raop_name_from_service_name(mdns_service.name)
     service = MutableService(
         get_unique_id(mdns_service.type, mdns_service.name, mdns_service.properties),
         Protocol.RAOP,
@@ -440,11 +446,6 @@ def raop_service_handler(
     return name, service
 
 
-def raop_name_from_service_name(service_name: str) -> str:
-    """Convert an raop service name to a name."""
-    return service_name.split("@", maxsplit=1)[1]
-
-
 def scan() -> Mapping[str, ScanHandlerDeviceInfoName]:
     """Return handlers used for scanning."""
     return {


Test patch:
diff --git a/tests/test_helpers.py b/tests/test_helpers.py
index 3dba0d72..6d9e2a13 100644
--- a/tests/test_helpers.py
+++ b/tests/test_helpers.py
@@ -83,6 +83,7 @@ async def test_auto_connect_with_device(mock_scan, mock_connect):
         ("_airplay._tcp.local", "name", {"deviceid": "test"}, "test"),
         ("_raop._tcp.local", "abcd@name", {}, "abcd"),
         ("_raop._tcp.local", "abcd@name", {}, "abcd"),
+        ("_raop._tcp.local", "name", {"pk": "abcd"}, "abcd"),
         ("_hscp._tcp.local", "name", {"Machine ID": "abcd"}, "abcd"),
     ],
 )