postlund / pyatv

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

Scan works, nothing else does #1372

Closed johnlcoxjr closed 3 years ago

johnlcoxjr commented 3 years ago

Describe the bug

I was using this before tvOS 15 and it worked fine. After the update, my implementation stopped working. Scan works and can find all of the AppleTV's. However the one running tvOS 15 doesn't respond to any command (other than scan), and always returns "Could not find any Apple TV on current network".

atvremote --scan-hosts 192.168.50.20,192.168.50.21,192.168.50.22,192.168.50.23 scan
Scan Results
========================================
       Name: Family Room 2
   Model/SW: Apple TV 4K (gen2), tvOS 15.0
    Address: 192.168.50.20
        MAC: 58:F3:49:D8:2A:70
 Deep Sleep: False
Identifiers:
 - 58:F3:49:D8:2A:70
 - 58F349D82A70
Services:
 - Protocol: Companion, Port: 49153, Credentials: None, Requires Password: False, Password: None, Pairing: Mandatory
 - Protocol: AirPlay, Port: 7000, Credentials: None, Requires Password: False, Password: None, Pairing: Mandatory
 - Protocol: RAOP, Port: 7000, Credentials: None, Requires Password: False, Password: None, Pairing: Mandatory

Error log

atvremote -i 58F349D82A70 --protocol companion pair
2021-10-05 11:18:19 ERROR [pyatv.core.mdns]: failed to add listener for 192.168.50.100
Traceback (most recent call last):
  File "p:\platformio\apple-tv\venv\lib\site-packages\pyatv\core\mdns.py", line 522, in multicast
    await protocol.add_socket(net.mcast_socket(str(addr)))
  File "p:\platformio\apple-tv\venv\lib\site-packages\pyatv\support\net.py", line 41, in mcast_socket
    sock.setsockopt(
OSError: [WinError 10022] An invalid argument was supplied
2021-10-05 11:18:19 ERROR [pyatv.core.mdns]: failed to add listener for 127.0.0.1
Traceback (most recent call last):
  File "p:\platformio\apple-tv\venv\lib\site-packages\pyatv\core\mdns.py", line 522, in multicast
    await protocol.add_socket(net.mcast_socket(str(addr)))
  File "p:\platformio\apple-tv\venv\lib\site-packages\pyatv\support\net.py", line 41, in mcast_socket
    sock.setsockopt(
OSError: [WinError 10022] An invalid argument was supplied
2021-10-05 11:18:22 ERROR [pyatv.scripts.atvremote]: Could not find any Apple TV on current network

How to reproduce the bug?

Execute any command other than scan

What is expected behavior?

Pairing would be successful, and subsequent commands (power on/power off) will be executes.

Operating System

Windows 10

Python

3.9

pyatv

0.9.2 (was 0.8.1 before)

Device

Apple TV 4K (gen2), tvOS 15.0

Additional context

The examples do not run.

postlund commented 3 years ago

It looks like multicast scanning isn't working for some reason. I guess atvremote -s <ip> --protocol companion pair works, right? Can't really tell if I am doing anything wrong and windows is certainly not my strong suit. Are you running in a regular command prompt, power shell or WSL? Maybe that makes a difference?

johnlcoxjr commented 3 years ago

Yes, atvremote -s <ip> --protocol companion pair does work. I've tried the command prompt and power shell. Neither of them work.

postlund commented 3 years ago

Multicast scanning is set up on all interfaces with private ip addresses (RFC1918), but in your case they all fail. So there's no interface listening to the multicast traffic. I'm a bit interested in if removing lines 41-43 here:

https://github.com/postlund/pyatv/blob/67ae1b8f1698b1c1e05413d35e40f462d572f0d1/pyatv/support/net.py#L41

"fixes" the problem. Is that something you can try?

postlund commented 3 years ago

I have a theory, can you try if #1376?

johnlcoxjr commented 3 years ago

Commenting out 41-43 still didn't work. As for 1376, I apologize, I have not used Gitpod before. I opened it and attempted tp run a scan:

(pyatv) gitpod /workspace/pyatv $ pyenv shell 3.8.12
(pyatv) gitpod /workspace/pyatv $ atvremote -s 192.168.50.20 scan
Scan Results
========================================

It can't see anything on the network.

postlund commented 3 years ago

As Gitpod is a server in the cloud, you can't use that for testing. You need to install pyatv from the PR and run from there. This should work:

pip3 install git+https://github.com/postlund/pyatv.git@refs/pull/1376/head
johnlcoxjr commented 3 years ago

I created a blank project. Ran pip as given.

(venv) PS P:\PlatformIO\Test> atvremote -s 192.168.50.20 --protocol companion pair
Enter PIN on screen: 0848
Pairing seems to have succeeded, yey!
You may now use these credentials: 9b51890d9193590a02a9fb2df30216a4e1a5aaeedabf88459087020433c27f59:99e8e3561177feab45b73aad93851229eb7726a12c8abda2d806771c4d6603b8:38373539374139392d334443442d344433372d413633412d413636354432374633323444:37333965313231652d363637662d346363612d396234342d383931313063346662313236

(venv) PS P:\PlatformIO\Test> atvremote -s 192.168.50.20 --protocol companion --companion-credentials 9b51890d9193590a02a9fb2df30216a4e1a5aaeedabf88459087020433c27f59:99e8e3561177feab45b73aad93851229eb7726a12c8abda2d806771c4d6603b8:38373539374139392d334443442d344433372d413633412d413636354432374633323444:37333965313231652d363637662d346363612d396234342d383931313063346662313236 turn_off
2021-10-06 13:08:23 WARNING [pyatv.protocols.airplay]: Failed to set up remote control channel: HTTP/1.1 method POST failed with code 470: Connection Authorization Required
Traceback (most recent call last):
  File "p:\PlatformIO\Test\venv\lib\site-packages\pyatv\scripts\atvremote.py", line 716, in _run_application
    return await cli_handler(loop)
  File "p:\PlatformIO\Test\venv\lib\site-packages\pyatv\scripts\atvremote.py", line 510, in cli_handler
    return await _handle_commands(args, config, loop)
  File "p:\PlatformIO\Test\venv\lib\site-packages\pyatv\scripts\atvremote.py", line 601, in _handle_commands
    atv = await connect(config, loop, protocol=args.protocol)
  File "p:\PlatformIO\Test\venv\lib\site-packages\pyatv\__init__.py", line 96, in connect
    await atv.connect()
  File "p:\PlatformIO\Test\venv\lib\site-packages\pyatv\core\facade.py", line 425, in connect
    if await setup_data.connect():
  File "p:\PlatformIO\Test\venv\lib\site-packages\pyatv\protocols\mrp\__init__.py", line 889, in _connect
    await protocol.start()
  File "p:\PlatformIO\Test\venv\lib\site-packages\pyatv\protocols\mrp\protocol.py", line 119, in start
    await self.connection.connect()
  File "p:\PlatformIO\Test\venv\lib\site-packages\pyatv\protocols\mrp\connection.py", line 100, in connect
    await self.loop.create_connection(lambda: self, self.host, self.port)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2032.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 1056, in create_connection
    raise exceptions[0]
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2032.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 1041, in create_connection
    sock = await self._connect_sock(
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2032.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 955, in _connect_sock     
    await self.sock_connect(sock, address)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2032.0_x64__qbz5n2kfra8p0\lib\asyncio\proactor_events.py", line 702, in sock_connect  
    return await self._proactor.connect(sock, address)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2032.0_x64__qbz5n2kfra8p0\lib\asyncio\windows_events.py", line 596, in connect        
    ov.ConnectEx(conn.fileno(), address)
OSError: [WinError 10049] The requested address is not valid in its context

>>> An error occurred, full stack trace above
postlund commented 3 years ago

You ran into an MRP bug here, which I have a fix for but haven't pushed yet. You can work-around that by either providing AirPlay credentials as well or add --scan-protocols raop,companion. Question is though: does scanning work now?

postlund commented 3 years ago

A fix to the MRP problem was merged to master earlier, so should work with master now.

johnlcoxjr commented 3 years ago

This still does not work: atvremote -i 58F349D82A70 --protocol companion pair

Using -s 192.168.50.20 instead of MAC does work.

I am able to pair using companion, although (maybe I'm missing something) all it can do is turn on and off because it always display an airplay code.

Using airplay seems to work all around.

postlund commented 3 years ago

So I guess atvremote scan yields no result and the same error as before?

Companion only supports turn_on, turn_off, app_list, launch_app and a few buttons so that is normal. You need AirPlay for metadata and the rest. General rule is to just pair everything and always pass all credentials.

johnlcoxjr commented 3 years ago

This is the result:

(venv) PS P:\PlatformIO\Test> atvremote scan
2021-10-07 17:13:42 ERROR [pyatv.core.mdns]: failed to add listener for 192.168.50.100
Traceback (most recent call last):
  File "p:\PlatformIO\Test\venv\lib\site-packages\pyatv\core\mdns.py", line 522, in multicast    
    await protocol.add_socket(net.mcast_socket(str(addr)))
  File "p:\PlatformIO\Test\venv\lib\site-packages\pyatv\support\net.py", line 44, in mcast_socket
    sock.setsockopt(
OSError: [WinError 10022] An invalid argument was supplied
2021-10-07 17:13:42 ERROR [pyatv.core.mdns]: failed to add listener for 127.0.0.1
Traceback (most recent call last):
  File "p:\PlatformIO\Test\venv\lib\site-packages\pyatv\core\mdns.py", line 522, in multicast    
    await protocol.add_socket(net.mcast_socket(str(addr)))
  File "p:\PlatformIO\Test\venv\lib\site-packages\pyatv\support\net.py", line 44, in mcast_socket
    sock.setsockopt(
OSError: [WinError 10022] An invalid argument was supplied
Scan Results
postlund commented 3 years ago

Ok, so some as before. What is so different about your setup then... Can you try another version of python, like 3.8.x or so? Maybe even 3.7.x if that doesn't work?

johnlcoxjr commented 3 years ago

So I narrowed it down to the network. If the device is connected via ethernet to the same subnet that the Apple TV is on, scanning works. If the device is connected via wifi to the same subnet, scanning fails. It also fails if connected to a different subnet, but this is intended. Also noteworthy, ethernet to ethernet works, and wifi to wifi works, I just can't mix them.

So while original issue was directly related to tvOS 15, when the Apple TV auto updated, and the changes to MRP, the other issues were solely related to my Unifi setup. While I have not found a working solution for mixing ethernet and wifi, I do have the functionality that I was looking to restore working

Thank you very much for ALL of your help!

postlund commented 3 years ago

That's a sound analysis I would say! Multicast is really a hassle many times but Ubiquities hardware seems to be outright garbage in that department. I have a UDM myself (with 2xU6-LR + som switches) and it's just one problem after the other. But enough ranting... It's good so see a that you reached decent destination here, so I guess we can close the issue!