Skip to content

Commit bfb2096

Browse files
committed
Provide data in callbacks
Differentiate between websocket state changes and data payloads Provide error reasons during unexpected disconnections Specifically handle authorization rejections
1 parent cdc2ea3 commit bfb2096

2 files changed

Lines changed: 31 additions & 5 deletions

File tree

plexwebsocket.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@
77

88
_LOGGER = logging.getLogger(__name__)
99

10+
SIGNAL_DATA = "data"
11+
SIGNAL_CONNECTION_STATE = "state"
12+
13+
ERROR_AUTH_FAILURE = "Authorization failure"
14+
ERROR_TOO_MANY_RETRIES = "Too many retries"
15+
ERROR_UNKNOWN = "Unknown"
16+
17+
MAX_FAILED_ATTEMPTS = 5
18+
1019
STATE_CONNECTED = "connected"
1120
STATE_DISCONNECTED = "disconnected"
1221
STATE_STARTING = "starting"
@@ -47,7 +56,10 @@ def __init__(self, plex_server, callback, session=None, verify_ssl=True):
4756
plex_server (plexapi.server.PlexServer):
4857
A connected PlexServer instance.
4958
callback (Runnable):
50-
Callback to issue when Plex player events occur.
59+
Called when interesting events occur. Provides arguments:
60+
signal (str): One of SIGNAL_* constants
61+
data (str): Current STATE_* or websocket payload contents
62+
error (str): Error message if any or None
5163
verify_ssl:
5264
Set to False to disable SSL certificate validation.
5365
session (aiohttp.ClientSession, optional):
@@ -61,6 +73,7 @@ def __init__(self, plex_server, callback, session=None, verify_ssl=True):
6173
self._ssl = False if verify_ssl is False else None
6274
self._state = None
6375
self.failed_attempts = 0
76+
self._error_reason = None
6477

6578
@property
6679
def state(self):
@@ -72,6 +85,8 @@ def state(self, value):
7285
"""Set the state."""
7386
self._state = value
7487
_LOGGER.debug("Websocket %s", value)
88+
self.callback(SIGNAL_CONNECTION_STATE, value, self._error_reason)
89+
self._error_reason = None
7590

7691
@staticmethod
7792
def _get_uri(plex_server):
@@ -90,7 +105,6 @@ async def running(self):
90105
) as ws_client:
91106
self.state = STATE_CONNECTED
92107
self.failed_attempts = 0
93-
self.callback()
94108

95109
async for message in ws_client:
96110
if self.state == STATE_STOPPED:
@@ -99,7 +113,7 @@ async def running(self):
99113
if message.type == aiohttp.WSMsgType.TEXT:
100114
msg = message.json()["NotificationContainer"]
101115
if self.player_event(msg):
102-
self.callback()
116+
self.callback(SIGNAL_DATA, msg, None)
103117

104118
elif message.type == aiohttp.WSMsgType.CLOSED:
105119
_LOGGER.warning("AIOHTTP websocket connection closed")
@@ -109,8 +123,19 @@ async def running(self):
109123
_LOGGER.error("AIOHTTP websocket error")
110124
break
111125

126+
except aiohttp.ClientResponseError as error:
127+
if error.code == 401:
128+
_LOGGER.error("Credentials rejected: %s", error)
129+
self._error_reason = ERROR_AUTH_FAILURE
130+
else:
131+
_LOGGER.error("Unexpected response received: %s", error)
132+
self._error_reason = ERROR_UNKNOWN
133+
self.state = STATE_STOPPED
112134
except (aiohttp.ClientConnectionError, asyncio.TimeoutError) as error:
113-
if self.state != STATE_STOPPED:
135+
if self.failed_attempts >= MAX_FAILED_ATTEMPTS:
136+
self._error_reason = ERROR_TOO_MANY_RETRIES
137+
self.state = STATE_STOPPED
138+
elif self.state != STATE_STOPPED:
114139
retry_delay = min(2 ** (self.failed_attempts - 1) * 30, 300)
115140
self.failed_attempts += 1
116141
_LOGGER.error(
@@ -123,6 +148,7 @@ async def running(self):
123148
except Exception as error: # pylint: disable=broad-except
124149
if self.state != STATE_STOPPED:
125150
_LOGGER.exception("Unexpected exception occurred: %s", error)
151+
self._error_reason = ERROR_UNKNOWN
126152
self.state = STATE_STOPPED
127153
else:
128154
if self.state != STATE_STOPPED:

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
with open('README.md') as f:
44
long_description = f.read()
55

6-
VERSION="0.0.11"
6+
VERSION="0.0.12"
77

88
setup(
99
name='plexwebsocket',

0 commit comments

Comments
 (0)