Dernières nouvelles

Une classe PHP pour piloter ses Sonos avec l’eeDomus

Au menu aujourd’hui, une classe PHP qui vous permet de piloter vos équipements Sonos, comme vous pourriez le faire depuis un Controler Sonos ou l’application Android/iOS/Windows dédiée. Avec cette classe, votre box domotique (ou tout autre système pouvant générer des requêtes HTTP) va pouvoir piloter votre produit Sonos :

  • mettre en lecture/pause,
  • gérer le niveau sonore,
  • avancer/reculer dans une chanson/une playlist,
  • charger une chanson/une radio,
  • charger/sauvegarder/vider la playlist,
  • connaitre l’état du Sonos (en lecture, en pause..),
  • connaitre les détails de la chanson diffusée (artiste, album, durée écoulée…),
  • etc…

En prime, cette classe va vous permettre de faire du Text-to-speech. Oui oui, vous avez bien lu. Vous allez pouvoir faire dire tout ce que vous voulez à vos enceintes, à l’image du Karotz.

Mais voyons sans attendre comment cela se présente.

La classe PHP est composée d’un fichier sonos.class.php et d’un fichier sonos.php (qui sert d’exemple) et à retrouver sur mon GitHub. Il vous faudra adapter le fichier sonos.php à vos besoins réels.

Le fichier sonos.class.php est composé de diverses fonctions qu’il va falloir appeler depuis votre script sonos.php selon ce que vous souhaitez exécuter. Les fonctions actuellement disponibles sont les suivantes (cela sera amené à évoluer) :

  * - Play() : play / lecture 
  * - Pause() : pause
  * - Stop() : stop
  * - Next() : next track / titre suivant 
  * - Previous() : previous track / titre précédent
  * - SeekTime(string) : seek to time xx:xx:xx / avancer-reculer à la position xx:xx:xx
  * - ChangeTrack(int) : change to track xx / aller au titre xx
  * - RestartTrack() : restart actual track / revenir au début du titre actuel
  * - RestartQueue() : restart queue / revenir au début de la liste actuelle
  * - GetVolume() : get volume level / récupérer le niveau sonore actuel
  * - SetVolume(int) : set volume level / régler le niveau sonore
  * - GetMute() : get mute status / connaitre l'état de la sourdine
  * - SetMute(bool) : active-disable mute / activer-désactiver la sourdine
  * - GetTransportInfo() : get status about player / connaitre l'état de la lecture
  * - GetMediaInfo() : get informations about media / connaitre des informations sur le média
  * - GetPositionInfo() : get some informations about track / connaitre des informations sur le titre
  * - AddURIToQueue(string,bool) : add a track to queue / ajouter un titre à la liste de lecture
  * - RemoveTrackFromQueue(int) : remove a track from Queue / supprimer un tritre de la liste de lecture
  * - RemoveAllTracksFromQueue() : remove all tracks from queue / vider la liste de lecture
  * - RefreshShareIndex() : refresh music library / rafraichit la bibliothèque musicale
  * - SetQueue(string) : load a track or radio in player / charge un titre ou une radio dans le lecteur
  * - PlayTTS(string message,string station,int volume,string lang) : play a text-to-speech message / lit un message texte

Par exemple, si vous souhaitez baisser le niveau sonore s’il est supérieur à une certaine valeur, votre fichier sonos.php ressemblera à celui-ci (il vous faut renseigner l’adresse IP du Sonos à contrôler) :

<?php
// Exemple d'application de la classe PHP Sonos permettant de baisser le niveau sonore s'il est supérieur à 50%

$IP_sonos_1 = "192.168.1.11"; // A adapter avec l'adresse IP du Sonos à contrôler

require("sonos.class.php");
//Instanciation de la classe
$sonos_1 = new SonosPHPController($IP_sonos_1);
$volume = $sonos_1->GetVolume();
if ($volume > 50)
$sonos_1 = $sonos_1->SetVolume(50);
?>

Et voilà pour les bases. Maintenons, passons à la pratique : diffusons un message texte généré par notre eedomus, même si un titre est en cours de diffusion sur notre Sonos. Cerise sur le gâteau, la diffusion sonore reprendra là où elle en était, et avec son niveau sonore, avant la diffusion du message.

Cela peut vous paraitre compliqué, mais avec cette classe PHP, tout ceci est simplifié puis c’est réalisé par un seul appel à la fonction PlayTTS  :

PlayTTS(string message,string directory,int volume,int force_unmute,string lang)

Détaillons les arguments disponibles lors de l’appel à cette fonction :

  • message : le message à diffuser (chaine de 100 caractères maximum),
  • directory : dossier partagé sur votre serveur web correspondant au dossier où est stocké le présent script (chaine de caractères)(voir ci-dessous),
  • volume : niveau sonore dans lequel le message sera diffusé (de 0 à 100). Optionnel (si non renseigné, niveau sonore conservé à la même valeur),
  • force_unmute : force à diffuser le message même si l’enceinte est en sourdine (=1). Optionnel (si non renseigné pas de modification de l’état de la sourdine),
  • lang : code pays (‘fr’, ‘en’, etc…) de la langue dans lequel le message doit être diffusé. Optionnel (si non renseigné lang=’fr’)

Comment fonctionne le principe de TTS ? Nous utilisons l’API PHP officieuse de Google permettant de faire du TTS : vous fournissez une chaine de caractères, une langue, Google vous retourne des données sonores.

Ici, pour éviter de charger inutilement les serveurs de Google (et perdre du temps) lors de la génération du message, ce dernier va être sauvegardé au format MP3 sur le serveur web qui héberge cette classe PHP Sonos, dans le sous-dossier « audio » pour être réutilisé par la suite. Cela a l’avantage à la fois d’avoir des requêtes plus rapides pour des messages répétitifs, mais aussi de pouvoir diffuser des messages sonores en l’absence de connexion Internet (et c’est là le gros avantage par rapport au Karotz), vu que le fichier aura été précédemment sauvegardé sur le serveur web.

Les 2 seuls prérequis est de mettre en partage Samba (lecture seule suffit) le dossier hébergeant les présents scripts (sur les NAS Synology par exemple, partager le dossier web est suffisant) et de rajouter ce dossier à la bibliothèque musicale de l’application Sonos.

La variable $directory contiendra le chemin Samba correspondant au dossier contenant les scripts PHP Sonos. Cela servira aux Sonos pour venir lire le fichier MP3 précédemment généré. Par exemple, si sur un Synology, on partage le dossier web et que les scripts sont dans un sous-dossier web/sonos, la variable $directory vaudra « IP_Synology/web/sonos ».

Voilà alors ce que pourrait donner une nouvelle version du script sonos.php :

<?php 
// Exemple de l'utilisation de la fonction Text-to-speech
require("sonos.class.php");
$IP_sonos_1 = "192.168.1.11"; // A adapter avec l'adresse IP du Sonos à contrôler 

$volume = 0;
$force_unmute = 0;

if (isset($_GET['force_unmute'])) $force_unmute = $_GET['force_unmute']; // Force la désactivation de la sourdine. Optionnel 
if (isset($_GET['volume'])) $volume = $_GET['volume']; // Niveau sonore. Optionnel. 
$message = $_GET['message']; // Message à diffuser 

//Instanciation de la classe 
$sonos_1 = new SonosPHPController($IP_sonos_1); 
$sonos_1->PlayTTS($message,$volume,$force_unmute); //Lecture du message
?>

Il ne vous restera alors qu’à appeler votre script et lui passer les paramètres qu’il faut :

Pour diffuser « Mon message à diffuser » sans toucher au niveau sonore (même si l’enceinte est en sourdine) :

http://IP_serveur_web/chemin/vers/sonos/sonos.php?$message=Mon message à diffuser

Pour diffuser « Mon message à diffuser » en forçant le niveau sonore à 50% mais sans toucher à la sourdine (si l’enceinte est en sourdine, elle le restera pour la diffusion de ce message -> pas de diffusion sonore) :

http://IP_serveur_web/chemin/vers/sonos/sonos.php?$message=Mon message à diffuser&volume=50

Pour diffuser « Mon message à diffuser » en forçant le niveau sonore à 50% et en désactivant la sourdine :

http://IP_serveur_web/chemin/vers/sonos/sonos.php?$message=Mon message à diffuser&volume=50&force_unmute=1

Voyons en pratique ce que cela donne sur une eedomus, en générant une alerte sonore lorsque notre département passe en vigilance orange (cf mon précédent article « La vigilance météo dans votre eedomus« ).

Sur notre eedomus, créons un actionneur HTTP.

Sauvegardez et continuez à éditer et passez à l’onglet « Valeurs ». Créez une nouvelle ligne en renseignant l’IP et le chemin où sont hébergés vos scripts. Dans les paramètres, complétons avec un message compréhensible, configurons le niveau sonore et sauvegardons.

Il ne vous reste plus alors qu’à ajouter cet actionneur HTTP dans la règle qui va bien.

Et voilà, vous serez averti dès lors que votre département passera en vigilance orange.

Le script joint à cette classe n’étant qu’un exemple à l’utilisation de la classe Sonos, votre imagination est alors votre seule limite… Faire une diffusion générale d’un même message simultanément sur plusieurs Sonos alors qu’il y a des lectures en cours différentes devient alors possible et très simple à mettre en œuvre par exemple…

Cette classe n’est pas complète, mais elle permet déjà pas mal de choses. Il me reste à y intégrer entre autre la gestion des groupes et des paires d’enceintes.

Les évolutions prochaines seront à suivre sur mon Github.

A propos de Fabien

Touche à tout dans le domaine de l'électronique et l'informatique tant chez moi qu'à mon boulot (réseaux, télécoms, radio, outils de supervision...), j'ai découvert la domotique en 2011. Ayant débuté avec un RFXCOM et un NAS Synology, j'ai testé la Zibase et la Vera lite avant de jeter mon dévolu sur une Eedomus. J'adore :-D

45 commentaires

  1. Raah, il va me faire passer à Sonos, le Fabien :p
    Dommage, je n’ai que des Squeezebox, et trop pour tout changer en Sonos…

  2. @Cédric.. pourquoi ? tu peux bien faire la même chose avec les SqueezeBox.. non ?
    Je suis en train de monter mon multi room et hormis l’aspect DIY, je ne vois pas ce qui différencie de Sonos?

  3. Petite erruer pour le fichier sonos.php dans le cadre du TTS, la ligne 15 ressemble à cela : $sonos_1->PlayTTS($message,$directory,$volume,$force_unmute); //Lecture du message

  4. @Flop: oui, je pense qu’il doit y avoir moyen d’adapter le plugin. Mais pas beaucoup de temps en ce moment :(

  5. Excellent, j’ai des sonos ;-)
    C’est quand qu’eedomus héberge ces belles classes php sur l’eedomus ?
    A+
    Domotics

  6. Très intéressant comme article :) !

    J’adore ton travail Fabien… et j’adore Planète Domotique pour les conseils et le suivi !
    Continuez comme ça.

    Pat

  7. Bonjour,

    Je débute en domotique avec ma ZIBASE. J’ai attentivement ton article, mais mon niveau ne me permet pas de tout comprendre sur le matériel nécessaire.
    J’avais dans l’idée d’utiliser mes SONOS pour diffuser des messages pré enregistrés piloter par la zibase suite à une ouverture de porte ou la sonnette.
    Peut tu me donner quelques piste .

    Merci d’avance

  8. Mise à jour du 16/06 :
    - correction de bugs mineurs
    - ajout de possibilité de dire le titre / auteur en cours de diffusion (merci tchex)
    - possibilité de faire dire des messages de plus de 100 caractères

  9. @arnaud, il te faut exécuter une action dès lors que ta sonnette est appuyée. Ensuite, dans cette action, appeler une URL (je sais plus si c’est possible), et dans l’URL tu indiques le messages que tu souhaites faire dire à tes Sonos.
    Sinon, il te faut créer un script PHP qui appelle ma fonction PlayTTS, fonction dans laquelle tu auras remplacé la ligne 470 $file = ‘x-file-cifs://’.$directory.’/’.$this->TTSToMp3($message,$lang); par $file = ‘x-file-cifs://chemin_vers_ton_MP3_a_lire;

  10. Fabien,

    merci pour les informations, n’ayant pas de NAS je pense qu’il n’est pas possible d’utiliser du PHP ?
    je souhiate m’orienter vers des commandes en URL , aurais tu la liste des commandes possible ou un lien pour les recuprer?

    Encore merci

    Arnaud

  11. Bonsoir .
    je me pose la question du multiroom et de sonos. mais est ce que l on peux aussi gerer avec eedomus (piloter et envoyer des messages comme karotz,, ou autres sons) sur d autres system. je pense a JONGO, Cabasse, Bose.les ampoules avec HP…. tout le monde sort un systeme wifi, mais qu en est il..
    j ai la chance de voyager , et je decouvre plein de HP wireless , wifi. dois je sauter le pas??
    comment envoyer les sons à ces HP?? depuis leedomus

    merci

    Franck

  12. Hi!

    Im rather new to Php but got a Sonos system set up and like to test out the TTS function. I Changed the sonos.php and updated with my IP adress to the Sonos controller. I then run the php script and expected some speech, but silence… What can be wrong?

  13. Hi Kristian,

    I’m not at home actually, I’ll check it when I’ll be back.

  14. bonsoir, j’ai essayer la classe, mais malheureusement rien ne marche. J’ai bien sur mis l’ip du sonos mais lorsque je lance l’url (http://192.168.0.120/sonos.php) rien ne se passe. J’ai essayer le php qui met le son a 50 %.
    un peut d’aide pour le debug est souhaitée.

  15. j’ai poursuivi mes essais et j’avais loupé la partie partage samba. Maintenant c’est fait mais je n’arrive toujours pas a communiquer avec le sonos avec cette class.php. J’utilise une linknxwebbox (boitier avec linux voyage et le tri linknx,eibd et knxweb2). Apache et le php sont bien installé. J’ai créer un répertoire sonos sous le répertoire www qui contient les plei droit et également le aprtage samba. J’ai mis le class.php et un sonos.php de test pour juste baisser le son. Lorsque je lance le php depuis safari (http://ipbox/sonos/sonos.php) la page reste vide et rien n’est fait sur le sonos. J’ai désactivé aussi l’appli sonos web qui permet de faire presque la même chose (prog en perl mais en plus compliqué, mais qui marche) mais sans succés.

  16. j’ai installé un serveur apache sous Windows et maintenant marche nickel. JE vais essayer de vois sous le linux ce qu’il y a ?

    Merci pour votre travail, je cherchais depuis longtemps une solution pour envoyer des messages sur mes sonos

  17. Bonsoir Laurent,

    Désolé pour la réponse tardive. Il faudrait que tu vérifies si sur ta linknxwebbox est installé et activé le module PHP curl.

  18. copy de phpinfo() pour la aprtie curl
    curl

    cURL support => enabled
    cURL Information => 7.21.0
    Age => 3
    Features
    AsynchDNS => No
    Debug => No
    GSS-Negotiate => Yes
    IDN => Yes
    IPv6 => Yes
    Largefile => Yes

    donc a priori oui.

  19. Bonjour
    et merci pour tout ce travail.
    J’ai essayé avec un serveur Apache doté de php 5.4 installé sous windows 7 (wamp server)
    Mais j’ai un souci avec l’appel $this->Upnp($url,$service,$action,$args,$filter)
    qui ne se termine jamais :
    Fatal error: Maximum execution time of 30 seconds exceeded in C:\wamp\www\sonos\sonos.class.php on line 78
    Je débute avec toiut ca et je ne sais pas ce qui cloche. Le fichier audio est bien créé, le volume du sonos s’ajuste, mais je n’entend pas mon message… Si quelqu’un a une idée je suis preneur ..

  20. Bonjour,
    je cherchais également un moyen de faire parler mes sonos; ceci semble fort adapté, mais je n’arrive a rien.
    j’ai un syno sur lequel est activé web service. Les .php sont dans syno/web/sonos.
    également une zibase
    ou faut-il définir $directory?
    merci

  21. de plus, pas de mp3 créé dans syno/web/sonos/audio
    j’ai créé audio manuellement

  22. j’ai progressé! le php du syno est 5.3xx, il fallait donc modifier quelques fonctions, majoritairement [] qui doit être remplacé par array(). et j’avais pris le mauvais sonos.php
    Le fichier mp3 est créé, mais reste vide et toujours avec un nom TTS-d41d8cd98f00b204e9800998ecf8427e.mp3
    Par contre si je le remplace par un mp3 valide en reprenant le même nom, ce fichier est lu, avec ajustement du volume, et reprise de la lecture, mais ceci peux importe ce que je mets en ?$message=xxx…
    une idée SVP?
    En tous cas, bravo à l’auteur pour ce script extrêmement bien étudié

  23. Bonjour Goth,

    Merci pour tes félicitations, ça motive. Je suis désolé de n’avoir pas pu répondre avant, pas mal de boulot avant les vacances. Je me replonge dans le script entre foie gras et saumon pendant ces 15 jours, j’ai moi aussi un Syno donc ça va aller vite.
    Pour le problème de fichier MP3 vide, je soupçonne un changement d’URL de l’API Google concernant le TTS.

    Je mets à jour le script d’ici la fin d’année.

    Bonnes fêtes

  24. Bonjour Fabien,
    tu viens de me combler! j’arrive a faire parler mes sonos! merci pour ce travail partagé.
    Après avoir cherché avec ma connaissance -10 en PHP durant des heures, je viens de me rendre compte que l’erreur se trouve dans la req http et non dans le script: http://IP_serveur_web/chemin/vers/sonos/sonos.php?$message=Mon message à diffuser – il ne faut pas mettre le $ avant message… maintenant plus qu’à intégrer tout ça à la zibase. merci encore

  25. @Goth
    Tu pourrais me donner plus d’informations sur l’utilisation de SONOS avec la Zibase.
    Quel type de serveur PHP utilise tu ?
    Quel fichiers as tu utilisés ?

    Merci d’avance pour tes réponses

    Arnaud

  26. Arnaud,

    Un serveur web classique, hébergé chez toi, fait l’affaire. Soit sur un Raspberry, soit un Synology, soit un PC sous Linux ou Windows, etc… Il suffit juste de s’assurer que PHP est installé (ça l’est par défaut maintenant).
    Il te faut utiliser, pour du TTS, les fichiers sonos.class.php et sonos.tts.php, placés dans le même répertoire de ton serveur web.
    Ensuite, il faut appeler l’URL http://IP_SERVEUR_WEB/dossier/sonos.tts.php?message=Mon message, en remplaçant « mon message » par le message que tu souhaites faire dire à ton Sonos.

  27. Chez moi il tourne sur un Synology. Je m’en sers par exemple pour annoncer une porte de garage ouverte sur les HP de la SDB (capteur de portes sonos), ou annoncer la fermeture auto des volets à l’avance pour ne pas se faire avoir sur la terrasse…
    Faire tout de même attention avec la version de php et de certaines fonctions qui changent.

  28. coquille: (capteur de porte, zibase, sonos)

  29. Bonjour et Bonne année,
    Est il possible d’avoir la version en PHP5.3 du fichier class.PHP ? mon niveau est à -1000 en php et il m’est difficile de modifier
    Merci beaucoup pour tout ceci et j’espère que ça finira par fonctionner pour moi.
    (NAS syno DSM à jour – aucun fichier MP3 ne s’enregistre)
    Merci

  30. Bonjour et bonne année,

    Je vais regarder ça, mais normalement le script est compatible avec les versions les plus récentes de PHP. Sur mon Syno cela fonctionne, mes TTS s’enregistrent au format MP3 et sont lus. ;-)

  31. Bonjour, merci pour votre réponse, je me suis basé sur le message de Goth et je semble avoir également eu une confirmation en ce sens suite à une analyse de la syntaxe du code qui renvoie une erreur pour PHP5.3 et pas pour PHP5.4. Désolé je comprend à peine ce que je dis ;) mais j’ai récupéré une version qui semble plus ancienne sur le forum eedomus avec moins d’options et qui fonctionne : il n’y a pas de [] dans le code. J’aimerai cependant avoir cette dernière version : à voir si Goth voit ce message…
    Sinon, c’est vrai que c’est tout simplement excellent comme fonction et Madame Google a une voix sympa ;)

  32. Bonjour Domosapiens,

    Essaie de remplacer le contenu du fichier sonos.class.php avec la version disponible à cette adresse : https://raw.github.com/DjMomo/sonos/debug/sonos.class.php et tiens moi au courant.

  33. Bonjour,
    Toujours une erreur Parse error: syntax error, unexpected ‘[' in /volume1/web/sonos/sonos.class.php on line 543
    Les crochets semblent poser problème avec la version PHP 5.3.27 (syno 210j DSM 4.3-3810), il ne semble pas y avoir moyen d'installer la version 5.4
    La ligne 543 : $out = [...
    La ligne 565 contient ['host']
    Ligne 612 : [$sock]
    Ligne 680 : ['roomName']
    Merci encore

  34. Salut à tous et meilleurs voeux!
    Domosapiens, donne ton mail, je pourrai t’envoyer la version modifiée qui tourne chez moi, avec l’accord de Fabien bien-sur.

  35. Bonjour et merci Goth,
    essjay [AT] club [-] internet [.] fr
    et merci les crochets ;)

  36. Goth, pas de soucis.

    Domosapiens, si tu as quelques minutes pour tester ce fichier là : https://raw.github.com/DjMomo/sonos/debug/sonos.class.php
    Merci ;)

  37. Bonjour,
    Toujours problème de Parse error: syntax error, unexpected ‘[' in /volume1/web/sonos/sonos.class.php on line 565 probablement le ['host']
    Je pense que ça posera problème aussi à la 680 : ['roomName']
    J’attends de voir le fichier de Goth
    Merci en tout cas pour les efforts ;)

  38. Là, je pense que c’est la bonne :-)

  39. Oups, rappel de l’URL (qui n’a pas changé) : https://raw.github.com/DjMomo/sonos/debug/sonos.class.php

  40. Bonjour,
    BINGO ça fonctionne ! un grand merci ;)
    Avec tout ça, je me rends compte que je ne connais pas la commande à lancer pour avoir « cette chanson s’appelle »
    …php?message= comment s’appelle cette chanson ?? ;)

  41. bonsoir,
    je rencontre le pb suivant.
    le mp3 se créé bien sur mon syno dans le répertoire audio/fr/ , par contre lorsque le sonos veut le lire, je vois apparaitre le msg suivant sur l’application sonos sur mon telephone « impossible de lire TTS-xxxxxxxxxx.mp » « impossible de se connecter à //0/audio »
    J’ai bien partagé le répertoire web sur le syno et j’ai ajouté dans les paramétres de bibliothéque au niveau du syno le répertoire web.
    Merci pour votre aide.

  42. J’ai refait mes déclarations au niveau de l’application sonos et çà marche !!!
    Merci pour cette excellente appli.

  43. Bonjour, je n’arrive toujours pas a faire parler mon sonos, le mp3 se crée, mais j’ai l’erreur
     » Notice: Undefined offset: 1 in C:\wamp\www\sonos\sonos.class.php on line 90″
    ca coince dans la fonction Filter, a la ligne return $matches[1]
    J’ai pourtant PHP 5.4.12 sur un serveur apache sous windows ….
    merci pour votre aide

  44. Bonjour !

    Juste une petite question :) Quel serait-la syntaxe pour utiliser les autres fonctions ? (Play() Pause() etc…)

    Merci d’avance ! :D

    Cordialement, Zegorax

  45. C’est bon finalement ! Petite erreur de code de ma part ;)

Répondre

Votre adresse email ne sera pas publiée. Les champs obligatoires sont marqués d'une étoile *

*

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Revenir en haut de la page