Default to websocket connection

* No polling failover
This commit is contained in:
JonnyWong16 2016-10-08 20:55:51 -07:00 committed by JonnyWong16
parent be50ecd033
commit 16c7d27508
5 changed files with 59 additions and 63 deletions

View file

@ -194,8 +194,6 @@ def main():
web_socket.start_thread() web_socket.start_thread()
except: except:
logger.warn(u"Websocket :: Unable to open connection.") logger.warn(u"Websocket :: Unable to open connection.")
# Fallback to polling
plexpy.POLLING_FAILOVER = True
plexpy.initialize_scheduler() plexpy.initialize_scheduler()
# Force the http port if neccessary # Force the http port if neccessary

View file

@ -42,7 +42,7 @@ DOCUMENTATION :: END
<td>${arrow.get(next_run_interval).format('HH:mm:ss')}</td> <td>${arrow.get(next_run_interval).format('HH:mm:ss')}</td>
<td>${arrow.get(sched_job.next_run_time).format('YYYY-MM-DD HH:mm:ss')}</td> <td>${arrow.get(sched_job.next_run_time).format('YYYY-MM-DD HH:mm:ss')}</td>
</tr> </tr>
% elif job in ('Check for active sessions', 'Check for recently added items') and plexpy.CONFIG.MONITORING_USE_WEBSOCKET and not plexpy.POLLING_FAILOVER: % elif job in ('Check for active sessions', 'Check for recently added items') and plexpy.WS_CONNECTED:
<tr> <tr>
<td>${job}</td> <td>${job}</td>
<td><i class="fa fa-sm fa-fw fa-check"></i> Using Websocket</td> <td><i class="fa fa-sm fa-fw fa-check"></i> Using Websocket</td>

View file

@ -64,7 +64,7 @@ NOTIFY_QUEUE = Queue()
INIT_LOCK = threading.Lock() INIT_LOCK = threading.Lock()
_INITIALIZED = False _INITIALIZED = False
started = False _STARTED = False
DATA_DIR = None DATA_DIR = None
@ -80,12 +80,12 @@ COMMITS_BEHIND = None
UMASK = None UMASK = None
POLLING_FAILOVER = False
HTTP_ROOT = None HTTP_ROOT = None
DEV = False DEV = False
WS_CONNECTED = False
def initialize(config_file): def initialize(config_file):
with INIT_LOCK: with INIT_LOCK:
@ -96,7 +96,6 @@ def initialize(config_file):
global CURRENT_VERSION global CURRENT_VERSION
global LATEST_VERSION global LATEST_VERSION
global UMASK global UMASK
global POLLING_FAILOVER
CONFIG = plexpy.config.Config(config_file) CONFIG = plexpy.config.Config(config_file)
CONFIG_FILE = config_file CONFIG_FILE = config_file
@ -299,10 +298,21 @@ def initialize_scheduler():
schedule_job(versioncheck.checkGithub, 'Check GitHub for updates', schedule_job(versioncheck.checkGithub, 'Check GitHub for updates',
hours=0, minutes=github_minutes, seconds=0) hours=0, minutes=github_minutes, seconds=0)
# Our interval should never be less than 30 seconds backup_hours = CONFIG.BACKUP_INTERVAL if 1 <= CONFIG.BACKUP_INTERVAL <= 24 else 6
monitor_seconds = CONFIG.MONITORING_INTERVAL if CONFIG.MONITORING_INTERVAL >= 30 else 30
if CONFIG.PMS_IP and CONFIG.PMS_TOKEN: schedule_job(database.make_backup, 'Backup PlexPy database',
hours=backup_hours, minutes=0, seconds=0, args=(True, True))
schedule_job(config.make_backup, 'Backup PlexPy config',
hours=backup_hours, minutes=0, seconds=0, args=(True, True))
if WS_CONNECTED and CONFIG.PMS_IP and CONFIG.PMS_TOKEN:
# Our interval should never be less than 30 seconds
monitor_seconds = CONFIG.MONITORING_INTERVAL if CONFIG.MONITORING_INTERVAL >= 30 else 30
#schedule_job(activity_pinger.check_active_sessions, 'Check for active sessions',
# hours=0, minutes=0, seconds=1)
#schedule_job(activity_pinger.check_recently_added, 'Check for recently added items',
# hours=0, minutes=0, seconds=monitor_seconds * bool(CONFIG.NOTIFY_RECENTLY_ADDED))
schedule_job(plextv.get_real_pms_url, 'Refresh Plex server URLs', schedule_job(plextv.get_real_pms_url, 'Refresh Plex server URLs',
hours=12, minutes=0, seconds=0) hours=12, minutes=0, seconds=0)
schedule_job(pmsconnect.get_server_friendly_name, 'Refresh Plex server name', schedule_job(pmsconnect.get_server_friendly_name, 'Refresh Plex server name',
@ -313,31 +323,19 @@ def initialize_scheduler():
schedule_job(activity_pinger.check_server_updates, 'Check for Plex updates', schedule_job(activity_pinger.check_server_updates, 'Check for Plex updates',
hours=12 * bool(CONFIG.MONITOR_PMS_UPDATES), minutes=0, seconds=0) hours=12 * bool(CONFIG.MONITOR_PMS_UPDATES), minutes=0, seconds=0)
# If we're not using websockets then fall back to polling # Refresh the users list and libraries list
if not CONFIG.MONITORING_USE_WEBSOCKET or POLLING_FAILOVER: user_hours = CONFIG.REFRESH_USERS_INTERVAL if 1 <= CONFIG.REFRESH_USERS_INTERVAL <= 24 else 12
schedule_job(activity_pinger.check_active_sessions, 'Check for active sessions', library_hours = CONFIG.REFRESH_LIBRARIES_INTERVAL if 1 <= CONFIG.REFRESH_LIBRARIES_INTERVAL <= 24 else 12
hours=0, minutes=0, seconds=monitor_seconds)
schedule_job(activity_pinger.check_recently_added, 'Check for recently added items',
hours=0, minutes=0, seconds=monitor_seconds * bool(CONFIG.NOTIFY_RECENTLY_ADDED))
# Refresh the users list and libraries list
user_hours = CONFIG.REFRESH_USERS_INTERVAL if 1 <= CONFIG.REFRESH_USERS_INTERVAL <= 24 else 12
library_hours = CONFIG.REFRESH_LIBRARIES_INTERVAL if 1 <= CONFIG.REFRESH_LIBRARIES_INTERVAL <= 24 else 12
if CONFIG.PMS_TOKEN:
schedule_job(plextv.refresh_users, 'Refresh users list', schedule_job(plextv.refresh_users, 'Refresh users list',
hours=user_hours, minutes=0, seconds=0) hours=user_hours, minutes=0, seconds=0)
if CONFIG.PMS_IP and CONFIG.PMS_TOKEN:
schedule_job(pmsconnect.refresh_libraries, 'Refresh libraries list', schedule_job(pmsconnect.refresh_libraries, 'Refresh libraries list',
hours=library_hours, minutes=0, seconds=0) hours=library_hours, minutes=0, seconds=0)
backup_hours = CONFIG.BACKUP_INTERVAL if 1 <= CONFIG.BACKUP_INTERVAL <= 24 else 6 else:
## Add new taks to check and reconnect websocket
schedule_job(database.make_backup, 'Backup PlexPy database', pass
hours=backup_hours, minutes=0, seconds=0, args=(True, True))
schedule_job(config.make_backup, 'Backup PlexPy config',
hours=backup_hours, minutes=0, seconds=0, args=(True, True))
# Start scheduler # Start scheduler
if start_jobs and len(SCHED.get_jobs()): if start_jobs and len(SCHED.get_jobs()):
@ -373,17 +371,15 @@ def schedule_job(function, name, hours=0, minutes=0, seconds=0, args=None):
def start(): def start():
global started global _STARTED
if _INITIALIZED: if _INITIALIZED:
initialize_scheduler()
# Start background notification thread # Start background notification thread
if any([CONFIG.MOVIE_NOTIFY_ENABLE, CONFIG.TV_NOTIFY_ENABLE, if any([CONFIG.MOVIE_NOTIFY_ENABLE, CONFIG.TV_NOTIFY_ENABLE,
CONFIG.MUSIC_NOTIFY_ENABLE, CONFIG.NOTIFY_RECENTLY_ADDED]): CONFIG.MUSIC_NOTIFY_ENABLE, CONFIG.NOTIFY_RECENTLY_ADDED]):
notification_handler.start_threads(num_threads=3) notification_handler.start_threads(num_threads=3)
started = True _STARTED = True
def sig_handler(signum=None, frame=None): def sig_handler(signum=None, frame=None):

View file

@ -111,7 +111,7 @@ _CONFIG_DEFINITIONS = {
'CHECK_GITHUB_INTERVAL': (int, 'General', 360), 'CHECK_GITHUB_INTERVAL': (int, 'General', 360),
'CHECK_GITHUB_ON_STARTUP': (int, 'General', 1), 'CHECK_GITHUB_ON_STARTUP': (int, 'General', 1),
'CLEANUP_FILES': (int, 'General', 0), 'CLEANUP_FILES': (int, 'General', 0),
'CONFIG_VERSION': (str, 'General', '0'), 'CONFIG_VERSION': (int, 'Advanced', 0),
'DO_NOT_OVERRIDE_GIT_BRANCH': (int, 'General', 0), 'DO_NOT_OVERRIDE_GIT_BRANCH': (int, 'General', 0),
'EMAIL_ENABLED': (int, 'Email', 0), 'EMAIL_ENABLED': (int, 'Email', 0),
'EMAIL_FROM_NAME': (str, 'Email', 'PlexPy'), 'EMAIL_FROM_NAME': (str, 'Email', 'PlexPy'),
@ -460,7 +460,7 @@ _CONFIG_DEFINITIONS = {
'REFRESH_LIBRARIES_ON_STARTUP': (int, 'Monitoring', 1), 'REFRESH_LIBRARIES_ON_STARTUP': (int, 'Monitoring', 1),
'REFRESH_USERS_INTERVAL': (int, 'Monitoring', 12), 'REFRESH_USERS_INTERVAL': (int, 'Monitoring', 12),
'REFRESH_USERS_ON_STARTUP': (int, 'Monitoring', 1), 'REFRESH_USERS_ON_STARTUP': (int, 'Monitoring', 1),
'SESSION_DB_WRITE_ATTEMPTS': (int, 'Monitoring', 5), 'SESSION_DB_WRITE_ATTEMPTS': (int, 'Advanced', 5),
'SLACK_ENABLED': (int, 'Slack', 0), 'SLACK_ENABLED': (int, 'Slack', 0),
'SLACK_HOOK': (str, 'Slack', ''), 'SLACK_HOOK': (str, 'Slack', ''),
'SLACK_CHANNEL': (str, 'Slack', ''), 'SLACK_CHANNEL': (str, 'Slack', ''),
@ -750,7 +750,7 @@ class Config(object):
""" """
Upgrades config file from previous verisions and bumps up config version Upgrades config file from previous verisions and bumps up config version
""" """
if self.CONFIG_VERSION == '0': if self.CONFIG_VERSION == 0:
# Separate out movie and tv notifications # Separate out movie and tv notifications
if self.MOVIE_NOTIFY_ENABLE == 1: if self.MOVIE_NOTIFY_ENABLE == 1:
self.TV_NOTIFY_ENABLE = 1 self.TV_NOTIFY_ENABLE = 1
@ -758,9 +758,9 @@ class Config(object):
if self.VIDEO_LOGGING_ENABLE == 0: if self.VIDEO_LOGGING_ENABLE == 0:
self.MOVIE_LOGGING_ENABLE = 0 self.MOVIE_LOGGING_ENABLE = 0
self.TV_LOGGING_ENABLE = 0 self.TV_LOGGING_ENABLE = 0
self.CONFIG_VERSION = '1' self.CONFIG_VERSION = 1
if self.CONFIG_VERSION == '1': if self.CONFIG_VERSION == 1:
# Change home_stats_cards to list # Change home_stats_cards to list
if self.HOME_STATS_CARDS: if self.HOME_STATS_CARDS:
home_stats_cards = ''.join(self.HOME_STATS_CARDS).split(', ') home_stats_cards = ''.join(self.HOME_STATS_CARDS).split(', ')
@ -773,9 +773,9 @@ class Config(object):
if 'library_statistics' in home_library_cards: if 'library_statistics' in home_library_cards:
home_library_cards.remove('library_statistics') home_library_cards.remove('library_statistics')
self.HOME_LIBRARY_CARDS = home_library_cards self.HOME_LIBRARY_CARDS = home_library_cards
self.CONFIG_VERSION = '2' self.CONFIG_VERSION = 2
if self.CONFIG_VERSION == '2': if self.CONFIG_VERSION == 2:
def rep(s): def rep(s):
return s.replace('{progress}','{progress_duration}') return s.replace('{progress}','{progress_duration}')
@ -792,13 +792,13 @@ class Config(object):
self.NOTIFY_ON_WATCHED_SUBJECT_TEXT = rep(self.NOTIFY_ON_WATCHED_SUBJECT_TEXT) self.NOTIFY_ON_WATCHED_SUBJECT_TEXT = rep(self.NOTIFY_ON_WATCHED_SUBJECT_TEXT)
self.NOTIFY_ON_WATCHED_BODY_TEXT = rep(self.NOTIFY_ON_WATCHED_BODY_TEXT) self.NOTIFY_ON_WATCHED_BODY_TEXT = rep(self.NOTIFY_ON_WATCHED_BODY_TEXT)
self.NOTIFY_SCRIPTS_ARGS_TEXT = rep(self.NOTIFY_SCRIPTS_ARGS_TEXT) self.NOTIFY_SCRIPTS_ARGS_TEXT = rep(self.NOTIFY_SCRIPTS_ARGS_TEXT)
self.CONFIG_VERSION = '3' self.CONFIG_VERSION = 3
if self.CONFIG_VERSION == '3': if self.CONFIG_VERSION == 3:
if self.HTTP_ROOT == '/': self.HTTP_ROOT = '' if self.HTTP_ROOT == '/': self.HTTP_ROOT = ''
self.CONFIG_VERSION = '4' self.CONFIG_VERSION = 4
if self.CONFIG_VERSION == '4': if self.CONFIG_VERSION == 4:
if not len(self.HOME_STATS_CARDS) and 'watch_stats' in self.HOME_SECTIONS: if not len(self.HOME_STATS_CARDS) and 'watch_stats' in self.HOME_SECTIONS:
home_sections = self.HOME_SECTIONS home_sections = self.HOME_SECTIONS
home_sections.remove('watch_stats') home_sections.remove('watch_stats')
@ -807,18 +807,18 @@ class Config(object):
home_sections = self.HOME_SECTIONS home_sections = self.HOME_SECTIONS
home_sections.remove('library_stats') home_sections.remove('library_stats')
self.HOME_SECTIONS = home_sections self.HOME_SECTIONS = home_sections
self.CONFIG_VERSION = '5' self.CONFIG_VERSION = 5
if self.CONFIG_VERSION == '5': if self.CONFIG_VERSION == 5:
self.MONITOR_PMS_UPDATES = 0 self.MONITOR_PMS_UPDATES = 0
self.CONFIG_VERSION = '6' self.CONFIG_VERSION = 6
if self.CONFIG_VERSION == '6': if self.CONFIG_VERSION == 6:
if self.GIT_USER.lower() == 'drzoidberg33': if self.GIT_USER.lower() == 'drzoidberg33':
self.GIT_USER = 'JonnyWong16' self.GIT_USER = 'JonnyWong16'
self.CONFIG_VERSION = '7' self.CONFIG_VERSION = 7
if self.CONFIG_VERSION == '7': if self.CONFIG_VERSION == 7:
def rep(s): def rep(s):
return s.replace('<tv>','<episode>').replace('</tv>','</episode>').replace('<music>','<track>').replace('</music>','</track>') return s.replace('<tv>','<episode>').replace('</tv>','</episode>').replace('<music>','<track>').replace('</music>','</track>')
@ -835,4 +835,6 @@ class Config(object):
self.NOTIFY_ON_WATCHED_SUBJECT_TEXT = rep(self.NOTIFY_ON_WATCHED_SUBJECT_TEXT) self.NOTIFY_ON_WATCHED_SUBJECT_TEXT = rep(self.NOTIFY_ON_WATCHED_SUBJECT_TEXT)
self.NOTIFY_ON_WATCHED_BODY_TEXT = rep(self.NOTIFY_ON_WATCHED_BODY_TEXT) self.NOTIFY_ON_WATCHED_BODY_TEXT = rep(self.NOTIFY_ON_WATCHED_BODY_TEXT)
self.NOTIFY_SCRIPTS_ARGS_TEXT = rep(self.NOTIFY_SCRIPTS_ARGS_TEXT) self.NOTIFY_SCRIPTS_ARGS_TEXT = rep(self.NOTIFY_SCRIPTS_ARGS_TEXT)
self.CONFIG_VERSION = '8'
self.MONITORING_USE_WEBSOCKET = 1
self.CONFIG_VERSION = 8

View file

@ -64,23 +64,23 @@ def run():
global ws_reconnect global ws_reconnect
ws_reconnect = False ws_reconnect = False
ws_connected = False
reconnects = 0 reconnects = 0
# Try an open the websocket connection - if it fails after 15 retries fallback to polling # Try an open the websocket connection - if it fails after 15 retries fallback to polling
while not ws_connected and reconnects <= 15: while not plexpy.WS_CONNECTED and reconnects <= 15:
try: try:
logger.info(u"PlexPy WebSocket :: Opening%s websocket, connection attempt %s." % (secure, str(reconnects + 1))) logger.info(u"PlexPy WebSocket :: Opening%s websocket, connection attempt %s." % (secure, str(reconnects + 1)))
ws = create_connection(uri, header=header) ws = create_connection(uri, header=header)
reconnects = 0 reconnects = 0
ws_connected = True
logger.info(u"PlexPy WebSocket :: Ready") logger.info(u"PlexPy WebSocket :: Ready")
plexpy.WS_CONNECTED = True
plexpy.initialize_scheduler()
except IOError as e: except IOError as e:
logger.error(u"PlexPy WebSocket :: %s." % e) logger.error(u"PlexPy WebSocket :: %s." % e)
reconnects += 1 reconnects += 1
time.sleep(5) time.sleep(5)
while ws_connected: while plexpy.WS_CONNECTED:
try: try:
process(*receive(ws)) process(*receive(ws))
@ -102,19 +102,19 @@ def run():
else: else:
ws.shutdown() ws.shutdown()
ws_connected = False plexpy.WS_CONNECTED = False
break break
# Check if we recieved a restart notification and close websocket connection cleanly # Check if we recieved a restart notification and close websocket connection cleanly
if ws_reconnect: if ws_reconnect:
logger.info(u"PlexPy WebSocket :: Reconnecting websocket...") logger.info(u"PlexPy WebSocket :: Reconnecting websocket...")
ws.shutdown() ws.shutdown()
ws_connected = False plexpy.WS_CONNECTED = False
start_thread() start_thread()
if not ws_connected and not ws_reconnect: if not plexpy.WS_CONNECTED and not ws_reconnect:
logger.error(u"PlexPy WebSocket :: Connection unavailable, falling back to polling.") logger.error(u"PlexPy WebSocket :: Connection unavailable, Plex server is down.")
plexpy.POLLING_FAILOVER = True plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_intdown'})
plexpy.initialize_scheduler() plexpy.initialize_scheduler()
logger.debug(u"PlexPy WebSocket :: Leaving thread.") logger.debug(u"PlexPy WebSocket :: Leaving thread.")
@ -155,22 +155,22 @@ def process(opcode, data):
if type == 'playing': if type == 'playing':
# logger.debug('%s.playing %s' % (name, info)) # logger.debug('%s.playing %s' % (name, info))
try: try:
time_line = info.get('_children') children = info.get('_children')
except: except:
logger.debug(u"PlexPy WebSocket :: Session found but unable to get timeline data.") logger.debug(u"PlexPy WebSocket :: Session found but unable to get timeline data.")
return False return False
activity = activity_handler.ActivityHandler(timeline=time_line[0]) activity = activity_handler.ActivityHandler(timeline=children[0])
activity.process() activity.process()
if type == 'timeline': if type == 'timeline':
try: try:
time_line = info.get('_children') children = info.get('_children')
except: except:
logger.debug(u"PlexPy WebSocket :: Timeline event found but unable to get timeline data.") logger.debug(u"PlexPy WebSocket :: Timeline event found but unable to get timeline data.")
return False return False
activity = activity_handler.TimelineHandler(timeline=time_line[0]) activity = activity_handler.TimelineHandler(timeline=children[0])
activity.process() activity.process()
return True return True