pkkid / python-plexapi

Python bindings for the Plex API.
BSD 3-Clause "New" or "Revised" License
1.15k stars 198 forks source link

Unable to connect to a Plex HTPC client #1292

Open mainTAP opened 1 year ago

mainTAP commented 1 year ago

Describe the Bug

When connecting to a HTPC (windows,1.50.1.4014) client, the API cannot connect properly as it retrieves its IP as 127.0.0.1 instead of its real IP. Other clients like Plexamp or Plex for mac work fine.

Code Snippets

>>> import plexapi
>>> from plexapi.server import PlexServer
>>> baseurl = 'http://SERVERIP:32400'
>>> plex = PlexServer(baseurl)
>>> client = plex.client("HTPC")
>>> print(client)
<PlexClient:http://127.0.0.1:324:HTPC>
>>> client.timeline
Traceback (most recent call last):
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/urllib3/connection.py", line 203, in _new_conn
    sock = connection.create_connection(
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/urllib3/util/connection.py", line 85, in create_connection
    raise err
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/urllib3/util/connection.py", line 73, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/urllib3/connectionpool.py", line 790, in urlopen
    response = self._make_request(
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/urllib3/connectionpool.py", line 496, in _make_request
    conn.request(
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/urllib3/connection.py", line 395, in request
    self.endheaders()
  File "/usr/lib/python3.9/http/client.py", line 1250, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1010, in _send_output
    self.send(msg)
  File "/usr/lib/python3.9/http/client.py", line 950, in send
    self.connect()
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/urllib3/connection.py", line 243, in connect
    self.sock = self._new_conn()
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/urllib3/connection.py", line 218, in _new_conn
    raise NewConnectionError(
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x75e15988>: Failed to establish a new connection: [Errno 111] Connection refused

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/requests/adapters.py", line 486, in send
    resp = conn.urlopen(
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/urllib3/connectionpool.py", line 844, in urlopen
    retries = retries.increment(
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/urllib3/util/retry.py", line 515, in increment
    raise MaxRetryError(_pool, url, reason) from reason  # type: ignore[arg-type]
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=32400): Max retries exceeded with url: /player/timeline/poll?commandID=1&wait=0 (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x75e15988>: Failed to establish a new connection: [Errno 111] Connection refused'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/plexapi/client.py", line 587, in timeline
    return next((x for x in self.timelines() if x.state != 'stopped'), None)
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/plexapi/client.py", line 579, in timelines
    timelines = self.sendCommand(ClientTimeline.key, wait=wait) or []
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/plexapi/client.py", line 234, in sendCommand
    return query(key, headers=headers)
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/plexapi/client.py", line 186, in query
    response = method(url, headers=headers, timeout=timeout, **kwargs)
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/requests/sessions.py", line 602, in get
    return self.request("GET", url, **kwargs)
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/requests/sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/requests/sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
  File "/home/osmc/Scripts/audio-automation/venv/lib/python3.9/site-packages/requests/adapters.py", line 519, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=32400): Max retries exceeded with url: /player/timeline/poll?commandID=1&wait=0 (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x75e15988>: Failed to establish a new connection: [Errno 111] Connection refused'))
>>>

Expected Behavior

To be able to connect to HTPC client and control it

Additional Context

Retrieving the clients from the server via SERVERIP:32400/clients shows the HTPC twice, once with 127.0.0.1 and also one with IP of the server ( rather than the IP of the actual client ). If I iterate over the plex.clients() and use the instance with the server's IP address, I'm able to retrieve the timeline but can't control the client like client.pause() and get timeout error : requests.exceptions.ReadTimeout: HTTPConnectionPool(host='SERVERIP', port=32400): Read timed out. (read timeout=30)

Operating System and Version

Debian ( PlexAPI ) , Ubuntu ( Plex Server ) , Windows 11 ( Plex HTPC )

Plex Media Server Version

1.32.7.7621

Python Version

3.9.2

PlexAPI Version

4.15.5

JonnyWong16 commented 1 year ago

Try using proxyThroughServer().

>>> import plexapi
>>> from plexapi.server import PlexServer
>>> baseurl = 'http://SERVERIP:32400'
>>> plex = PlexServer(baseurl)
>>> client = plex.client("HTPC")
>>> client.proxyThroughServer()
>>> client.timeline
mainTAP commented 1 year ago

Thank you, using the client.proxyThroughServer() does help and it's able to show the timeline. Unfortunately, though, the client still cannot be controlled :

>>> client = plex.client("HTPC")
>>> client
<PlexClient:http://127.0.0.1:324:HTPC>
>>> client.proxyThroughServer()
>>> client.timeline
<ClientTimeline:25410>
>>> client.pause()
requests.exceptions.ReadTimeout: HTTPConnectionPool(host='SERVERIP', port=32400): Read timed out. (read timeout=30)
mainTAP commented 1 year ago

Just to add that when adding the mtype='music' to the command ( as the playing media was music ), the playback does actually pause, but the command still hangs and excepts with the same exception :

>>> client.pause(mtype='music')
requests.exceptions.ReadTimeout: HTTPConnectionPool(host='SERVERIP', port=32400): Read timed out. (read timeout=30)
mainTAP commented 7 months ago

I also have issues with retrieving client.isPlayingMedia() status ( and also timeline ) for the HTPC client when the client is freshly restarted and the media playback is initiated from the client itself, not via Plex companion / API . The client is listed but isPlayingMedia returns False. The dashboard in a Plex app shows the client playing the media and also the PlexServer.sessions() returns that session but not via the client itself.

Once there is connection to the client via Plex companion ( for instance Plex for MacOS,from the cast icon selecting the HTPC client ) even while that media is still being played at the HTPC client, once it connects, the API starts to recognising the client that it plays the media.

Once I disconnected from HTPC in the Plex for Mac app, the API still recognizing the client playing media, but once the playback is stopped and timeline cleared. The next media playback won't be recognised by the API until I connect via a Plex app to control HTPC.