From bea29d0737fe25f76436b8ea87a4ef1f33a85f30 Mon Sep 17 00:00:00 2001 From: "guirem@gmail.com" Date: Mon, 23 Apr 2018 15:07:31 +0200 Subject: [PATCH] fixes to install & stability - added param to manage frequency from interface - fix install_check script for raspberry - reduce cpu ressource of main program - fix ability to reconnect when lost --- core/class/googlecast.class.php | 1 + docs/fr_FR/changelog.md | 5 ++ docs/fr_FR/index.md | 1 + plugin_info/configuration.php | 10 +++ plugin_info/info.json | 2 +- plugin_info/install.php | 3 + resources/globals.py | 12 ++-- resources/googlecast.py | 106 +++++++++++++++++++++----------- resources/install_check.sh | 22 ++++--- resources/jeedom/jeedom.py | 6 +- 10 files changed, 114 insertions(+), 54 deletions(-) diff --git a/core/class/googlecast.class.php b/core/class/googlecast.class.php index 00d9fa1..df4fcba 100644 --- a/core/class/googlecast.class.php +++ b/core/class/googlecast.class.php @@ -587,6 +587,7 @@ public static function deamon_start() { $cmd .= ' --callback ' . network::getNetworkAccess('internal', 'proto:127.0.0.1:port:comp') . '/plugins/googlecast/core/php/googlecast.api.php'; $cmd .= ' --apikey ' . jeedom::getApiKey('googlecast'); $cmd .= ' --daemonname local'; + $cmd .= ' --cyclefactor ' . config::byKey('cyclefactor', 'googlecast', '1'); log::add('googlecast', 'info', 'Lancement démon googlecast : ' . $cmd); $result = exec($cmd . ' >> ' . log::getPathToLog('googlecast_local') . ' 2>&1 &'); $i = 0; diff --git a/docs/fr_FR/changelog.md b/docs/fr_FR/changelog.md index 794e820..c5898ca 100644 --- a/docs/fr_FR/changelog.md +++ b/docs/fr_FR/changelog.md @@ -4,6 +4,11 @@ Liste des versions du plugin googlecast. *[Retour à la documentation](index.md)* +## Version du 23 avril 2018 + +- Fix installation des dépendances pour raspberry +- Fix impossibilité de (re)connection +- Ajout de possibilité de réglage de la fréquence de rafraîchissement ## Version du 18 avril 2018 diff --git a/docs/fr_FR/index.md b/docs/fr_FR/index.md index 975c436..65a97cf 100644 --- a/docs/fr_FR/index.md +++ b/docs/fr_FR/index.md @@ -51,6 +51,7 @@ Après téléchargement du plugin : Les paramêtres de configuration n'ont généralement pas besoin d'être modifiés - Port du socket interne de communication. Ne modifier que si nécessaire (ex: s'il est déjà pris par un autres plugin) +- Fréquence de rafraîchissement. A ne modifier uniquement si la fréquence normale à un impact important sur les performances globales - Désactiver notif pour nouveaux GoogleCast : ce sont des notifications lors de la découverte de nouveaux Google Cast non configurés Configuration des équipements diff --git a/plugin_info/configuration.php b/plugin_info/configuration.php index f540e2f..e72176c 100644 --- a/plugin_info/configuration.php +++ b/plugin_info/configuration.php @@ -29,6 +29,16 @@
+ +
+ +
+ +
{{Notifications}}
diff --git a/plugin_info/info.json b/plugin_info/info.json index dd33e27..183b90b 100644 --- a/plugin_info/info.json +++ b/plugin_info/info.json @@ -12,7 +12,7 @@ "category" : "multimedia", "changelog" : "https://github.com/guirem/plugin-googlecast/blob/develop/docs/fr_FR/changelog.md", "documentation" : "https://github.com/guirem/plugin-googlecast/blob/develop/docs/fr_FR/index.md", - "forum_link" : "", + "forum_link" : "https://www.jeedom.com/forum/viewtopic.php?f=142&t=35863", "languages" : "french, english", "compatibility" : "miniplus, smart, docker, rpi, diy, mobileapp", "description" : "Plugin pour commander et connaitre l'état des équipements compatibles Google Cast.
Fonctionnalités :
- Contrôle du son (mute, +/-)
- Contrôle des médias (play/pause/stop...)
- Arrêt appli en cours, reboot
- Diffuser une page web sur un écran
- Lecture de fichier audio et vidéo via url
- Retour d'état sur les principales Fonctionnalités
- Affichage de la lecture en cours

Modèle compatibles Google Cast
- Chromecast Audio/Video, Google Home
- Android TV, GoogleCast TV (Vizio, Sharp, Sony, Toshiba, Philips)
- GoogleCast Soundbars et speakers
" diff --git a/plugin_info/install.php b/plugin_info/install.php index ec25a1f..f6815c3 100644 --- a/plugin_info/install.php +++ b/plugin_info/install.php @@ -51,6 +51,9 @@ function googlecast_install() { if ( config::byKey('socketport', 'googlecast') == '' ) { config::save('socketport','55012', 'googlecast'); } + if ( config::byKey('cyclefactor', 'googlecast') == '' ) { + config::save('cyclefactor','1', 'googlecast'); + } linkTemplate('dashboard/cmd.info.string.googlecast_playing.html'); diff --git a/resources/globals.py b/resources/globals.py index f70de8d..9c594dd 100644 --- a/resources/globals.py +++ b/resources/globals.py @@ -22,17 +22,16 @@ GCAST_DEVICES = {} NOWPLAYING_TIMEOUT = 15*60 # 15 minutes -NOWPLAYING_FREQUENCY = 15 # 30 seconds +NOWPLAYING_FREQUENCY = 15 # 15 seconds +NOWPLAYING_LAST = 0 LEARN_BEGIN = int(time.time()) LEARN_MODE = False # is learn mode ? LEARN_TIMEOUT = 60 -HEARTBEAT_FREQUENCY = 300 # 5 minutes +HEARTBEAT_FREQUENCY = 600 # 10 minutes LAST_BEAT = int(time.time()) -READ_FREQUENCY = 60 # in seconds - SCAN_FREQUENCY = 60 # in seconds SCAN_PENDING = False # is scanner running? SCAN_LAST = 0 # when last started @@ -45,11 +44,14 @@ IFACE_DEVICE = 0 +cycle_factor = 2 +cycle = 0.5 +cycle_main = 2 + log_level = "info" pidfile = '/tmp/googlecast.pid' apikey = '' callback = '' -cycle = 0.3 daemonname='' socketport=55012 sockethost='127.0.0.1' diff --git a/resources/googlecast.py b/resources/googlecast.py index 3c97078..e7f44d4 100644 --- a/resources/googlecast.py +++ b/resources/googlecast.py @@ -55,11 +55,12 @@ def __init__(self, gcast, options=None, scan_mode=False): self.now_playing = False self.now_playing_thread = False self.online = True - self.being_shutdown = True + self.being_shutdown = False self.scan_mode = scan_mode if scan_mode == False : self.customplayer = None self.customplayername = "" + self.nowplaying_lastupdated = 0 self.gcast.media_controller.register_status_listener(self) self.gcast.register_status_listener(self) self.gcast.register_connection_listener(self) @@ -85,7 +86,6 @@ def startNowPlaying(self): if self.now_playing == False and self.online == True and self.now_playing_thread == False: logging.debug("JEEDOMCHROMECAST------ Starting monitoring of " + self.uuid) self.now_playing = True - thread.start_new_thread(self.thread_nowlaying, ("nowPlayingTHread",)) def stopNowPlaying(self): logging.debug("JEEDOMCHROMECAST------ Stopping monitoring of " + self.uuid) @@ -94,11 +94,17 @@ def stopNowPlaying(self): def new_cast_status(self, new_status): #logging.debug("JEEDOMCHROMECAST------ Status " + str(new_status)) self._internal_refresh_status(False) + self.sendNowPlaying(force=True) + + def new_media_status(self, new_mediastatus): + #logging.debug("JEEDOMCHROMECAST------ New media status " + str(new_mediastatus)) + if self.now_playing==True and new_mediastatus.player_state!="BUFFERING" : + self._internal_send_now_playing() def new_connection_status(self, new_status): logging.debug("JEEDOMCHROMECAST------ Connection " + str(new_status.status)) self.online = False - if new_status.status == "DISCONNECTED" and self.being_shutdown == False: + if new_status.status == "DISCONNECTED" and self.being_shutdown==False: self.disconnect() logging.info("JEEDOMCHROMECAST------ Chromecast has beend disconnected : " + self.friendly_name) if new_status.status == "LOST" : @@ -109,7 +115,7 @@ def new_connection_status(self, new_status): globals.GCAST_DEVICES[self.uuid] = self self._internal_refresh_status(True) if self.now_playing == True : - self.sendNowPlaying() + self._internal_trigger_now_playing_update() def sendDeviceStatus(self, _force=True): try : @@ -123,16 +129,16 @@ def sendDeviceStatusIfNew(self): self.sendDeviceStatus(False) def disconnect(self): - if self.scan_mode == False : + self.being_shutdown = True + if self.scan_mode==False : self._internal_refresh_status(True) if self.now_playing == True : - self.now_playing = False self._internal_send_now_playing() + self.now_playing = False if self.uuid in globals.GCAST_DEVICES : del globals.GCAST_DEVICES[self.uuid] logging.debug("JEEDOMCHROMECAST------ Chromecast disconnected : " + self.friendly_name) self.gcast.disconnect() - self.being_shutdown = True del self def loadPlayer(self, playername, params=None, token=None) : @@ -163,6 +169,7 @@ def loadPlayer(self, playername, params=None, token=None) : self.gcast.quit_app() if params and 'wait' in params : time.sleep(params['wait']) + self.sendNowPlaying(force=True) return self.customplayer return None @@ -171,6 +178,7 @@ def resetPlayer(self) : if self.gcast.socket_client and self.customplayer.namespace in self.gcast.socket_client._handlers : del self.gcast.socket_client._handlers[self.customplayer.namespace] self.customplayer = None + self.sendNowPlaying(force=True) def _internal_refresh_status(self,_force = False): uuid = self.uuid @@ -245,32 +253,34 @@ def getStatus(self): return self._internal_get_status() - def thread_nowlaying(self, name): - logging.debug("JEEDOMCHROMECAST------ Starting NowPlaying thread for " + self.uuid) - self.now_playing_thread = True - delay = 0 - firstTime = True - while self and self.now_playing : - if delay >= globals.NOWPLAYING_FREQUENCY or firstTime : - self.sendNowPlaying() - firstTime = False - delay = 0 - delay = delay + 1 - time.sleep(1) - self.now_playing_thread = False - logging.debug("JEEDOMCHROMECAST------ Closing NowPlaying thread for " + self.uuid) - - def sendNowPlaying(self): + def _internal_trigger_now_playing_update(self) : try : - self.gcast.media_controller.update_status(callback_function_param=self._internal_send_now_playing) + self.gcast.media_controller.update_status() except Exception : - self._internal_send_now_playing() pass - def _internal_send_now_playing(self, message=None): + def sendNowPlaying(self, force=False): + if force==True : + self._internal_send_now_playing() + elif self.now_playing==True: + logging.debug("JEEDOMCHROMECAST------ NOW PLAYGIN " + str(int(time.time())-self.nowplaying_lastupdated)) + if (int(time.time())-self.nowplaying_lastupdated)>=globals.NOWPLAYING_FREQUENCY : + self._internal_trigger_now_playing_update() + + def sendNowPlaying_heartbeat(self): + if self.now_playing==True: + if (int(datetime.utcnow().timestamp())-self.nowplaying_lastupdated)>=globals.NOWPLAYING_FREQUENCY : + logging.debug("JEEDOMCHROMECAST------ NOW PLAYGIN heartbeat " + str(int(datetime.utcnow().timestamp())-self.nowplaying_lastupdated)) + self._internal_trigger_now_playing_update() + + def _internal_send_now_playing(self): uuid = self.uuid if self.gcast.status and self.online == True : playStatus = self.gcast.media_controller.status + if self.gcast.media_controller.status.last_updated: + self.nowplaying_lastupdated = int(self.gcast.media_controller.status.last_updated.timestamp()) + else: + self.nowplaying_lastupdated = int(time.time()) if len(playStatus.images) > 0 : img = str(playStatus.images[0].url) else: @@ -291,7 +301,8 @@ def _internal_send_now_playing(self, message=None): "album_artist" : playStatus.album_artist, "metadata_type" : playStatus.metadata_type, "album_name" : playStatus.album_name, - "current_time" : '{0:.0f}'.format(playStatus.current_time), + #"current_time" : '{0:.0f}'.format(playStatus.current_time), + "current_time" : '{0:.0f}'.format(playStatus.adjusted_current_time), "artist" : playStatus.artist, 'series_title': playStatus.series_title, 'season': playStatus.season, @@ -484,7 +495,7 @@ def start(cycle=2): jeedom_socket.open() logging.info("GLOBAL------Socket started...") logging.info("GLOBAL------Waiting for messages...") - thread.start_new_thread( read_socket, ('socket',)) + thread.start_new_thread( read_socket, (globals.cycle,)) globals.JEEDOM_COM.send_change_immediate({'started' : 1,'source' : globals.daemonname}); try: @@ -503,9 +514,14 @@ def start(cycle=2): if globals.LEARN_MODE and not globals.SCAN_PENDING : thread.start_new_thread( scanner, ('learn',)) - if not globals.SCAN_PENDING and (int(time.time()) - globals.SCAN_LAST) > globals.SCAN_FREQUENCY : + if not globals.SCAN_PENDING and (current_time - globals.SCAN_LAST) > globals.SCAN_FREQUENCY : thread.start_new_thread( scanner, ('scanner',)) + if (current_time - globals.NOWPLAYING_LAST)>globals.NOWPLAYING_FREQUENCY/2 and not globals.LEARN_MODE: + for uuid in globals.GCAST_DEVICES : + globals.GCAST_DEVICES[uuid].sendNowPlaying_heartbeat() + globals.NOWPLAYING_LAST = current_time + if globals.LEARN_MODE : time.sleep(0.2) else : @@ -519,7 +535,7 @@ def start(cycle=2): shutdown() -def read_socket(name): +def read_socket(cycle): while True : try: global JEEDOM_SOCKET_MESSAGE @@ -607,8 +623,7 @@ def read_socket(name): except Exception as e: logging.error("SOCKET-READ------Exception on socket : %s" % str(e)) logging.debug(traceback.format_exc()) - time.sleep(0.3) - + time.sleep(cycle) def scanner(name): try: @@ -762,12 +777,17 @@ def shutdown(): parser.add_argument("--sockethost", help="Socket Host", type=str) parser.add_argument("--daemonname", help="Daemon Name", type=str) parser.add_argument("--scantimeout", help="GoogleCast scan timeout", type=str) -parser.add_argument("--cycle", help="Cycle to send event", type=str) +parser.add_argument("--scanfrequency", help="Frequency for scan", type=str) +parser.add_argument("--cycle", help="Cycle to send/receive event", type=str) +parser.add_argument("--cyclemain", help="Cycle for main loop", type=str) +parser.add_argument("--cyclefactor", help="Factor for event cycles (default=1)", type=str) args = parser.parse_args() if args.scantimeout: globals.SCAN_TIMEOUT = int(args.scantimeout) +if args.scanfrequency: + globals.SCAN_FREQUENCY = int(args.scanfrequency) if args.loglevel: globals.log_level = args.loglevel if args.pidfile: @@ -778,6 +798,10 @@ def shutdown(): globals.apikey = args.apikey if args.cycle: globals.cycle = float(args.cycle) +if args.cyclemain: + globals.cycle_main = float(args.cyclemain) +if args.cyclefactor: + globals.cycle_factor = int(args.cyclefactor) if args.socketport: globals.socketport = args.socketport if args.sockethost: @@ -785,21 +809,31 @@ def shutdown(): if args.daemonname: globals.daemonname = args.daemonname +if globals.cycle_factor==0: + globals.cycle_factor=1 +globals.NOWPLAYING_FREQUENCY = int(globals.NOWPLAYING_FREQUENCY*globals.cycle_factor) +globals.SCAN_FREQUENCY = int(globals.SCAN_FREQUENCY*globals.cycle_factor) + globals.socketport = int(globals.socketport) -globals.cycle = float(globals.cycle) +globals.cycle = float(globals.cycle*globals.cycle_factor) +globals.cycle_main = float(globals.cycle_main*globals.cycle_factor) + +#globals.cycle_factor = int(globals.cycle_factor) jeedom_utils.set_log_level(globals.log_level) logging.info('------------------------------------------------------') logging.info('------------------------------------------------------') logging.info('GLOBAL------STARTING googlecast') logging.info('GLOBAL------Scan Timeout : '+str(globals.SCAN_TIMEOUT)) +logging.info('GLOBAL------Scan Frequency : '+str(globals.SCAN_FREQUENCY)) logging.info('GLOBAL------Log level : '+str(globals.log_level)) logging.info('GLOBAL------Socket port : '+str(globals.socketport)) logging.info('GLOBAL------Socket host : '+str(globals.sockethost)) logging.info('GLOBAL------PID file : '+str(globals.pidfile)) logging.info('GLOBAL------Apikey : '+str(globals.apikey)) logging.info('GLOBAL------Callback : '+str(globals.callback)) -logging.info('GLOBAL------Cycle : '+str(globals.cycle)) +logging.info('GLOBAL------Event cycle : '+str(globals.cycle)) +logging.info('GLOBAL------Main cycle : '+str(globals.cycle_main)) logging.info('------------------------------------------------------') signal.signal(signal.SIGINT, handler) @@ -814,7 +848,7 @@ def shutdown(): else : logging.info('GLOBAL------Network communication to jeedom OK.') jeedom_socket = jeedom_socket(port=globals.socketport,address=globals.sockethost) - start(2) + start(globals.cycle_main) except Exception as e: logging.error('GLOBAL------Fatal error : '+str(e)) diff --git a/resources/install_check.sh b/resources/install_check.sh index 4c6fc7c..1160b2d 100644 --- a/resources/install_check.sh +++ b/resources/install_check.sh @@ -1,21 +1,25 @@ rm -f /tmp/dependancycheck_googlecast -if [[ $(python3 -V) != Python* ]]; then +if ! python3 -V 2>&1 | grep -q "Python 3"; then echo "nok" exit 0 fi pip3cmd=$(compgen -ac | grep -E '^pip-?3' | sort -r | head -1) if [[ ! -z $pip3cmd ]]; then # pip3 found - $(sudo $pip3cmd list | grep -E "zeroconf|requests|protobuf" | wc -l > /tmp/dependancycheck_googlecast) - - content=$(cat /tmp/dependancycheck_googlecast) - if [ "3" == "$content" ];then - echo "ok" - else + $(sudo $pip3cmd list 2>/dev/null | grep -E "zeroconf|requests|protobuf" | wc -l > /tmp/dependancycheck_googlecast) + content=$(cat /tmp/dependancycheck_googlecast 2>/dev/null) + if [[ -z $content ]]; then + $content = 0 + fi + if [ "$content" -lt 3 ];then echo "nok" + rm -f /tmp/dependancycheck_googlecast + exit 0 fi - rm -f /tmp/dependancycheck_googlecast - exit 0 else echo "nok" + exit 0 fi +echo "ok" +rm -f /tmp/dependancycheck_googlecast +exit 0 diff --git a/resources/jeedom/jeedom.py b/resources/jeedom/jeedom.py index 28f66b7..3f2532d 100644 --- a/resources/jeedom/jeedom.py +++ b/resources/jeedom/jeedom.py @@ -19,7 +19,7 @@ import threading import _thread as thread import requests -import datetime +from datetime import datetime import collections import os from os.path import join @@ -50,7 +50,7 @@ def send_changes_async(self): resend_changes = threading.Timer(self.cycle, self.send_changes_async) resend_changes.start() return - start_time = datetime.datetime.now() + start_time = datetime.now() changes = self.changes self.changes = {} logging.debug('SENDER------Send to jeedom : '+str(changes)) @@ -65,7 +65,7 @@ def send_changes_async(self): i = i + 1 if r.status_code != requests.codes.ok: logging.error('SENDER------Error on send request to jeedom, return code %s' % (str(r.status_code),)) - dt = datetime.datetime.now() - start_time + dt = datetime.now() - start_time ms = (dt.days * 24 * 60 * 60 + dt.seconds) * 1000 + dt.microseconds / 1000.0 timer_duration = self.cycle - ms if timer_duration < 0.1: