postlund / pyatv

A client library for Apple TV and AirPlay devices
https://pyatv.dev
MIT License
839 stars 91 forks source link

Storage, settings, improvement to API reference and a wizard in atvremote #2151

Closed postlund closed 10 months ago

postlund commented 10 months ago

It's finally time to introduce something I've been working on for a while: storage! The storage API provides means for pyatv to store things like credentials and passwords so you don't have to type them manually all the time. As a start, pyatv includes a file based storage module that stores everything in a JSON structured file. The API is however flexible, so you can write your own storage (quite simple) that stores it somewhere else, like a file in Google Drive. I have also adjusted atvremote and atvscript to use file storage by default, so everything will be stored in $HOME/.pyatv.conf now.

All devices found during scanning will be stored automatically. Also, credentials obtained via pairing will be inserted into the storage automatically. So once you have paired once, you don't have to care about credentials again, i.e. no need specifying --xxx-credentials anymore. Same goes if you specify --xxx-password. Pretty neat actually.

Another benefit of this is that setting can be stored as well. I have added a few fields that allows setting things like custom remote name, MAC address, OS version and so on. These are currently not used, but I will address that too soon. Other things that I will include are ways to specify static port numbers where randomized ports are used today. Also a way to force AirPlay 1 when connecting to an AirPlay 2 receiver as well.

I have also made some improvements to the API reference, so that value of enums are now printed as well:

IMG_5285

And lastly... I have started working on a "wizard" in atvremote that simplifies setting up a new device. You simply run atvremote wizard and follow the instructions:

$ atvremote wizard
Looking for devices...
Found the following devices:
    Name                      Model                    Address
--  ------------------------  -----------------------  -----------
 1  Receiver                  RX-V773                  10.0.10.82
 2  Vardagsrum                Apple TV 4K              10.0.10.81
 3  Pierre's AirPort Express  AirPort Express (gen 2)  10.0.10.168
 4  Office                    HomePod Mini             10.0.10.84
 5  Apple TV                  Apple TV 3               10.0.10.83
Enter index of device to set up (q to quit): 4
Starting to set up Office
Ignoring Companion as it is not supported
Ignoring AirPlay since pairing is not needed
Ignoring RAOP since pairing is not needed
Pairing finished, trying to connect and get some metadata...
Currently playing:
  Media type: Unknown
Device state: Idle
      Repeat: Off
     Shuffle: Off
Device is now set up!

Since file storage is used, the credentials will be automatically saved. So once the wizard is done, you don't have to care about pairing, credentials or password anymore. You will even get some hints if incorrect access mode is not configured. This is still very early, so expect things to change and improve over time. But I hope everyone will like this!

I am still not finished with the work here, I have some details to iron out. Mostly it's related to documentation and testing, since a lot of things are missing tests. But it would be really great to get some feedback on the work so far, so please give it a spin and let me know how it works!

One additional last thing... I have added commands to atvremote to simplify working with settings. So they can be listed like this for instance:

$ atvremote -s 10.0.0.5 print_settings
info.name = pyatv (str)
info.mac = 02:70:79:61:74:76 (str)
info.model = iPhone10,6 (str)
info.device_id = FF:70:79:61:74:76 (str)
info.os_name = iPhone OS (str)
info.os_build = 18G82 (str)
info.os_version = 14.7.1 (str)
protocols.airplay.identifier = 58:D3:49:34:A4:B4 (str, NoneType)
protocols.airplay.credentials = None (str, NoneType)
protocols.airplay.password = None (str, NoneType)
protocols.companion.identifier = None (str, NoneType)
protocols.companion.credentials = None (str, NoneType)
protocols.dmap.identifier = None (str, NoneType)
protocols.dmap.credentials = None (str, NoneType)
protocols.mrp.identifier = None (str, NoneType)
protocols.mrp.credentials = None (str, NoneType)
protocols.raop.identifier = 58D34934A4B4 (str, NoneType)
protocols.raop.credentials = None (str, NoneType)
protocols.raop.password = None (str, NoneType)

Or even changed:

$ atvremote -s 10.0.10.84 change_setting=info.os_build,19G82

I believe most things are done now, but I do need to split and clean up my changes in a few commits. So I should be ready to merge this very soon!

codecov[bot] commented 10 months ago

Codecov Report

Patch coverage: 97.28% and project coverage change: +0.23% :tada:

Comparison is base (05ca46d) 88.72% compared to head (4c4800b) 88.96%.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## master #2151 +/- ## ========================================== + Coverage 88.72% 88.96% +0.23% ========================================== Files 163 167 +4 Lines 11070 11342 +272 ========================================== + Hits 9822 10090 +268 - Misses 1248 1252 +4 ``` | [Files Changed](https://app.codecov.io/gh/postlund/pyatv/pull/2151?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/protocols/airplay/utils.py](https://app.codecov.io/gh/postlund/pyatv/pull/2151?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL2FpcnBsYXkvdXRpbHMucHk=) | `87.85% <ø> (ø)` | | | [pyatv/protocols/airplay/ap2\_session.py](https://app.codecov.io/gh/postlund/pyatv/pull/2151?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL2FpcnBsYXkvYXAyX3Nlc3Npb24ucHk=) | `37.50% <50.00%> (+0.29%)` | :arrow_up: | | [pyatv/protocols/dmap/\_\_init\_\_.py](https://app.codecov.io/gh/postlund/pyatv/pull/2151?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL2RtYXAvX19pbml0X18ucHk=) | `97.41% <66.66%> (ø)` | | | [pyatv/protocols/raop/\_\_init\_\_.py](https://app.codecov.io/gh/postlund/pyatv/pull/2151?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=) | `97.02% <66.66%> (ø)` | | | [pyatv/protocols/airplay/\_\_init\_\_.py](https://app.codecov.io/gh/postlund/pyatv/pull/2151?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL2FpcnBsYXkvX19pbml0X18ucHk=) | `73.09% <75.00%> (ø)` | | | [pyatv/core/\_\_init\_\_.py](https://app.codecov.io/gh/postlund/pyatv/pull/2151?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvY29yZS9fX2luaXRfXy5weQ==) | `96.73% <85.71%> (-0.94%)` | :arrow_down: | | [pyatv/protocols/airplay/pairing.py](https://app.codecov.io/gh/postlund/pyatv/pull/2151?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL2FpcnBsYXkvcGFpcmluZy5weQ==) | `94.82% <91.66%> (-1.33%)` | :arrow_down: | | [pyatv/\_\_init\_\_.py](https://app.codecov.io/gh/postlund/pyatv/pull/2151?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvX19pbml0X18ucHk=) | `93.75% <95.65%> (+1.06%)` | :arrow_up: | | [pyatv/settings.py](https://app.codecov.io/gh/postlund/pyatv/pull/2151?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvc2V0dGluZ3MucHk=) | `96.29% <96.29%> (ø)` | | | [pyatv/core/facade.py](https://app.codecov.io/gh/postlund/pyatv/pull/2151?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvY29yZS9mYWNhZGUucHk=) | `99.31% <100.00%> (+<0.01%)` | :arrow_up: | | ... and [15 more](https://app.codecov.io/gh/postlund/pyatv/pull/2151?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl) | | ... and [1 file with indirect coverage changes](https://app.codecov.io/gh/postlund/pyatv/pull/2151/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl)

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.