<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://mydil.tala-informatique.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tala</id>
	<title>mydil - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://mydil.tala-informatique.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tala"/>
	<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Sp%C3%A9cial:Contributions/Tala"/>
	<updated>2026-04-08T23:54:13Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.39.17</generator>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=338</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=338"/>
		<updated>2019-07-23T16:50:14Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
* Pour le Banana PI:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Pour le Raspberry PI:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer1.0 | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039; | grep plugins)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
Pour le Banana Pi M1:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Pour le Raspberry Pi 2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y wiringpi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détection de musique ==&lt;br /&gt;
Il est possible de détecter si de la musique est en train d&#039;être jouée sur le PI grâce à la commande suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si cette commande renvoie &#039;&#039;1&#039;&#039; cela veut dire que &#039;&#039;state: RUNNING&#039;&#039; est présent dans un des fichiers d&#039;une des cartes son.&lt;br /&gt;
&lt;br /&gt;
Cette commande peu permettre de piloter un amplificateur au travers d&#039;un relais piloté par une GPIO...&lt;br /&gt;
Nous aurions le script &#039;&#039;/opt/amp-relay.php&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/php&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
function main($argv){&lt;br /&gt;
        // Amp relay GPIO&lt;br /&gt;
        $GPIO = 1;&lt;br /&gt;
        $cmd = &#039;cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&#039;;&lt;br /&gt;
        shell_exec(&#039;gpio mode &#039;.$GPIO.&#039; output&#039;);&lt;br /&gt;
        shell_exec(&#039;gpio write &#039;.$GPIO.&#039; 0&#039;);&lt;br /&gt;
        while(1){&lt;br /&gt;
                exec($cmd, $output, $ret);&lt;br /&gt;
                if($ret==0){&lt;br /&gt;
                        shell_exec(&#039;gpio write &#039;.$GPIO.&#039; &#039;.$output[0]);&lt;br /&gt;
                        unset($output);&lt;br /&gt;
                }&lt;br /&gt;
                usleep(50);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
main($argv);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
avec un petit script systemctl (&#039;&#039;/etc/systemd/system/ampli-relay.service&#039;&#039;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Aplificator relay service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/opt/amp-relay.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On n&#039;oubliera pas de rendre le fichier exécutable et d&#039;activer le service:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /etc/amp-relay.php&lt;br /&gt;
# systemctl start amp-relay.service&lt;br /&gt;
# systemctl enable amp-relay.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
=== Paramétrage de la carte===&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y bluez bluez-tools bluealsa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut créer le fichier &#039;&#039;/etc/bluetooth/audio.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[General]&lt;br /&gt;
Enable=Source,Sink,Media,Socket&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
éditez le fichier &#039;&#039;/etc/bluetooth/main.conf&#039;&#039; pour modifier les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
Class = 0x00041C&lt;br /&gt;
...&lt;br /&gt;
DiscoverableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
PairableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut ensuite redémarrer le service &#039;&#039;bluetooth&#039;&#039; pour appairer le téléphone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart bluetooth&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Déclaration de services===&lt;br /&gt;
Avant d&#039;aller plus loin, nous allons enregistrer deux commandes en tant que service système:&lt;br /&gt;
* &#039;&#039;bluealsa -p a2dp-sink &amp;amp;&#039;&#039; : qui permet de déclarer le PI comme point de terminaison A2DP (musique);&lt;br /&gt;
* &#039;&#039;bluealsa-aplay 00:00:00:00:00:00&#039;&#039; : qui permet de laisser passer la musique sur la carte son par défaut.&lt;br /&gt;
Pour cela nous allons utiliser la même technique que pour Rygel (plus haut):&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-a2dp.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa A2DP service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa -p a2dp-sink&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-aplay.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa Aplay authorization service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa-aplay 00:00:00:00:00:00&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à enregistrer les services:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start blue-a2dp.service&lt;br /&gt;
# systemctl start blue-aplay.service&lt;br /&gt;
# systemctl enable blue-aplay.service&lt;br /&gt;
# systemctl enable blue-a2dp.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Appairage ===&lt;br /&gt;
Il faut lancer l&#039;utilitaire &#039;&#039;bluetoothctl&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# bluetoothctl&lt;br /&gt;
Agent registered&lt;br /&gt;
[bluetooth]# &lt;br /&gt;
[CHG] Device 0C:2C:54:1B:A3:A9 Connected: yes&lt;br /&gt;
[tala_phone]#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=337</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=337"/>
		<updated>2019-07-19T18:35:38Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Détection de musique */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
* Pour le Banana PI:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Pour le Raspberry PI:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | grep -v python | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
Pour le Banana Pi M1:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Pour le Raspberry Pi 2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y wiringpi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détection de musique ==&lt;br /&gt;
Il est possible de détecter si de la musique est en train d&#039;être jouée sur le PI grâce à la commande suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si cette commande renvoie &#039;&#039;1&#039;&#039; cela veut dire que &#039;&#039;state: RUNNING&#039;&#039; est présent dans un des fichiers d&#039;une des cartes son.&lt;br /&gt;
&lt;br /&gt;
Cette commande peu permettre de piloter un amplificateur au travers d&#039;un relais piloté par une GPIO...&lt;br /&gt;
Nous aurions le script &#039;&#039;/opt/amp-relay.php&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/php&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
function main($argv){&lt;br /&gt;
        // Amp relay GPIO&lt;br /&gt;
        $GPIO = 1;&lt;br /&gt;
        $cmd = &#039;cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&#039;;&lt;br /&gt;
        shell_exec(&#039;gpio mode &#039;.$GPIO.&#039; output&#039;);&lt;br /&gt;
        shell_exec(&#039;gpio write &#039;.$GPIO.&#039; 0&#039;);&lt;br /&gt;
        while(1){&lt;br /&gt;
                exec($cmd, $output, $ret);&lt;br /&gt;
                if($ret==0){&lt;br /&gt;
                        shell_exec(&#039;gpio write &#039;.$GPIO.&#039; &#039;.$output[0]);&lt;br /&gt;
                        unset($output);&lt;br /&gt;
                }&lt;br /&gt;
                usleep(50);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
main($argv);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
avec un petit script systemctl (&#039;&#039;/etc/systemd/system/ampli-relay.service&#039;&#039;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Aplificator relay service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/opt/amp-relay.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On n&#039;oubliera pas de rendre le fichier exécutable et d&#039;activer le service:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /etc/amp-relay.php&lt;br /&gt;
# systemctl start amp-relay.service&lt;br /&gt;
# systemctl enable amp-relay.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
=== Paramétrage de la carte===&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y bluez bluez-tools bluealsa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut créer le fichier &#039;&#039;/etc/bluetooth/audio.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[General]&lt;br /&gt;
Enable=Source,Sink,Media,Socket&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
éditez le fichier &#039;&#039;/etc/bluetooth/main.conf&#039;&#039; pour modifier les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
Class = 0x00041C&lt;br /&gt;
...&lt;br /&gt;
DiscoverableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
PairableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut ensuite redémarrer le service &#039;&#039;bluetooth&#039;&#039; pour appairer le téléphone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart bluetooth&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Déclaration de services===&lt;br /&gt;
Avant d&#039;aller plus loin, nous allons enregistrer deux commandes en tant que service système:&lt;br /&gt;
* &#039;&#039;bluealsa -p a2dp-sink &amp;amp;&#039;&#039; : qui permet de déclarer le PI comme point de terminaison A2DP (musique);&lt;br /&gt;
* &#039;&#039;bluealsa-aplay 00:00:00:00:00:00&#039;&#039; : qui permet de laisser passer la musique sur la carte son par défaut.&lt;br /&gt;
Pour cela nous allons utiliser la même technique que pour Rygel (plus haut):&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-a2dp.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa A2DP service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa -p a2dp-sink&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-aplay.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa Aplay authorization service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa-aplay 00:00:00:00:00:00&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à enregistrer les services:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start blue-a2dp.service&lt;br /&gt;
# systemctl start blue-aplay.service&lt;br /&gt;
# systemctl enable blue-aplay.service&lt;br /&gt;
# systemctl enable blue-a2dp.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Appairage ===&lt;br /&gt;
Il faut lancer l&#039;utilitaire &#039;&#039;bluetoothctl&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# bluetoothctl&lt;br /&gt;
Agent registered&lt;br /&gt;
[bluetooth]# &lt;br /&gt;
[CHG] Device 0C:2C:54:1B:A3:A9 Connected: yes&lt;br /&gt;
[tala_phone]#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=336</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=336"/>
		<updated>2019-07-19T18:31:21Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Détection de musique */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
* Pour le Banana PI:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Pour le Raspberry PI:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | grep -v python | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
Pour le Banana Pi M1:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Pour le Raspberry Pi 2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y wiringpi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détection de musique ==&lt;br /&gt;
Il est possible de détecter si de la musique est en train d&#039;être jouée sur le PI grâce à la commande suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si cette commande renvoie &#039;&#039;1&#039;&#039; cela veut dire que &#039;&#039;state: RUNNING&#039;&#039; est présent dans un des fichiers d&#039;une des cartes son.&lt;br /&gt;
&lt;br /&gt;
Cette commande peu permettre de piloter un amplificateur au travers d&#039;un relais piloté par une GPIO...&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/php&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
function main($argv){&lt;br /&gt;
        // Amp relay GPIO&lt;br /&gt;
        $GPIO = 1;&lt;br /&gt;
        $cmd = &#039;cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&#039;;&lt;br /&gt;
        shell_exec(&#039;gpio mode &#039;.$GPIO.&#039; output&#039;);&lt;br /&gt;
        shell_exec(&#039;gpio write &#039;.$GPIO.&#039; 0&#039;);&lt;br /&gt;
        while(1){&lt;br /&gt;
                exec($cmd, $output, $ret);&lt;br /&gt;
                if($ret==0){&lt;br /&gt;
                        echo &#039;gpio write &#039;.$GPIO.&#039; &#039;.$output[0].&amp;quot;\n&amp;quot;;&lt;br /&gt;
                        shell_exec(&#039;gpio write &#039;.$GPIO.&#039; &#039;.$output[0]);&lt;br /&gt;
                        unset($output);&lt;br /&gt;
                }&lt;br /&gt;
                usleep(50);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
main($argv);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
=== Paramétrage de la carte===&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y bluez bluez-tools bluealsa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut créer le fichier &#039;&#039;/etc/bluetooth/audio.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[General]&lt;br /&gt;
Enable=Source,Sink,Media,Socket&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
éditez le fichier &#039;&#039;/etc/bluetooth/main.conf&#039;&#039; pour modifier les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
Class = 0x00041C&lt;br /&gt;
...&lt;br /&gt;
DiscoverableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
PairableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut ensuite redémarrer le service &#039;&#039;bluetooth&#039;&#039; pour appairer le téléphone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart bluetooth&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Déclaration de services===&lt;br /&gt;
Avant d&#039;aller plus loin, nous allons enregistrer deux commandes en tant que service système:&lt;br /&gt;
* &#039;&#039;bluealsa -p a2dp-sink &amp;amp;&#039;&#039; : qui permet de déclarer le PI comme point de terminaison A2DP (musique);&lt;br /&gt;
* &#039;&#039;bluealsa-aplay 00:00:00:00:00:00&#039;&#039; : qui permet de laisser passer la musique sur la carte son par défaut.&lt;br /&gt;
Pour cela nous allons utiliser la même technique que pour Rygel (plus haut):&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-a2dp.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa A2DP service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa -p a2dp-sink&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-aplay.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa Aplay authorization service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa-aplay 00:00:00:00:00:00&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à enregistrer les services:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start blue-a2dp.service&lt;br /&gt;
# systemctl start blue-aplay.service&lt;br /&gt;
# systemctl enable blue-aplay.service&lt;br /&gt;
# systemctl enable blue-a2dp.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Appairage ===&lt;br /&gt;
Il faut lancer l&#039;utilitaire &#039;&#039;bluetoothctl&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# bluetoothctl&lt;br /&gt;
Agent registered&lt;br /&gt;
[bluetooth]# &lt;br /&gt;
[CHG] Device 0C:2C:54:1B:A3:A9 Connected: yes&lt;br /&gt;
[tala_phone]#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=335</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=335"/>
		<updated>2019-07-19T17:42:40Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
* Pour le Banana PI:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Pour le Raspberry PI:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | grep -v python | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
Pour le Banana Pi M1:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Pour le Raspberry Pi 2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y wiringpi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détection de musique ==&lt;br /&gt;
Il est possible de détecter si de la musique est en train d&#039;être jouée sur le PI grâce à la commande suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si cette commande renvoie &#039;&#039;1&#039;&#039; cela veut dire que &#039;&#039;state: RUNNING&#039;&#039; est présent dans un des fichiers d&#039;une des cartes son.&lt;br /&gt;
&lt;br /&gt;
Cette commande peu permettre de piloter un amplificateur au travers d&#039;un relais piloté par une GPIO...&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
=== Paramétrage de la carte===&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y bluez bluez-tools bluealsa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut créer le fichier &#039;&#039;/etc/bluetooth/audio.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[General]&lt;br /&gt;
Enable=Source,Sink,Media,Socket&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
éditez le fichier &#039;&#039;/etc/bluetooth/main.conf&#039;&#039; pour modifier les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
Class = 0x00041C&lt;br /&gt;
...&lt;br /&gt;
DiscoverableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
PairableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut ensuite redémarrer le service &#039;&#039;bluetooth&#039;&#039; pour appairer le téléphone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart bluetooth&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Déclaration de services===&lt;br /&gt;
Avant d&#039;aller plus loin, nous allons enregistrer deux commandes en tant que service système:&lt;br /&gt;
* &#039;&#039;bluealsa -p a2dp-sink &amp;amp;&#039;&#039; : qui permet de déclarer le PI comme point de terminaison A2DP (musique);&lt;br /&gt;
* &#039;&#039;bluealsa-aplay 00:00:00:00:00:00&#039;&#039; : qui permet de laisser passer la musique sur la carte son par défaut.&lt;br /&gt;
Pour cela nous allons utiliser la même technique que pour Rygel (plus haut):&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-a2dp.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa A2DP service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa -p a2dp-sink&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-aplay.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa Aplay authorization service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa-aplay 00:00:00:00:00:00&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à enregistrer les services:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start blue-a2dp.service&lt;br /&gt;
# systemctl start blue-aplay.service&lt;br /&gt;
# systemctl enable blue-aplay.service&lt;br /&gt;
# systemctl enable blue-a2dp.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Appairage ===&lt;br /&gt;
Il faut lancer l&#039;utilitaire &#039;&#039;bluetoothctl&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# bluetoothctl&lt;br /&gt;
Agent registered&lt;br /&gt;
[bluetooth]# &lt;br /&gt;
[CHG] Device 0C:2C:54:1B:A3:A9 Connected: yes&lt;br /&gt;
[tala_phone]#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=334</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=334"/>
		<updated>2019-07-19T17:36:56Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Déclaration de services */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
Pour le Banana Pi M1:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Pour le Raspberry Pi 2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y wiringpi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détection de musique ==&lt;br /&gt;
Il est possible de détecter si de la musique est en train d&#039;être jouée sur le PI grâce à la commande suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si cette commande renvoie &#039;&#039;1&#039;&#039; cela veut dire que &#039;&#039;state: RUNNING&#039;&#039; est présent dans un des fichiers d&#039;une des cartes son.&lt;br /&gt;
&lt;br /&gt;
Cette commande peu permettre de piloter un amplificateur au travers d&#039;un relais piloté par une GPIO...&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
=== Paramétrage de la carte===&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y bluez bluez-tools bluealsa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut créer le fichier &#039;&#039;/etc/bluetooth/audio.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[General]&lt;br /&gt;
Enable=Source,Sink,Media,Socket&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
éditez le fichier &#039;&#039;/etc/bluetooth/main.conf&#039;&#039; pour modifier les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
Class = 0x00041C&lt;br /&gt;
...&lt;br /&gt;
DiscoverableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
PairableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut ensuite redémarrer le service &#039;&#039;bluetooth&#039;&#039; pour appairer le téléphone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart bluetooth&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Déclaration de services===&lt;br /&gt;
Avant d&#039;aller plus loin, nous allons enregistrer deux commandes en tant que service système:&lt;br /&gt;
* &#039;&#039;bluealsa -p a2dp-sink &amp;amp;&#039;&#039; : qui permet de déclarer le PI comme point de terminaison A2DP (musique);&lt;br /&gt;
* &#039;&#039;bluealsa-aplay 00:00:00:00:00:00&#039;&#039; : qui permet de laisser passer la musique sur la carte son par défaut.&lt;br /&gt;
Pour cela nous allons utiliser la même technique que pour Rygel (plus haut):&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-a2dp.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa A2DP service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa -p a2dp-sink&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-aplay.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa Aplay authorization service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa-aplay 00:00:00:00:00:00&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à enregistrer les services:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start blue-a2dp.service&lt;br /&gt;
# systemctl start blue-aplay.service&lt;br /&gt;
# systemctl enable blue-aplay.service&lt;br /&gt;
# systemctl enable blue-a2dp.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Appairage ===&lt;br /&gt;
Il faut lancer l&#039;utilitaire &#039;&#039;bluetoothctl&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# bluetoothctl&lt;br /&gt;
Agent registered&lt;br /&gt;
[bluetooth]# &lt;br /&gt;
[CHG] Device 0C:2C:54:1B:A3:A9 Connected: yes&lt;br /&gt;
[tala_phone]#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=333</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=333"/>
		<updated>2019-07-19T17:28:57Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Déclaration de services */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
Pour le Banana Pi M1:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Pour le Raspberry Pi 2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y wiringpi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détection de musique ==&lt;br /&gt;
Il est possible de détecter si de la musique est en train d&#039;être jouée sur le PI grâce à la commande suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si cette commande renvoie &#039;&#039;1&#039;&#039; cela veut dire que &#039;&#039;state: RUNNING&#039;&#039; est présent dans un des fichiers d&#039;une des cartes son.&lt;br /&gt;
&lt;br /&gt;
Cette commande peu permettre de piloter un amplificateur au travers d&#039;un relais piloté par une GPIO...&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
=== Paramétrage de la carte===&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y bluez bluez-tools bluealsa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut créer le fichier &#039;&#039;/etc/bluetooth/audio.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[General]&lt;br /&gt;
Enable=Source,Sink,Media,Socket&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
éditez le fichier &#039;&#039;/etc/bluetooth/main.conf&#039;&#039; pour modifier les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
Class = 0x00041C&lt;br /&gt;
...&lt;br /&gt;
DiscoverableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
PairableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut ensuite redémarrer le service &#039;&#039;bluetooth&#039;&#039; pour appairer le téléphone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart bluetooth&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Déclaration de services===&lt;br /&gt;
Avant d&#039;aller plus loin, nous allons enregistrer deux commandes en tant que service système:&lt;br /&gt;
* &#039;&#039;bluealsa -p a2dp-sink &amp;amp;&#039;&#039; : qui permet de déclarer le PI comme point de terminaison A2DP (musique);&lt;br /&gt;
* &#039;&#039;bluealsa-aplay 00:00:00:00:00:00&#039;&#039; : qui permet de laisser passer la musique sur la carte son par défaut.&lt;br /&gt;
Pour cela nous allons utiliser la même technique que pour Rygel (plus haut):&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-a2dp.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa A2DP service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa -p a2dp-sink&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-aplay.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa Aplay authorization service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa-aplay 00:00:00:00:00:00 &amp;amp;&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à enregistrer les services:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start blue-a2dp.service&lt;br /&gt;
# systemctl start blue-aplay.service&lt;br /&gt;
# systemctl enable blue-aplay.service&lt;br /&gt;
# systemctl enable blue-a2dp.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Appairage ===&lt;br /&gt;
Il faut lancer l&#039;utilitaire &#039;&#039;bluetoothctl&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# bluetoothctl&lt;br /&gt;
Agent registered&lt;br /&gt;
[bluetooth]# &lt;br /&gt;
[CHG] Device 0C:2C:54:1B:A3:A9 Connected: yes&lt;br /&gt;
[tala_phone]#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=332</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=332"/>
		<updated>2019-07-19T17:26:52Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Ajout du bluetooth */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
Pour le Banana Pi M1:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Pour le Raspberry Pi 2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y wiringpi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détection de musique ==&lt;br /&gt;
Il est possible de détecter si de la musique est en train d&#039;être jouée sur le PI grâce à la commande suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si cette commande renvoie &#039;&#039;1&#039;&#039; cela veut dire que &#039;&#039;state: RUNNING&#039;&#039; est présent dans un des fichiers d&#039;une des cartes son.&lt;br /&gt;
&lt;br /&gt;
Cette commande peu permettre de piloter un amplificateur au travers d&#039;un relais piloté par une GPIO...&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
=== Paramétrage de la carte===&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y bluez bluez-tools bluealsa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut créer le fichier &#039;&#039;/etc/bluetooth/audio.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[General]&lt;br /&gt;
Enable=Source,Sink,Media,Socket&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
éditez le fichier &#039;&#039;/etc/bluetooth/main.conf&#039;&#039; pour modifier les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
Class = 0x00041C&lt;br /&gt;
...&lt;br /&gt;
DiscoverableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
PairableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut ensuite redémarrer le service &#039;&#039;bluetooth&#039;&#039; pour appairer le téléphone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart bluetooth&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Déclaration de services===&lt;br /&gt;
Avant d&#039;aller plus loin, nous allons enregistrer deux commandes en tant que service système:&lt;br /&gt;
* &#039;&#039;bluealsa -p a2dp-sink &amp;amp;&#039;&#039; : qui permet de déclarer le PI comme point de terminaison A2DP (musique);&lt;br /&gt;
* &#039;&#039;bluealsa-aplay 00:00:00:00:00:00&#039;&#039; : qui permet de laisser passer la musique sur la carte son par défaut.&lt;br /&gt;
Pour cela nous allons utiliser la même technique que pour Rygel (plus haut):&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-a2dp.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa A2DP service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa -p a2dp-sink &amp;amp;&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Dans le fichier &#039;&#039;/etc/systemd/system/blue-aplay.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Alsa Aplay authorization service&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
ExecStart=/usr/bin/bluealsa-aplay 00:00:00:00:00:00 &amp;amp;&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à enregistrer les services:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start blue-a2dp.service&lt;br /&gt;
# systemctl start blue-aplay.service&lt;br /&gt;
# systemctl enable blue-aplay.service&lt;br /&gt;
# systemctl enable blue-a2dp.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Appairage ===&lt;br /&gt;
Il faut lancer l&#039;utilitaire &#039;&#039;bluetoothctl&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# bluetoothctl&lt;br /&gt;
Agent registered&lt;br /&gt;
[bluetooth]# &lt;br /&gt;
[CHG] Device 0C:2C:54:1B:A3:A9 Connected: yes&lt;br /&gt;
[tala_phone]#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=331</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=331"/>
		<updated>2019-07-19T17:12:09Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Ajout du bluetooth */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
Pour le Banana Pi M1:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Pour le Raspberry Pi 2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y wiringpi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détection de musique ==&lt;br /&gt;
Il est possible de détecter si de la musique est en train d&#039;être jouée sur le PI grâce à la commande suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si cette commande renvoie &#039;&#039;1&#039;&#039; cela veut dire que &#039;&#039;state: RUNNING&#039;&#039; est présent dans un des fichiers d&#039;une des cartes son.&lt;br /&gt;
&lt;br /&gt;
Cette commande peu permettre de piloter un amplificateur au travers d&#039;un relais piloté par une GPIO...&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y bluez bluez-tools bluealsa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut créer le fichier &#039;&#039;/etc/bluetooth/audio.conf&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[General]&lt;br /&gt;
Enable=Source,Sink,Media,Socket&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
éditer le fichier &#039;&#039;/etc/bluetooth/main.conf&#039;&#039; pour modifier les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
Class = 0x00041C&lt;br /&gt;
...&lt;br /&gt;
DiscoverableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
PairableTimeout = 0&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut ensuite redémarrer le service &#039;&#039;bluetooth&#039;&#039; pour appairer le téléphone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart bluetooth&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut lancer l&#039;utilitaire &#039;&#039;bluetoothctl&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# bluetoothctl&lt;br /&gt;
Agent registered&lt;br /&gt;
[bluetooth]# &lt;br /&gt;
[CHG] Device 0C:2C:54:1B:A3:A9 Connected: yes&lt;br /&gt;
[tala_phone]#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=330</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=330"/>
		<updated>2019-07-19T15:20:12Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
Pour le Banana Pi M1:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Pour le Raspberry Pi 2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt install -y wiringpi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détection de musique ==&lt;br /&gt;
Il est possible de détecter si de la musique est en train d&#039;être jouée sur le PI grâce à la commande suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si cette commande renvoie &#039;&#039;1&#039;&#039; cela veut dire que &#039;&#039;state: RUNNING&#039;&#039; est présent dans un des fichiers d&#039;une des cartes son.&lt;br /&gt;
&lt;br /&gt;
Cette commande peu permettre de piloter un amplificateur au travers d&#039;un relais piloté par une GPIO...&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install -y bluez bluez-tools&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=329</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=329"/>
		<updated>2019-07-19T15:13:43Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détection de musique ==&lt;br /&gt;
Il est possible de détecter si de la musique est en train d&#039;être jouée sur le PI grâce à la commande suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si cette commande renvoie &#039;&#039;1&#039;&#039; cela veut dire que &#039;&#039;state: RUNNING&#039;&#039; est présent dans un des fichiers d&#039;une des cartes son.&lt;br /&gt;
&lt;br /&gt;
Cette commande peu permettre de piloter un amplificateur au travers d&#039;un relais piloté par une GPIO...&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install -y bluez bluez-tools&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=328</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=328"/>
		<updated>2019-07-17T04:17:20Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Détection de musique */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détection de musique ==&lt;br /&gt;
Il est possible de détecter si de la musique est en train d&#039;être jouée sur le PI grâce à la commande suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si cette commande renvoie &#039;&#039;1&#039;&#039; cela veut dire que &#039;&#039;state: RUNNING&#039;&#039; est présent dans un des fichiers d&#039;une des cartes son.&lt;br /&gt;
&lt;br /&gt;
Cette commande peu permettre de piloter un amplificateur au travers d&#039;un relais piloté par une GPIO...&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install -y bluez bluez-tools&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=327</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=327"/>
		<updated>2019-07-17T03:09:03Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Ajout du bluetooth */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détection de musique ==&lt;br /&gt;
Il est possible de détecter si de la musique est en train d&#039;être jouée sur le PI grâce à la commande suivante:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si cette commande renvoie &#039;&#039;1&#039;&#039; cela veut dire que &#039;&#039;state: RUNNING&#039;&#039; est présent dans un des fichiers d&#039;une des cartes son.&lt;br /&gt;
&lt;br /&gt;
Cette commande peu permettre de piloter un amplificateur...&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install -y bluez bluez-tools&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=326</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=326"/>
		<updated>2019-07-16T17:24:26Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Utilisation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install -y bluez bluez-tools&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=325</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=325"/>
		<updated>2019-07-16T17:24:11Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Installation de WiringPI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== WiringPI==&lt;br /&gt;
===Installation===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Utilisation===&lt;br /&gt;
Pour la lecture des états&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio readall&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |&lt;br /&gt;
 |   2 |   8 |   SDA.1 | ALT5 | 0 |  3 || 4  |   |      | 5V      |     |     |&lt;br /&gt;
 |   3 |   9 |   SCL.1 | ALT5 | 0 |  5 || 6  |   |      | 0v      |     |     |&lt;br /&gt;
 |   4 |   7 | GPIO. 7 |   IN | 0 |  7 || 8  | 1 | ALT2 | TxD     | 15  | 14  |&lt;br /&gt;
 |     |     |      0v |      |   |  9 || 10 | 0 | IN   | RxD     | 16  | 15  |&lt;br /&gt;
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |&lt;br /&gt;
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |&lt;br /&gt;
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |&lt;br /&gt;
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |&lt;br /&gt;
 |  10 |  12 |    MOSI | ALT5 | 0 | 19 || 20 |   |      | 0v      |     |     |&lt;br /&gt;
 |   9 |  13 |    MISO | ALT5 | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |&lt;br /&gt;
 |  11 |  14 |    SCLK | ALT5 | 0 | 23 || 24 | 0 | ALT5 | CE0     | 10  | 8   |&lt;br /&gt;
 |     |     |      0v |      |   | 25 || 26 | 0 | ALT5 | CE1     | 11  | 7   |&lt;br /&gt;
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |&lt;br /&gt;
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |&lt;br /&gt;
 |   6 |  22 | GPIO.22 | ALT4 | 0 | 31 || 32 | 0 | ALT4 | GPIO.26 | 26  | 12  |&lt;br /&gt;
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |&lt;br /&gt;
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |&lt;br /&gt;
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |&lt;br /&gt;
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |&lt;br /&gt;
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+&lt;br /&gt;
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |&lt;br /&gt;
 +-----+-----+---------+------+---+--Banana Pro--+---+------+---------+-----+-----+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ou d&#039;un état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# gpio read 1&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Changement d&#039;état:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gpio -1 write 8 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install -y bluez bluez-tools&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=324</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=324"/>
		<updated>2019-07-16T16:48:17Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Changement de la carte son par défaut */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;br /&gt;
&lt;br /&gt;
== Installation de WiringPI==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd /opt&lt;br /&gt;
# git clone https://github.com/LeMaker/WiringLMK.git &lt;br /&gt;
# cd WiringLMK&lt;br /&gt;
# chmod +x ./build&lt;br /&gt;
# ./build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ajout du bluetooth ==&lt;br /&gt;
Il faut d&#039;abord installer blueZ:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install -y bluez bluez-tools&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=323</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=323"/>
		<updated>2019-07-16T10:26:24Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Ajustement du volume */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;br /&gt;
== Changement de la carte son par défaut ==&lt;br /&gt;
Une fois la carte son USB installée, il suffit d&#039;utiliser la commande suivante pour voir son identifiant:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: sun4icodec [sun4i-codec], device 0: CDC PCM Codec-0 []&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]&lt;br /&gt;
  Subdevices: 0/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La carte son avec l&#039;ID &#039;&#039;0&#039;&#039; est celle intégrée au PI, celle avec l&#039;ID &#039;&#039;1&#039;&#039; est la carte USB.&lt;br /&gt;
Pour dire à ALSA que c&#039;est la carte avec l&#039;ID &#039;&#039;1&#039;&#039; que l&#039;on veut par défaut, il suffit de créer le fichier &#039;&#039;/etc/asound.conf&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults.pcm.card 1&lt;br /&gt;
defaults.ctl.card 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
La configuration est appliquée après un redémarrage !&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=322</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=322"/>
		<updated>2019-06-19T13:44:09Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Enceinte armbian */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Création du fichier de service ==&lt;br /&gt;
Il suffit de créer le fichier &#039;&#039;/etc/systemd/system/rygel.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Rygel service&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=/usr/bin/rygel -g 5&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
&lt;br /&gt;
# Configures the time to wait before service is stopped forcefully.&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On peut lancer le service et l&#039;activer au démarrage&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start rygel&lt;br /&gt;
# systemctl enable rygel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Désactivation des logs ==&lt;br /&gt;
Comme l&#039;enceinte n&#039;est pas à proprement parler un serveur exécutant un service critique, on peut désactiver le système de logging pour économiser la durée de vie de la carte SD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl stop rsyslog&lt;br /&gt;
# systemctl disable rsyslog&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Ajustement du volume ==&lt;br /&gt;
Il faut maintenant mettre le volume au maximum coté Pi avec le mixer ALSA [https://fr.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture wikipedia] :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# alsamixer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Fichier:alsamixer armbian.png|centré]]&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Alsamixer_armbian.png&amp;diff=321</id>
		<title>Fichier:Alsamixer armbian.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Alsamixer_armbian.png&amp;diff=321"/>
		<updated>2019-06-19T13:35:49Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=320</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=320"/>
		<updated>2019-06-19T13:01:56Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Projet=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA7297&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA7297.png|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 15W &lt;br /&gt;
|align=center|&lt;br /&gt;
2A (peak)&lt;br /&gt;
|align=center|&lt;br /&gt;
6 - 18 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Avec µControlleur&amp;lt;br&amp;gt;(p. 3/4)&lt;br /&gt;
|align=center|&lt;br /&gt;
Obligatoire&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.st.com/content/ccc/resource/technical/document/datasheet/a3/eb/9b/59/dd/26/4a/27/CD00001048.pdf/files/CD00001048.pdf/jcr:content/translations/en.CD00001048.pdf TDA7297]&lt;br /&gt;
|align=left|&lt;br /&gt;
Super amplification sans distorsion !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Forte dissipation thermique à pleine puissance :&lt;br /&gt;
* 33W d&#039;après la doc;&lt;br /&gt;
* vraiment très (trop) fort !&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531 (YDA138)&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 20 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 15V  &lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.ksp-electronics.com/product_files/8eeedc66ea8fbcdf2e74294037c2f389 YDA138]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8610&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 10 W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
7 - 15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8610.pdf PAM8610]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Mono&lt;br /&gt;
|align=center|&lt;br /&gt;
3.5w&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
5w&lt;br /&gt;
|align=center|&lt;br /&gt;
3 Ω&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
2 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Media:XPT8871.pdf|XPT8871]]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bien pour la voix, pas top pour la musique&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Amplification moyenne&lt;br /&gt;
*Basses creuses&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3116&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3116.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 50W&amp;lt;br&amp;gt;&lt;br /&gt;
2 x 15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&amp;lt;br&amp;gt;&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
21 V&amp;lt;br&amp;gt;&lt;br /&gt;
15 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&amp;lt;br&amp;gt;&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3116d2.pdf TPA3116]&lt;br /&gt;
|align=left|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3118&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3118.png|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2 x 30W&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
12 - 24 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI par µC&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=left|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3118d2.pdf TPA3118]&lt;br /&gt;
|align=center|&lt;br /&gt;
*Bonne amplification&lt;br /&gt;
*Basses profondes&lt;br /&gt;
*Distorsions peu audibles&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Media:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;br /&gt;
&lt;br /&gt;
= Enceinte armbian =&lt;br /&gt;
Même objectif mais cette fois-ci avec Rygel, un lecteur DLNA.&lt;br /&gt;
==Installation ==&lt;br /&gt;
Le système:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Le lecteur rygel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get -y install rygel-playbin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Les différents plugins. Tout d&#039;abord, récupérer les plugins en fonctions de la distribution:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# plugins=$(apt-cache search gstreamer | grep plugin | awk -F &#039; - &#039; &#039;{print $1}&#039;)&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ensuite on procéde à l&#039;installation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt-get install ${plugins}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Domotech_esp8266_api&amp;diff=319</id>
		<title>Domotech esp8266 api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Domotech_esp8266_api&amp;diff=319"/>
		<updated>2019-03-30T15:36:10Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Commandes =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiCommandServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/cmd/locate&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Fait clignoter la led (D4) présente sur le module&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/cmd/reboot&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Redémarre le module&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/cmd/disable&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Désactive le module. Un module désactivé ne répondra plus à aucun ordre, notamment de modification de GPIO.&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/cmd/enable&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Active le module.&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= GPIO =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiGpioServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Affiche l&#039;état des broches&lt;br /&gt;
||&lt;br /&gt;
*200 : { &amp;quot;gpios&amp;quot; : { &amp;quot;A0&amp;quot; : { &amp;quot;state&amp;quot; : 9, &amp;quot;time&amp;quot; : 0 } , &amp;quot;D0&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D1&amp;quot; : { &amp;quot;state&amp;quot; : 1, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D2&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D3&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D4&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D5&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D6&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D7&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D8&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } } }&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/mode&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;mode&#039;&#039; : mode de la broche, &#039;&#039;i&#039;&#039; &amp;amp;rarr; &#039;&#039;INPUT&#039;&#039; et &#039;&#039;o&#039;&#039; &amp;amp;rarr; &#039;&#039;OUTPUT&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Modifie le mode d&#039;une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si les deux paramètres sont présents&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/state&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;state&#039;&#039; : état désiré de la broche, &#039;&#039;1&#039;&#039; &amp;amp;rarr; &#039;&#039;HIGH&#039;&#039; et &#039;&#039;0&#039;&#039; &amp;amp;rarr; &#039;&#039;LOW&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère / modifie l&#039;état d&#039;une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si &#039;&#039;gpio&#039;&#039; est présent le retour correspondra au nouvel état de la broche &amp;amp;rarr; { &amp;quot;state&amp;quot; : 1 }&lt;br /&gt;
*400 : si &#039;&#039;gpio&#039;&#039; n&#039;est pas présent&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/pwm&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;pwm&#039;&#039; : état PWM désiré de la broche (&#039;&#039;0&#039;&#039; - &#039;&#039;1024&#039;&#039;)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère / modifie l&#039;état d&#039;une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si &#039;&#039;gpio&#039;&#039; est présent le retour correspondra au nouvel état de la broche &amp;amp;rarr; { &amp;quot;state&amp;quot; : 650 }&lt;br /&gt;
*400 : si &#039;&#039;gpio&#039;&#039; n&#039;est pas présent&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/toggle&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Permet de basculer l&#039;état d&#039;une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si &#039;&#039;gpio&#039;&#039; est présent le retour correspondra au nouvel état de la broche &amp;amp;rarr; { &amp;quot;state&amp;quot; : 1 }&lt;br /&gt;
*400 : si &#039;&#039;gpio&#039;&#039; n&#039;est pas présent&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/time&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;time&#039;&#039; : durée de changement d&#039;état de la broche (0 - 65535)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Permet de basculer l&#039;état d&#039;une broche pendant un certain nombre de secondes&lt;br /&gt;
||&lt;br /&gt;
*200 : si &#039;&#039;gpio&#039;&#039; est présent sans &#039;&#039;time&#039;&#039; &amp;amp;rarr; { &amp;quot;D1&amp;quot; : { &amp;quot;time&amp;quot; : 0 } }&lt;br /&gt;
*200 : si le paramètre &#039;&#039;time&#039;&#039; est présent le retour correspondra au nouvel état de la broche &amp;amp;rarr; { &amp;quot;state&amp;quot; : 1 }&lt;br /&gt;
*400 : si &#039;&#039;gpio&#039;&#039; n&#039;est pas présent&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/isr&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;isr&#039;&#039; : le type d&#039;interruption&lt;br /&gt;
** &#039;&#039;0&#039;&#039; &amp;amp;rarr; pas d&#039;ISR&lt;br /&gt;
** &#039;&#039;1&#039;&#039; &amp;amp;rarr; CHANGE&lt;br /&gt;
** &#039;&#039;2&#039;&#039; &amp;amp;rarr; RISING&lt;br /&gt;
** &#039;&#039;3&#039;&#039; &amp;amp;rarr; FALLING&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Attache une interruption sur une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si le paramètre &#039;&#039;gpio&#039;&#039; est présent avec &#039;&#039;isr&#039;&#039; &amp;amp;rarr; { &amp;quot;D1&amp;quot; : { &amp;quot;isr&amp;quot; : 0 } }&lt;br /&gt;
*400 : si l&#039;un des deux paramètres est manquant&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/serial&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;start&#039;&#039; : démarre la lecture sur le port série (300 - 115200)&lt;br /&gt;
* &#039;&#039;stop&#039;&#039; : arrête la lecture sur le port série&lt;br /&gt;
* &#039;&#039;send&#039;&#039; : envoie un message sur le port série&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Démarre / stop la lecture sur le port série ou envoie / retourne les données dans le tampon du port série (UART)&lt;br /&gt;
||&lt;br /&gt;
*200 : si le paramètre &#039;&#039;start&#039;&#039; est présent, il correspond à la vitesse du port série&lt;br /&gt;
*200 : si le paramètre &#039;&#039;stop&#039;&#039; est présent, cela stoppera la lecture&lt;br /&gt;
*200 : si le paramètre &#039;&#039;send&#039;&#039; est présent, cela enverra les données sur le port série&lt;br /&gt;
*200 : si aucun paramètre n&#039;est présent, cela retournera le contenu du tampon&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Température =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiTempServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/temp&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Affiche les températures de tous les thermomètres ou false si aucun thermomètre n&#039;est présent&lt;br /&gt;
||&lt;br /&gt;
*200 : { &amp;quot;temperatures&amp;quot; : [ 25.325, 38.152 ] }&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/temp/res&lt;br /&gt;
||&lt;br /&gt;
* id : le numéro du thermomètre&lt;br /&gt;
* res : la résolution voulue&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||Affiche la résolution si le paramètre &#039;&#039;res&#039;&#039; est absent&lt;br /&gt;
Configure la résolution si le paramètre &#039;&#039;res&#039;&#039; est présent&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant est valide&lt;br /&gt;
*404 : si l&#039;identifiant n&#039;est pas valide&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/temp/addr&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Affiche les adresses des thermomètres&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
= Configuration =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiConfigServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/conf&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Permet d&#039;afficher la configuration&lt;br /&gt;
||&lt;br /&gt;
*200 : &lt;br /&gt;
[[Fichier:api_config_retrieval_example.png]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/conf/apply&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Permet d&#039;appliquer une configuration (redémarre simplement le module)&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/conf/save&lt;br /&gt;
||&lt;br /&gt;
*&#039;&#039;hostname&#039;&#039; : nom du module&lt;br /&gt;
*&#039;&#039;wifimode&#039;&#039; : &lt;br /&gt;
** &#039;&#039;1&#039;&#039; &amp;amp;rarr; station mode&lt;br /&gt;
** &#039;&#039;2&#039;&#039; &amp;amp;rarr; AP mode&lt;br /&gt;
** &#039;&#039;3&#039;&#039; &amp;amp;rarr; AP_STA (both)&lt;br /&gt;
*&#039;&#039;sta_ssid&#039;&#039; : SSID of the AP to connect to (&#039;&#039;wifimode&#039;&#039; must be 1 or 3)&lt;br /&gt;
*&#039;&#039;sta_pwd&#039;&#039; : password of the AP to connect to (&#039;&#039;wifimode&#039;&#039; must be 1 or 3)&lt;br /&gt;
*&#039;&#039;ap_ssid&#039;&#039; : AP SSID (&#039;&#039;wifimode&#039;&#039; must be 2 or 3)&lt;br /&gt;
*&#039;&#039;ap_pwd&#039;&#039; : AP password (&#039;&#039;wifimode&#039;&#039; must be 2 or 3)&lt;br /&gt;
*&#039;&#039;ap_pwr&#039;&#039; : AP output power (&#039;&#039;wifimode&#039;&#039; must be 1 or 3)&lt;br /&gt;
*&#039;&#039;ipconfig&#039;&#039; : ip configuration, &#039;&#039;0&#039;&#039; for DHCP, &#039;&#039;1&#039;&#039; for static&lt;br /&gt;
*&#039;&#039;ipaddr&#039;&#039; : ip address (&#039;&#039;ipconfig&#039;&#039; must be &#039;&#039;1&#039;&#039;)&lt;br /&gt;
*&#039;&#039;netmask&#039;&#039; : ip netmask (&#039;&#039;ipconfig&#039;&#039; must be &#039;&#039;1&#039;&#039;)&lt;br /&gt;
*&#039;&#039;gateway&#039;&#039; : ip gateway (&#039;&#039;ipconfig&#039;&#039; must be &#039;&#039;1&#039;&#039;)&lt;br /&gt;
*&#039;&#039;dns&#039;&#039; : ip dns (&#039;&#039;ipconfig&#039;&#039; must be &#039;&#039;1&#039;&#039;)&lt;br /&gt;
*&#039;&#039;to_apply&#039;&#039; : will apply configuration by rebooting the device&lt;br /&gt;
*&#039;&#039;disabled&#039;&#039; : if &#039;&#039;1&#039;&#039; disable the module otherwise module is active with &#039;&#039;0&#039;&#039;&lt;br /&gt;
*&#039;&#039;is_temp&#039;&#039; : if &#039;&#039;1&#039;&#039; temperature sensor will be active, otherwise &#039;&#039;0&#039;&#039; to disable&lt;br /&gt;
*&#039;&#039;temp_pin&#039;&#039; : GPIO to look &lt;br /&gt;
*&#039;&#039;isr&#039;&#039;&lt;br /&gt;
*&#039;&#039;is_serial&#039;&#039;&lt;br /&gt;
*&#039;&#039;start&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Permet de modifier la configuration du module&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/conf/reset&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Efface la configuration et redémarre le module&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
= Firmware =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiUpdateServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/firmware/update&lt;br /&gt;
||&lt;br /&gt;
*server: l&#039;adresse IP du serveur&lt;br /&gt;
*name: le nom du firmware&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Met à jour le micrologiciel du module avec le fichier présent à &#039;&#039;http://ip_du_serveur/nom_du_firmware&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 :&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/firmware/info&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Affiche des informations sur la mise à jour. En cas de mise à jour réussie, comme le module redémarre automatiquement, l&#039;état n&#039;est pas cohérent (affiche une erreur)&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant est valide&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Domotech_esp8266_api&amp;diff=318</id>
		<title>Domotech esp8266 api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Domotech_esp8266_api&amp;diff=318"/>
		<updated>2019-03-30T15:30:16Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Commandes =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiCommandServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/cmd/locate&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Fait clignoter la led (D4) présente sur le module&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/cmd/reboot&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Redémarre le module&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/cmd/disable&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Désactive le module. Un module désactivé ne répondra plus à aucun ordre, notamment de modification de GPIO.&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/cmd/enable&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Active le module.&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= GPIO =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiGpioServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Affiche l&#039;état des broches&lt;br /&gt;
||&lt;br /&gt;
*200 : { &amp;quot;gpios&amp;quot; : { &amp;quot;A0&amp;quot; : { &amp;quot;state&amp;quot; : 9, &amp;quot;time&amp;quot; : 0 } , &amp;quot;D0&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D1&amp;quot; : { &amp;quot;state&amp;quot; : 1, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D2&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D3&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D4&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D5&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D6&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D7&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D8&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } } }&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/mode&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;mode&#039;&#039; : mode de la broche, &#039;&#039;i&#039;&#039; &amp;amp;rarr; &#039;&#039;INPUT&#039;&#039; et &#039;&#039;o&#039;&#039; &amp;amp;rarr; &#039;&#039;OUTPUT&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Modifie le mode d&#039;une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si les deux paramètres sont présents&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/state&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;state&#039;&#039; : état désiré de la broche, &#039;&#039;1&#039;&#039; &amp;amp;rarr; &#039;&#039;HIGH&#039;&#039; et &#039;&#039;0&#039;&#039; &amp;amp;rarr; &#039;&#039;LOW&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère / modifie l&#039;état d&#039;une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si &#039;&#039;gpio&#039;&#039; est présent le retour correspondra au nouvel état de la broche &amp;amp;rarr; { &amp;quot;state&amp;quot; : 1 }&lt;br /&gt;
*400 : si &#039;&#039;gpio&#039;&#039; n&#039;est pas présent&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/pwm&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;pwm&#039;&#039; : état PWM désiré de la broche (&#039;&#039;0&#039;&#039; - &#039;&#039;1024&#039;&#039;)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère / modifie l&#039;état d&#039;une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si &#039;&#039;gpio&#039;&#039; est présent le retour correspondra au nouvel état de la broche &amp;amp;rarr; { &amp;quot;state&amp;quot; : 650 }&lt;br /&gt;
*400 : si &#039;&#039;gpio&#039;&#039; n&#039;est pas présent&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/toggle&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Permet de basculer l&#039;état d&#039;une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si &#039;&#039;gpio&#039;&#039; est présent le retour correspondra au nouvel état de la broche &amp;amp;rarr; { &amp;quot;state&amp;quot; : 1 }&lt;br /&gt;
*400 : si &#039;&#039;gpio&#039;&#039; n&#039;est pas présent&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/time&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;time&#039;&#039; : durée de changement d&#039;état de la broche (0 - 65535)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Permet de basculer l&#039;état d&#039;une broche pendant un certain nombre de secondes&lt;br /&gt;
||&lt;br /&gt;
*200 : si &#039;&#039;gpio&#039;&#039; est présent sans &#039;&#039;time&#039;&#039; &amp;amp;rarr; { &amp;quot;D1&amp;quot; : { &amp;quot;time&amp;quot; : 0 } }&lt;br /&gt;
*200 : si le paramètre &#039;&#039;time&#039;&#039; est présent le retour correspondra au nouvel état de la broche &amp;amp;rarr; { &amp;quot;state&amp;quot; : 1 }&lt;br /&gt;
*400 : si &#039;&#039;gpio&#039;&#039; n&#039;est pas présent&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/isr&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;isr&#039;&#039; : le type d&#039;interruption&lt;br /&gt;
** &#039;&#039;0&#039;&#039; &amp;amp;rarr; pas d&#039;ISR&lt;br /&gt;
** &#039;&#039;1&#039;&#039; &amp;amp;rarr; CHANGE&lt;br /&gt;
** &#039;&#039;2&#039;&#039; &amp;amp;rarr; RISING&lt;br /&gt;
** &#039;&#039;3&#039;&#039; &amp;amp;rarr; FALLING&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Attache une interruption sur une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si le paramètre &#039;&#039;gpio&#039;&#039; est présent avec &#039;&#039;isr&#039;&#039; &amp;amp;rarr; { &amp;quot;D1&amp;quot; : { &amp;quot;isr&amp;quot; : 0 } }&lt;br /&gt;
*400 : si l&#039;un des deux paramètres est manquant&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/serial&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;start&#039;&#039; : démarre la lecture sur le port série (300 - 115200)&lt;br /&gt;
* &#039;&#039;stop&#039;&#039; : arrête la lecture sur le port série&lt;br /&gt;
* &#039;&#039;send&#039;&#039; : envoie un message sur le port série&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Démarre / stop la lecture sur le port série ou envoie / retourne les données dans le tampon du port série (UART)&lt;br /&gt;
||&lt;br /&gt;
*200 : si le paramètre &#039;&#039;start&#039;&#039; est présent, il correspond à la vitesse du port série&lt;br /&gt;
*200 : si le paramètre &#039;&#039;stop&#039;&#039; est présent, cela stoppera la lecture&lt;br /&gt;
*200 : si le paramètre &#039;&#039;send&#039;&#039; est présent, cela enverra les données sur le port série&lt;br /&gt;
*200 : si aucun paramètre n&#039;est présent, cela retournera le contenu du tampon&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Température =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiTempServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/temp&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Affiche les températures de tous les thermomètres ou false si aucun thermomètre n&#039;est présent&lt;br /&gt;
||&lt;br /&gt;
*200 : { &amp;quot;temperatures&amp;quot; : [ 25.325, 38.152 ] }&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/temp/res&lt;br /&gt;
||&lt;br /&gt;
* id : le numéro du thermomètre&lt;br /&gt;
* res : la résolution voulue&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||Affiche la résolution si le paramètre &#039;&#039;res&#039;&#039; est absent&lt;br /&gt;
Configure la résolution si le paramètre &#039;&#039;res&#039;&#039; est présent&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant est valide&lt;br /&gt;
*404 : si l&#039;identifiant n&#039;est pas valide&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/temp/addr&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Affiche les adresses des thermomètres&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
= Configuration =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiConfigServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/conf&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Permet d&#039;afficher la configuration&lt;br /&gt;
||&lt;br /&gt;
*200 : &lt;br /&gt;
[[Fichier:api_config_retrieval_example.png]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/conf/apply&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Permet d&#039;appliquer une configuration (redémarre simplement le module)&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/conf/save&lt;br /&gt;
||&lt;br /&gt;
*&#039;&#039;hostname&#039;&#039; : nom du module&lt;br /&gt;
*&#039;&#039;wifimode&#039;&#039; : &lt;br /&gt;
** &#039;&#039;1&#039;&#039; &amp;amp;rarr; station mode&lt;br /&gt;
** &#039;&#039;2&#039;&#039; &amp;amp;rarr; AP mode&lt;br /&gt;
** &#039;&#039;3&#039;&#039; &amp;amp;rarr; AP_STA (both)&lt;br /&gt;
*&#039;&#039;sta_ssid&#039;&#039; : SSID of the AP to connect to (&#039;&#039;wifimode&#039;&#039; must be 1 or 3)&lt;br /&gt;
*&#039;&#039;sta_pwd&#039;&#039; : password of the AP to connect to (&#039;&#039;wifimode&#039;&#039; must be 1 or 3)&lt;br /&gt;
*&#039;&#039;ap_ssid&#039;&#039; : AP SSID (&#039;&#039;wifimode&#039;&#039; must be 2 or 3)&lt;br /&gt;
*&#039;&#039;ap_pwd&#039;&#039; : AP password (&#039;&#039;wifimode&#039;&#039; must be 2 or 3)&lt;br /&gt;
*&#039;&#039;ap_pwr&#039;&#039; : AP output power (&#039;&#039;wifimode&#039;&#039; must be 1 or 3)&lt;br /&gt;
*&#039;&#039;ipconfig&#039;&#039; : ip configuration, &#039;&#039;0&#039;&#039; for DHCP, &#039;&#039;1&#039;&#039; for static&lt;br /&gt;
*&#039;&#039;ipaddr&#039;&#039; : ip address (&#039;&#039;ipconfig&#039;&#039; must be &#039;&#039;1&#039;&#039;)&lt;br /&gt;
*&#039;&#039;netmask&#039;&#039; : ip netmask (&#039;&#039;ipconfig&#039;&#039; must be &#039;&#039;1&#039;&#039;)&lt;br /&gt;
*&#039;&#039;gateway&#039;&#039; : ip gateway (&#039;&#039;ipconfig&#039;&#039; must be &#039;&#039;1&#039;&#039;)&lt;br /&gt;
*&#039;&#039;dns&#039;&#039; : ip dns (&#039;&#039;ipconfig&#039;&#039; must be &#039;&#039;1&#039;&#039;)&lt;br /&gt;
*&#039;&#039;to_apply&#039;&#039; : will apply configuration by rebooting the device&lt;br /&gt;
*&#039;&#039;disabled&#039;&#039; : if &#039;&#039;1&#039;&#039; disable the module otherwise module is active with &#039;&#039;0&#039;&#039;&lt;br /&gt;
*&#039;&#039;is_temp&#039;&#039; : if &#039;&#039;1&#039;&#039; temperature sensor will be active, otherwise &#039;&#039;0&#039;&#039; to disable&lt;br /&gt;
*&#039;&#039;temp_pin&#039;&#039; : GPIO to look &lt;br /&gt;
*&#039;&#039;isr&#039;&#039;&lt;br /&gt;
*&#039;&#039;is_serial&#039;&#039;&lt;br /&gt;
*&#039;&#039;start&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Permet de modifier la configuration du module&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/conf/reset&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Efface la configuration et redémarre le module&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Api_config_retrieval_example.png&amp;diff=317</id>
		<title>Fichier:Api config retrieval example.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Api_config_retrieval_example.png&amp;diff=317"/>
		<updated>2019-03-30T15:28:57Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Domotech_esp8266_api&amp;diff=316</id>
		<title>Domotech esp8266 api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Domotech_esp8266_api&amp;diff=316"/>
		<updated>2019-03-30T14:41:20Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* GPIO */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Commandes =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiCommandServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/cmd/locate&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Fait clignoter la led (D4) présente sur le module&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/cmd/reboot&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Redémarre le module&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/cmd/disable&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Désactive le module. Un module désactivé ne répondra plus à aucun ordre, notamment de modification de GPIO.&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/cmd/enable&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Active le module.&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= GPIO =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiGpioServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Affiche l&#039;état des broches&lt;br /&gt;
||&lt;br /&gt;
*200 : { &amp;quot;gpios&amp;quot; : { &amp;quot;A0&amp;quot; : { &amp;quot;state&amp;quot; : 9, &amp;quot;time&amp;quot; : 0 } , &amp;quot;D0&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D1&amp;quot; : { &amp;quot;state&amp;quot; : 1, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D2&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D3&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D4&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D5&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D6&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D7&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } , &amp;quot;D8&amp;quot; : { &amp;quot;state&amp;quot; : 0, &amp;quot;time&amp;quot; : 0, &amp;quot;isr&amp;quot; : 0 } } }&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/mode&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;mode&#039;&#039; : mode de la broche, &#039;&#039;i&#039;&#039; &amp;amp;rarr; &#039;&#039;INPUT&#039;&#039; et &#039;&#039;o&#039;&#039; &amp;amp;rarr; &#039;&#039;OUTPUT&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Modifie le mode d&#039;une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si les deux paramètres sont présents&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/state&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;state&#039;&#039; : état désiré de la broche, &#039;&#039;1&#039;&#039; &amp;amp;rarr; &#039;&#039;HIGH&#039;&#039; et &#039;&#039;0&#039;&#039; &amp;amp;rarr; &#039;&#039;LOW&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère / modifie l&#039;état d&#039;une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si &#039;&#039;gpio&#039;&#039; est présent le retour correspondra au nouvel état de la broche &amp;amp;rarr; { &amp;quot;state&amp;quot; : 1 }&lt;br /&gt;
*400 : si &#039;&#039;gpio&#039;&#039; n&#039;est pas présent&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/pwm&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;pwm&#039;&#039; : état PWM désiré de la broche (&#039;&#039;0&#039;&#039; - &#039;&#039;1024&#039;&#039;)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère / modifie l&#039;état d&#039;une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si &#039;&#039;gpio&#039;&#039; est présent le retour correspondra au nouvel état de la broche &amp;amp;rarr; { &amp;quot;state&amp;quot; : 650 }&lt;br /&gt;
*400 : si &#039;&#039;gpio&#039;&#039; n&#039;est pas présent&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/toggle&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Permet de basculer l&#039;état d&#039;une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si &#039;&#039;gpio&#039;&#039; est présent le retour correspondra au nouvel état de la broche &amp;amp;rarr; { &amp;quot;state&amp;quot; : 1 }&lt;br /&gt;
*400 : si &#039;&#039;gpio&#039;&#039; n&#039;est pas présent&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/time&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;time&#039;&#039; : durée de changement d&#039;état de la broche (0 - 65535)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Permet de basculer l&#039;état d&#039;une broche pendant un certain nombre de secondes&lt;br /&gt;
||&lt;br /&gt;
*200 : si &#039;&#039;gpio&#039;&#039; est présent sans &#039;&#039;time&#039;&#039; &amp;amp;rarr; { &amp;quot;D1&amp;quot; : { &amp;quot;time&amp;quot; : 0 } }&lt;br /&gt;
*200 : si le paramètre &#039;&#039;time&#039;&#039; est présent le retour correspondra au nouvel état de la broche &amp;amp;rarr; { &amp;quot;state&amp;quot; : 1 }&lt;br /&gt;
*400 : si &#039;&#039;gpio&#039;&#039; n&#039;est pas présent&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/isr&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;gpio&#039;&#039; : broche à modifier (D0 - D7)&lt;br /&gt;
* &#039;&#039;isr&#039;&#039; : le type d&#039;interruption&lt;br /&gt;
** &#039;&#039;0&#039;&#039; &amp;amp;rarr; pas d&#039;ISR&lt;br /&gt;
** &#039;&#039;1&#039;&#039; &amp;amp;rarr; CHANGE&lt;br /&gt;
** &#039;&#039;2&#039;&#039; &amp;amp;rarr; RISING&lt;br /&gt;
** &#039;&#039;3&#039;&#039; &amp;amp;rarr; FALLING&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Attache une interruption sur une broche&lt;br /&gt;
||&lt;br /&gt;
*200 : si le paramètre &#039;&#039;gpio&#039;&#039; est présent avec &#039;&#039;isr&#039;&#039; &amp;amp;rarr; { &amp;quot;D1&amp;quot; : { &amp;quot;isr&amp;quot; : 0 } }&lt;br /&gt;
*400 : si l&#039;un des deux paramètres est manquant&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/gpio/serial&lt;br /&gt;
||&lt;br /&gt;
* &#039;&#039;start&#039;&#039; : démarre la lecture sur le port série (300 - 115200)&lt;br /&gt;
* &#039;&#039;stop&#039;&#039; : arrête la lecture sur le port série&lt;br /&gt;
* &#039;&#039;send&#039;&#039; : envoie un message sur le port série&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Démarre / stop la lecture sur le port série ou envoie / retourne les données dans le tampon du port série (UART)&lt;br /&gt;
||&lt;br /&gt;
*200 : si le paramètre &#039;&#039;start&#039;&#039; est présent, il correspond à la vitesse du port série&lt;br /&gt;
*200 : si le paramètre &#039;&#039;stop&#039;&#039; est présent, cela stoppera la lecture&lt;br /&gt;
*200 : si le paramètre &#039;&#039;send&#039;&#039; est présent, cela enverra les données sur le port série&lt;br /&gt;
*200 : si aucun paramètre n&#039;est présent, cela retournera le contenu du tampon&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Température =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiTempServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/temp&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Affiche les températures de tous les thermomètres ou false si aucun thermomètre n&#039;est présent&lt;br /&gt;
||&lt;br /&gt;
*200 : { &amp;quot;temperatures&amp;quot; : [ 25.325, 38.152 ] }&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/temp/res&lt;br /&gt;
||&lt;br /&gt;
* id : le numéro du thermomètre&lt;br /&gt;
* res : la résolution voulue&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||Affiche la résolution si le paramètre &#039;&#039;res&#039;&#039; est absent&lt;br /&gt;
Configure la résolution si le paramètre &#039;&#039;res&#039;&#039; est présent&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant est valide&lt;br /&gt;
*404 : si l&#039;identifiant n&#039;est pas valide&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/temp/addr&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Affiche les adresses des thermomètres&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
= Configuration =&lt;br /&gt;
Déclaration de cette API dans le fichier &#039;&#039;ApiConfigServer.cpp&#039;&#039;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/conf&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
&lt;br /&gt;
||&lt;br /&gt;
*200 : &lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/conf/apply&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/conf/save&lt;br /&gt;
||&lt;br /&gt;
*&#039;&#039;hostname&#039;&#039; : nom du module&lt;br /&gt;
*&#039;&#039;wifimode&#039;&#039; : &lt;br /&gt;
** &#039;&#039;1&#039;&#039; &amp;amp;rarr; station mode&lt;br /&gt;
** &#039;&#039;2&#039;&#039; &amp;amp;rarr; AP mode&lt;br /&gt;
** &#039;&#039;3&#039;&#039; &amp;amp;rarr; AP_STA (both)&lt;br /&gt;
*&#039;&#039;sta_ssid&#039;&#039; : SSID of the AP to connect to (&#039;&#039;wifimode&#039;&#039; must be 1 or 3)&lt;br /&gt;
*&#039;&#039;sta_pwd&#039;&#039; : password of the AP to connect to (&#039;&#039;wifimode&#039;&#039; must be 1 or 3)&lt;br /&gt;
*&#039;&#039;ap_ssid&#039;&#039; : AP SSID (&#039;&#039;wifimode&#039;&#039; must be 2 or 3)&lt;br /&gt;
*&#039;&#039;ap_pwd&#039;&#039; : AP password (&#039;&#039;wifimode&#039;&#039; must be 2 or 3)&lt;br /&gt;
*&#039;&#039;ap_pwr&#039;&#039; : AP output power (&#039;&#039;wifimode&#039;&#039; must be 1 or 3)&lt;br /&gt;
*&#039;&#039;ipconfig&#039;&#039; : ip configuration, &#039;&#039;0&#039;&#039; for DHCP, &#039;&#039;1&#039;&#039; for static&lt;br /&gt;
*&#039;&#039;ipaddr&#039;&#039; : ip address (&#039;&#039;ipconfig&#039;&#039; must be &#039;&#039;1&#039;&#039;)&lt;br /&gt;
*&#039;&#039;netmask&#039;&#039; : ip netmask (&#039;&#039;ipconfig&#039;&#039; must be &#039;&#039;1&#039;&#039;)&lt;br /&gt;
*&#039;&#039;gateway&#039;&#039; : ip gateway (&#039;&#039;ipconfig&#039;&#039; must be &#039;&#039;1&#039;&#039;)&lt;br /&gt;
*&#039;&#039;dns&#039;&#039; : ip dns (&#039;&#039;ipconfig&#039;&#039; must be &#039;&#039;1&#039;&#039;)&lt;br /&gt;
*&#039;&#039;to_apply&#039;&#039; : will apply configuration by rebooting the device&lt;br /&gt;
*&#039;&#039;disabled&#039;&#039; : if &#039;&#039;1&#039;&#039; disable the module otherwise module is active with &#039;&#039;0&#039;&#039;&lt;br /&gt;
*&#039;&#039;is_temp&#039;&#039; : if &#039;&#039;1&#039;&#039; temperature sensor will be active, otherwise &#039;&#039;0&#039;&#039; to disable&lt;br /&gt;
*&#039;&#039;temp_pin&#039;&#039; : GPIO to look &lt;br /&gt;
*&#039;&#039;isr&#039;&#039;&lt;br /&gt;
*&#039;&#039;is_serial&#039;&#039;&lt;br /&gt;
*&#039;&#039;start&#039;&#039;&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/conf/reset&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Roadmap_orange_pi_music&amp;diff=315</id>
		<title>Roadmap orange pi music</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Roadmap_orange_pi_music&amp;diff=315"/>
		<updated>2019-01-20T19:34:15Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* TODO */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== TODO ==&lt;br /&gt;
*&amp;lt;strike&amp;gt;Ajouter au script d&#039;installation la partie Fail2Ban&amp;lt;/strike&amp;gt;&lt;br /&gt;
*faire un script de démarrage pour iptables&lt;br /&gt;
*&amp;lt;strike&amp;gt;Tester cet API : https://www.yt2mp3s.me/@api/button/mp3/MqmN-5g3_5Y&amp;lt;/strike&amp;gt;&lt;br /&gt;
*&amp;lt;strike&amp;gt;intégrer youtube-dl&amp;lt;/strike&amp;gt;&lt;br /&gt;
* mettre à jour youtube-dl avec un cron&lt;br /&gt;
&lt;br /&gt;
== Fonctionnalités ==&lt;br /&gt;
* Réfléchir à un système de playlist, avec ou sans indexation;&lt;br /&gt;
&lt;br /&gt;
== API ==&lt;br /&gt;
* Finir la partie relative à Youtube ;&lt;br /&gt;
* Procéder à une authentification (OAuth);&lt;br /&gt;
== GUI ==&lt;br /&gt;
===Partie device===&lt;br /&gt;
* Listage des périphériques USB montés / démontés&lt;br /&gt;
[[Fichier:device_available.png|centré|500px]]&lt;br /&gt;
* Montage d&#039;un périphérique USB&lt;br /&gt;
[[Fichier:device_mount.png|centré|500px]]&lt;br /&gt;
* Parcours d&#039;un périphérique USB monté&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:device_explorer.png|centré|500px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:device_explorer1.png|centré|500px]]&lt;br /&gt;
|}&lt;br /&gt;
===Partie share===&lt;br /&gt;
* Parcours des partages SMB/CIFS sur un hôte&lt;br /&gt;
[[Fichier:share_host.png|centré|500px]]&lt;br /&gt;
* Montage d&#039;un partage avec automount&lt;br /&gt;
[[Fichier:share_mount.png|centré|500px]]&lt;br /&gt;
*Parcours d&#039;un partage&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:share_explorer1.png|centré|500px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:share_explorer.png|centré|500px]]&lt;br /&gt;
|}&lt;br /&gt;
===Partie player===&lt;br /&gt;
*Lecture d&#039;un MP3 avec tag&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:player_1.png|centré|500px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:player_2.png|centré|500px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Kernel ==&lt;br /&gt;
* Écrire un démon ou faire un CRON ;&lt;br /&gt;
* Utiliser un fichier de configuration global ;&lt;br /&gt;
* Tester la présence de périphérique USB ;&lt;br /&gt;
&lt;br /&gt;
== BUGS ==&lt;br /&gt;
=== BDD ===&lt;br /&gt;
* La partie indexation mérite réflexion, dans cet état elle est trop restrictive et nécessite un TAG trop parfait pour réussir. Voir pour faire une indexation plus souple qui réussie même en l&#039;absence de certain champ (artiste, album, genre, pochette, etc...). Problème à régler dans la classe &#039;&#039;DaoMusique&#039;&#039; et &#039;&#039;Tag&#039;&#039;.&lt;br /&gt;
* Problème de typage pour le champ &#039;&#039;duration&#039;&#039;, il faut le repasser en secondes pour que cela fonctionne&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 select * from music;&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
| id_music | title                  | bitrate | hit  | duration | path                                         | id_image |&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
|        1 | Five More hours        |     128 |    0 |        3 | Deorro &amp;amp; Chris Brown   Five More Hours.mp3   |        1 |&lt;br /&gt;
|        2 | Milkshake (TRFN Remix) |     192 |    0 |        2 | 2018/Kelis - Milkshake (TRFN Remix).mp3      |        2 |&lt;br /&gt;
|        3 | Uptown Funk            |     128 |    0 |        4 | Mark Ronson ft. Bruno Mars - Uptown Funk.mp3 |        3 |&lt;br /&gt;
|        4 | Want To Want Me        |     128 |    0 |        3 | Jason Derulo - Want To Want Me.mp3           |        4 |&lt;br /&gt;
|        5 | Love Me Like You Do    |     128 |    0 |        4 | Ellie Goulding - Love Me Like You Do.mp3     |        1 |&lt;br /&gt;
|        6 | Take Me To Church      |     128 |    0 |        4 | Hozier - Take Me To Church.mp3               |        1 |&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Roadmap_orange_pi_music&amp;diff=314</id>
		<title>Roadmap orange pi music</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Roadmap_orange_pi_music&amp;diff=314"/>
		<updated>2019-01-13T23:04:15Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* TODO */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== TODO ==&lt;br /&gt;
*Ajouter au script d&#039;installation la partie Fail2Ban&lt;br /&gt;
*Tester cet API : https://www.yt2mp3s.me/@api/button/mp3/MqmN-5g3_5Y&lt;br /&gt;
&lt;br /&gt;
== Fonctionnalités ==&lt;br /&gt;
* Réfléchir à un système de playlist, avec ou sans indexation;&lt;br /&gt;
&lt;br /&gt;
== API ==&lt;br /&gt;
* Finir la partie relative à Youtube ;&lt;br /&gt;
* Procéder à une authentification (OAuth);&lt;br /&gt;
== GUI ==&lt;br /&gt;
===Partie device===&lt;br /&gt;
* Listage des périphériques USB montés / démontés&lt;br /&gt;
[[Fichier:device_available.png|centré|500px]]&lt;br /&gt;
* Montage d&#039;un périphérique USB&lt;br /&gt;
[[Fichier:device_mount.png|centré|500px]]&lt;br /&gt;
* Parcours d&#039;un périphérique USB monté&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:device_explorer.png|centré|500px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:device_explorer1.png|centré|500px]]&lt;br /&gt;
|}&lt;br /&gt;
===Partie share===&lt;br /&gt;
* Parcours des partages SMB/CIFS sur un hôte&lt;br /&gt;
[[Fichier:share_host.png|centré|500px]]&lt;br /&gt;
* Montage d&#039;un partage avec automount&lt;br /&gt;
[[Fichier:share_mount.png|centré|500px]]&lt;br /&gt;
*Parcours d&#039;un partage&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:share_explorer1.png|centré|500px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:share_explorer.png|centré|500px]]&lt;br /&gt;
|}&lt;br /&gt;
===Partie player===&lt;br /&gt;
*Lecture d&#039;un MP3 avec tag&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:player_1.png|centré|500px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:player_2.png|centré|500px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Kernel ==&lt;br /&gt;
* Écrire un démon ou faire un CRON ;&lt;br /&gt;
* Utiliser un fichier de configuration global ;&lt;br /&gt;
* Tester la présence de périphérique USB ;&lt;br /&gt;
&lt;br /&gt;
== BUGS ==&lt;br /&gt;
=== BDD ===&lt;br /&gt;
* La partie indexation mérite réflexion, dans cet état elle est trop restrictive et nécessite un TAG trop parfait pour réussir. Voir pour faire une indexation plus souple qui réussie même en l&#039;absence de certain champ (artiste, album, genre, pochette, etc...). Problème à régler dans la classe &#039;&#039;DaoMusique&#039;&#039; et &#039;&#039;Tag&#039;&#039;.&lt;br /&gt;
* Problème de typage pour le champ &#039;&#039;duration&#039;&#039;, il faut le repasser en secondes pour que cela fonctionne&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 select * from music;&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
| id_music | title                  | bitrate | hit  | duration | path                                         | id_image |&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
|        1 | Five More hours        |     128 |    0 |        3 | Deorro &amp;amp; Chris Brown   Five More Hours.mp3   |        1 |&lt;br /&gt;
|        2 | Milkshake (TRFN Remix) |     192 |    0 |        2 | 2018/Kelis - Milkshake (TRFN Remix).mp3      |        2 |&lt;br /&gt;
|        3 | Uptown Funk            |     128 |    0 |        4 | Mark Ronson ft. Bruno Mars - Uptown Funk.mp3 |        3 |&lt;br /&gt;
|        4 | Want To Want Me        |     128 |    0 |        3 | Jason Derulo - Want To Want Me.mp3           |        4 |&lt;br /&gt;
|        5 | Love Me Like You Do    |     128 |    0 |        4 | Ellie Goulding - Love Me Like You Do.mp3     |        1 |&lt;br /&gt;
|        6 | Take Me To Church      |     128 |    0 |        4 | Hozier - Take Me To Church.mp3               |        1 |&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Roadmap_orange_pi_music&amp;diff=313</id>
		<title>Roadmap orange pi music</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Roadmap_orange_pi_music&amp;diff=313"/>
		<updated>2019-01-13T22:54:42Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Fonctionnalités */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== TODO ==&lt;br /&gt;
Ajouter au script d&#039;installation la partie Fail2Ban&lt;br /&gt;
&lt;br /&gt;
== Fonctionnalités ==&lt;br /&gt;
* Réfléchir à un système de playlist, avec ou sans indexation;&lt;br /&gt;
&lt;br /&gt;
== API ==&lt;br /&gt;
* Finir la partie relative à Youtube ;&lt;br /&gt;
* Procéder à une authentification (OAuth);&lt;br /&gt;
== GUI ==&lt;br /&gt;
===Partie device===&lt;br /&gt;
* Listage des périphériques USB montés / démontés&lt;br /&gt;
[[Fichier:device_available.png|centré|500px]]&lt;br /&gt;
* Montage d&#039;un périphérique USB&lt;br /&gt;
[[Fichier:device_mount.png|centré|500px]]&lt;br /&gt;
* Parcours d&#039;un périphérique USB monté&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:device_explorer.png|centré|500px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:device_explorer1.png|centré|500px]]&lt;br /&gt;
|}&lt;br /&gt;
===Partie share===&lt;br /&gt;
* Parcours des partages SMB/CIFS sur un hôte&lt;br /&gt;
[[Fichier:share_host.png|centré|500px]]&lt;br /&gt;
* Montage d&#039;un partage avec automount&lt;br /&gt;
[[Fichier:share_mount.png|centré|500px]]&lt;br /&gt;
*Parcours d&#039;un partage&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:share_explorer1.png|centré|500px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:share_explorer.png|centré|500px]]&lt;br /&gt;
|}&lt;br /&gt;
===Partie player===&lt;br /&gt;
*Lecture d&#039;un MP3 avec tag&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:player_1.png|centré|500px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:player_2.png|centré|500px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Kernel ==&lt;br /&gt;
* Écrire un démon ou faire un CRON ;&lt;br /&gt;
* Utiliser un fichier de configuration global ;&lt;br /&gt;
* Tester la présence de périphérique USB ;&lt;br /&gt;
&lt;br /&gt;
== BUGS ==&lt;br /&gt;
=== BDD ===&lt;br /&gt;
* La partie indexation mérite réflexion, dans cet état elle est trop restrictive et nécessite un TAG trop parfait pour réussir. Voir pour faire une indexation plus souple qui réussie même en l&#039;absence de certain champ (artiste, album, genre, pochette, etc...). Problème à régler dans la classe &#039;&#039;DaoMusique&#039;&#039; et &#039;&#039;Tag&#039;&#039;.&lt;br /&gt;
* Problème de typage pour le champ &#039;&#039;duration&#039;&#039;, il faut le repasser en secondes pour que cela fonctionne&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 select * from music;&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
| id_music | title                  | bitrate | hit  | duration | path                                         | id_image |&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
|        1 | Five More hours        |     128 |    0 |        3 | Deorro &amp;amp; Chris Brown   Five More Hours.mp3   |        1 |&lt;br /&gt;
|        2 | Milkshake (TRFN Remix) |     192 |    0 |        2 | 2018/Kelis - Milkshake (TRFN Remix).mp3      |        2 |&lt;br /&gt;
|        3 | Uptown Funk            |     128 |    0 |        4 | Mark Ronson ft. Bruno Mars - Uptown Funk.mp3 |        3 |&lt;br /&gt;
|        4 | Want To Want Me        |     128 |    0 |        3 | Jason Derulo - Want To Want Me.mp3           |        4 |&lt;br /&gt;
|        5 | Love Me Like You Do    |     128 |    0 |        4 | Ellie Goulding - Love Me Like You Do.mp3     |        1 |&lt;br /&gt;
|        6 | Take Me To Church      |     128 |    0 |        4 | Hozier - Take Me To Church.mp3               |        1 |&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=312</id>
		<title>Music sender api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=312"/>
		<updated>2019-01-13T11:45:41Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Share */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=User=&lt;br /&gt;
L&#039;objet user est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;pseudo&amp;quot;:&amp;quot;tala&amp;quot;,&amp;quot;email&amp;quot;:&amp;quot;tala@tala.com&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/&lt;br /&gt;
||&lt;br /&gt;
* pseudo : le pseudo de l&#039;utilisateur&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
* password : le mot de passe de l&#039;utilisateur&lt;br /&gt;
* image : l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Crée un nouvel utilisateur et renvoie son identifiant&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussi avec en réponse l&#039;identifiant (eg. {&amp;quot;id&amp;quot;:1} )&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/email/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;email du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/password/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* password : le nouveau mot de passe utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le mot de passe du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Genre=&lt;br /&gt;
L&#039;objet genre est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Electro-Jazz&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets genre&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet genre&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom du genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface le genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Artist=&lt;br /&gt;
L&#039;objet artiste est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;84&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;Yolanda Be Cool &amp;amp; Dcup&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;artist&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet artiste&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’artiste&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Album=&lt;br /&gt;
L&#039;objet album est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;album&amp;quot;:&amp;quot;Electro Swing Collection 1&amp;quot;,&amp;quot;coverId&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;album&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet album&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’album&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Music=&lt;br /&gt;
L&#039;objet musique est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;title&amp;quot;:&amp;quot;All Night&amp;quot;,&amp;quot;artists&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;genres&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;bitrate&amp;quot;:&amp;quot;128&amp;quot;,&amp;quot;hit&amp;quot;:&amp;quot;4&amp;quot;,&amp;quot;duration&amp;quot;:&amp;quot;163&amp;quot;,&amp;quot;id_image&amp;quot;:&amp;quot;1&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet musique au format Json &lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/content/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu de la musique (fichier son)&amp;lt;br&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json appartenant à l&#039;album associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json dont le créateur est l&#039;artiste associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Image=&lt;br /&gt;
L&#039;objet image est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;/9j/4B4…T0+7RRW/2Q==&amp;quot;,&amp;quot;mime&amp;quot;:&amp;quot;image\jpeg&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0aebaad7…4f265bd&amp;quot;} }&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/images&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets image&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/info/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/content/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Device=&lt;br /&gt;
L&#039;objet périphérique est composé comme suit : {&amp;quot;name&amp;quot;:&amp;quot;\/dev\/sda1&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;MUSIC&amp;quot;,&amp;quot;size&amp;quot;:&amp;quot;7.2 GiB&amp;quot;,&amp;quot;UUID&amp;quot;:&amp;quot;84B9-A853&amp;quot;,&amp;quot;fstype&amp;quot;:&amp;quot;vfat&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les périphériques&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/list/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers et dossiers:&lt;br /&gt;
&lt;br /&gt;
{&amp;quot;directories&amp;quot;:[&amp;quot;Pop&amp;quot;,&amp;quot;Rock&amp;quot;],&amp;quot;files&amp;quot;:[&amp;quot;Gala - Freed From Desire.mp3&amp;quot;,&amp;quot;13)Jacques Your Body (Make Me Sweat)(Jcf Pitch Edit).mp3&amp;quot;]}&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/content/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** download : si présent, le navigateur téléchargera le fichier (&#039;Content-disposition: attachment;&#039; au lieu de &#039;Content-disposition: inline;&#039;)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête &lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/tag/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/size/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la taille du fichiers ou répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques montés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/umounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques démontés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le périphérique sur le système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Active le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/index/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le périphérique du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Désactive le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Share=&lt;br /&gt;
L&#039;objet partage est composé comme suit : {&amp;quot;host&amp;quot;:&amp;quot;hades&amp;quot;,&amp;quot;share&amp;quot;:&amp;quot;downloads&amp;quot;,&amp;quot;login&amp;quot;:&amp;quot;nobody&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les partages montés&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des partages disponibles sur l&#039;hôte&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
** extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive de tous les fichiers disponibles sur le partage&lt;br /&gt;
&lt;br /&gt;
Attention, l&#039;appel peut être long, surtout lorsque les partages contiennent beaucoup de fichiers&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le partage existe&lt;br /&gt;
* 400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
** extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si le partage existe&lt;br /&gt;
*400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/content/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
** download : si présent, le navigateur téléchargera le fichier (&#039;Content-disposition: attachment;&#039; au lieu de &#039;Content-disposition: inline;&#039;)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/tag/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/size/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la taille du fichiers ou répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* login : le login à utiliser (optionnel)&lt;br /&gt;
* password : le mot de passe associé (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le partage sur le système. Si aucun couple d&#039;authentification n&#039;est fourni, &#039;&#039;nobody&#039;&#039; sera utilisé&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/index/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le partage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Youtube =&lt;br /&gt;
Permet de récupérer des informations sur les vidéo Youtube&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère des informations sur la vidéo Youtube. Voici un exemple:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
&amp;quot;url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;cover&amp;quot;:&amp;quot;https:\/\/i.ytimg.com\/vi\/eVGrSCrRiy8\/maxresdefault.jpg&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;author&amp;quot;:&amp;quot;ElectroDanceMixes&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;title&amp;quot;:&amp;quot;FESTIVAL MIX - Best EDM &amp;amp; Electro House Dance Party Mix 2018&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;id&amp;quot;:&amp;quot;eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;videos&amp;quot;:[&amp;quot;...&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/cover/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la &#039;&#039;pochette&#039;&#039; de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/listen/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère le contenu de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Player=&lt;br /&gt;
Joue la musique sur la carte son du Pi (intégration VLC)&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/pause&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Met en pause la music&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/stop&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Stop la lecture&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/volume/$$PERCENT$$&lt;br /&gt;
*$$PERCENT$$ : le volume en poucentage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Règle le volume du lecteur&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/device/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le périphérique &#039;&#039;UUID&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier et le périphérique existent&lt;br /&gt;
*400 : si le fichier ou le périphérique n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le partage &#039;&#039;SHARE&#039;&#039; sur l&#039;hôte &#039;&#039;HOST&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier, le partage et l&#039;hôte existent&lt;br /&gt;
*400 : si le fichier, le partage ou l&#039;hôte n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/youtube/$$ID$$&lt;br /&gt;
||&lt;br /&gt;
* $$ID$$ : un ID de vidéo Youtube (https://www.youtube.com/watch?v=mEYyVY9ffDM &amp;amp;rarr; mEYyVY9ffDM)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le son de la vidéo, quand c&#039;est possible (certaines vidéos ne fonctionnent pas)&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la vidéo existe&lt;br /&gt;
* 400 : si le vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/url&lt;br /&gt;
||&lt;br /&gt;
* path : un lien vers un fichier musical&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Indexer (WIP)=&lt;br /&gt;
Permet d&#039;avoir des informations sur les travaux d&#039;indexation en cours. Voici un exemple:&lt;br /&gt;
* d&#039;identifiant de travail &amp;amp;rarr; 5c2e724887be4;&lt;br /&gt;
* d&#039;informations sur un travail &amp;amp;rarr; {&amp;quot;files&amp;quot;:{&amp;quot;directory&amp;quot;:&amp;quot;\/opt\/mount\/192.168.1.252-torrent\/\/Best of POP JCF&amp;quot;,&amp;quot;total&amp;quot;:8,&amp;quot;current&amp;quot;:[],&amp;quot;processed&amp;quot;:8,&amp;quot;remaining&amp;quot;:0,&amp;quot;success&amp;quot;:[1,2,3,4,5,6,7,8],&amp;quot;failure&amp;quot;:[]},&amp;quot;time&amp;quot;:{&amp;quot;start&amp;quot;:1546547784,&amp;quot;elapsed&amp;quot;:1,&amp;quot;end&amp;quot;:1546547785},&amp;quot;state&amp;quot;:2}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la liste des identifiants des travaux en cours&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la liste des identifiants des travaux disponibles pour consultation&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Stop le travail d&#039;indexation désignè par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Supprime les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=311</id>
		<title>Music sender api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=311"/>
		<updated>2019-01-13T11:45:21Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Device */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=User=&lt;br /&gt;
L&#039;objet user est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;pseudo&amp;quot;:&amp;quot;tala&amp;quot;,&amp;quot;email&amp;quot;:&amp;quot;tala@tala.com&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/&lt;br /&gt;
||&lt;br /&gt;
* pseudo : le pseudo de l&#039;utilisateur&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
* password : le mot de passe de l&#039;utilisateur&lt;br /&gt;
* image : l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Crée un nouvel utilisateur et renvoie son identifiant&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussi avec en réponse l&#039;identifiant (eg. {&amp;quot;id&amp;quot;:1} )&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/email/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;email du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/password/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* password : le nouveau mot de passe utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le mot de passe du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Genre=&lt;br /&gt;
L&#039;objet genre est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Electro-Jazz&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets genre&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet genre&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom du genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface le genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Artist=&lt;br /&gt;
L&#039;objet artiste est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;84&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;Yolanda Be Cool &amp;amp; Dcup&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;artist&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet artiste&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’artiste&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Album=&lt;br /&gt;
L&#039;objet album est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;album&amp;quot;:&amp;quot;Electro Swing Collection 1&amp;quot;,&amp;quot;coverId&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;album&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet album&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’album&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Music=&lt;br /&gt;
L&#039;objet musique est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;title&amp;quot;:&amp;quot;All Night&amp;quot;,&amp;quot;artists&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;genres&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;bitrate&amp;quot;:&amp;quot;128&amp;quot;,&amp;quot;hit&amp;quot;:&amp;quot;4&amp;quot;,&amp;quot;duration&amp;quot;:&amp;quot;163&amp;quot;,&amp;quot;id_image&amp;quot;:&amp;quot;1&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet musique au format Json &lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/content/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu de la musique (fichier son)&amp;lt;br&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json appartenant à l&#039;album associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json dont le créateur est l&#039;artiste associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Image=&lt;br /&gt;
L&#039;objet image est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;/9j/4B4…T0+7RRW/2Q==&amp;quot;,&amp;quot;mime&amp;quot;:&amp;quot;image\jpeg&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0aebaad7…4f265bd&amp;quot;} }&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/images&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets image&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/info/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/content/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Device=&lt;br /&gt;
L&#039;objet périphérique est composé comme suit : {&amp;quot;name&amp;quot;:&amp;quot;\/dev\/sda1&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;MUSIC&amp;quot;,&amp;quot;size&amp;quot;:&amp;quot;7.2 GiB&amp;quot;,&amp;quot;UUID&amp;quot;:&amp;quot;84B9-A853&amp;quot;,&amp;quot;fstype&amp;quot;:&amp;quot;vfat&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les périphériques&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/list/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers et dossiers:&lt;br /&gt;
&lt;br /&gt;
{&amp;quot;directories&amp;quot;:[&amp;quot;Pop&amp;quot;,&amp;quot;Rock&amp;quot;],&amp;quot;files&amp;quot;:[&amp;quot;Gala - Freed From Desire.mp3&amp;quot;,&amp;quot;13)Jacques Your Body (Make Me Sweat)(Jcf Pitch Edit).mp3&amp;quot;]}&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/content/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** download : si présent, le navigateur téléchargera le fichier (&#039;Content-disposition: attachment;&#039; au lieu de &#039;Content-disposition: inline;&#039;)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête &lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/tag/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/size/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la taille du fichiers ou répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques montés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/umounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques démontés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le périphérique sur le système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Active le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/index/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le périphérique du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Désactive le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Share=&lt;br /&gt;
L&#039;objet partage est composé comme suit : {&amp;quot;host&amp;quot;:&amp;quot;hades&amp;quot;,&amp;quot;share&amp;quot;:&amp;quot;downloads&amp;quot;,&amp;quot;login&amp;quot;:&amp;quot;nobody&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les partages montés&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des partages disponibles sur l&#039;hôte&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
** extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive de tous les fichiers disponibles sur le partage&lt;br /&gt;
&lt;br /&gt;
Attention, l&#039;appel peut être long, surtout lorsque les partages contiennent beaucoup de fichiers&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le partage existe&lt;br /&gt;
* 400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
** extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si le partage existe&lt;br /&gt;
*400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/content/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/tag/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/size/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la taille du fichiers ou répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* login : le login à utiliser (optionnel)&lt;br /&gt;
* password : le mot de passe associé (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le partage sur le système. Si aucun couple d&#039;authentification n&#039;est fourni, &#039;&#039;nobody&#039;&#039; sera utilisé&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/index/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le partage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Youtube =&lt;br /&gt;
Permet de récupérer des informations sur les vidéo Youtube&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère des informations sur la vidéo Youtube. Voici un exemple:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
&amp;quot;url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;cover&amp;quot;:&amp;quot;https:\/\/i.ytimg.com\/vi\/eVGrSCrRiy8\/maxresdefault.jpg&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;author&amp;quot;:&amp;quot;ElectroDanceMixes&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;title&amp;quot;:&amp;quot;FESTIVAL MIX - Best EDM &amp;amp; Electro House Dance Party Mix 2018&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;id&amp;quot;:&amp;quot;eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;videos&amp;quot;:[&amp;quot;...&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/cover/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la &#039;&#039;pochette&#039;&#039; de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/listen/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère le contenu de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Player=&lt;br /&gt;
Joue la musique sur la carte son du Pi (intégration VLC)&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/pause&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Met en pause la music&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/stop&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Stop la lecture&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/volume/$$PERCENT$$&lt;br /&gt;
*$$PERCENT$$ : le volume en poucentage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Règle le volume du lecteur&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/device/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le périphérique &#039;&#039;UUID&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier et le périphérique existent&lt;br /&gt;
*400 : si le fichier ou le périphérique n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le partage &#039;&#039;SHARE&#039;&#039; sur l&#039;hôte &#039;&#039;HOST&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier, le partage et l&#039;hôte existent&lt;br /&gt;
*400 : si le fichier, le partage ou l&#039;hôte n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/youtube/$$ID$$&lt;br /&gt;
||&lt;br /&gt;
* $$ID$$ : un ID de vidéo Youtube (https://www.youtube.com/watch?v=mEYyVY9ffDM &amp;amp;rarr; mEYyVY9ffDM)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le son de la vidéo, quand c&#039;est possible (certaines vidéos ne fonctionnent pas)&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la vidéo existe&lt;br /&gt;
* 400 : si le vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/url&lt;br /&gt;
||&lt;br /&gt;
* path : un lien vers un fichier musical&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Indexer (WIP)=&lt;br /&gt;
Permet d&#039;avoir des informations sur les travaux d&#039;indexation en cours. Voici un exemple:&lt;br /&gt;
* d&#039;identifiant de travail &amp;amp;rarr; 5c2e724887be4;&lt;br /&gt;
* d&#039;informations sur un travail &amp;amp;rarr; {&amp;quot;files&amp;quot;:{&amp;quot;directory&amp;quot;:&amp;quot;\/opt\/mount\/192.168.1.252-torrent\/\/Best of POP JCF&amp;quot;,&amp;quot;total&amp;quot;:8,&amp;quot;current&amp;quot;:[],&amp;quot;processed&amp;quot;:8,&amp;quot;remaining&amp;quot;:0,&amp;quot;success&amp;quot;:[1,2,3,4,5,6,7,8],&amp;quot;failure&amp;quot;:[]},&amp;quot;time&amp;quot;:{&amp;quot;start&amp;quot;:1546547784,&amp;quot;elapsed&amp;quot;:1,&amp;quot;end&amp;quot;:1546547785},&amp;quot;state&amp;quot;:2}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la liste des identifiants des travaux en cours&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la liste des identifiants des travaux disponibles pour consultation&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Stop le travail d&#039;indexation désignè par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Supprime les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=310</id>
		<title>Music sender api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=310"/>
		<updated>2019-01-13T11:20:07Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Share */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=User=&lt;br /&gt;
L&#039;objet user est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;pseudo&amp;quot;:&amp;quot;tala&amp;quot;,&amp;quot;email&amp;quot;:&amp;quot;tala@tala.com&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/&lt;br /&gt;
||&lt;br /&gt;
* pseudo : le pseudo de l&#039;utilisateur&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
* password : le mot de passe de l&#039;utilisateur&lt;br /&gt;
* image : l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Crée un nouvel utilisateur et renvoie son identifiant&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussi avec en réponse l&#039;identifiant (eg. {&amp;quot;id&amp;quot;:1} )&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/email/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;email du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/password/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* password : le nouveau mot de passe utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le mot de passe du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Genre=&lt;br /&gt;
L&#039;objet genre est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Electro-Jazz&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets genre&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet genre&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom du genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface le genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Artist=&lt;br /&gt;
L&#039;objet artiste est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;84&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;Yolanda Be Cool &amp;amp; Dcup&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;artist&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet artiste&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’artiste&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Album=&lt;br /&gt;
L&#039;objet album est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;album&amp;quot;:&amp;quot;Electro Swing Collection 1&amp;quot;,&amp;quot;coverId&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;album&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet album&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’album&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Music=&lt;br /&gt;
L&#039;objet musique est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;title&amp;quot;:&amp;quot;All Night&amp;quot;,&amp;quot;artists&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;genres&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;bitrate&amp;quot;:&amp;quot;128&amp;quot;,&amp;quot;hit&amp;quot;:&amp;quot;4&amp;quot;,&amp;quot;duration&amp;quot;:&amp;quot;163&amp;quot;,&amp;quot;id_image&amp;quot;:&amp;quot;1&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet musique au format Json &lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/content/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu de la musique (fichier son)&amp;lt;br&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json appartenant à l&#039;album associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json dont le créateur est l&#039;artiste associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Image=&lt;br /&gt;
L&#039;objet image est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;/9j/4B4…T0+7RRW/2Q==&amp;quot;,&amp;quot;mime&amp;quot;:&amp;quot;image\jpeg&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0aebaad7…4f265bd&amp;quot;} }&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/images&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets image&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/info/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/content/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Device=&lt;br /&gt;
L&#039;objet périphérique est composé comme suit : {&amp;quot;name&amp;quot;:&amp;quot;\/dev\/sda1&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;MUSIC&amp;quot;,&amp;quot;size&amp;quot;:&amp;quot;7.2 GiB&amp;quot;,&amp;quot;UUID&amp;quot;:&amp;quot;84B9-A853&amp;quot;,&amp;quot;fstype&amp;quot;:&amp;quot;vfat&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les périphériques&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/list/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers et dossiers:&lt;br /&gt;
&lt;br /&gt;
{&amp;quot;directories&amp;quot;:[&amp;quot;Pop&amp;quot;,&amp;quot;Rock&amp;quot;],&amp;quot;files&amp;quot;:[&amp;quot;Gala - Freed From Desire.mp3&amp;quot;,&amp;quot;13)Jacques Your Body (Make Me Sweat)(Jcf Pitch Edit).mp3&amp;quot;]}&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/content/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête &lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/tag/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/size/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la taille du fichiers ou répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques montés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/umounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques démontés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le périphérique sur le système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Active le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/index/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le périphérique du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Désactive le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Share=&lt;br /&gt;
L&#039;objet partage est composé comme suit : {&amp;quot;host&amp;quot;:&amp;quot;hades&amp;quot;,&amp;quot;share&amp;quot;:&amp;quot;downloads&amp;quot;,&amp;quot;login&amp;quot;:&amp;quot;nobody&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les partages montés&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des partages disponibles sur l&#039;hôte&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
** extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive de tous les fichiers disponibles sur le partage&lt;br /&gt;
&lt;br /&gt;
Attention, l&#039;appel peut être long, surtout lorsque les partages contiennent beaucoup de fichiers&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le partage existe&lt;br /&gt;
* 400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
** extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si le partage existe&lt;br /&gt;
*400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/content/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/tag/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/size/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la taille du fichiers ou répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* login : le login à utiliser (optionnel)&lt;br /&gt;
* password : le mot de passe associé (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le partage sur le système. Si aucun couple d&#039;authentification n&#039;est fourni, &#039;&#039;nobody&#039;&#039; sera utilisé&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/index/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le partage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Youtube =&lt;br /&gt;
Permet de récupérer des informations sur les vidéo Youtube&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère des informations sur la vidéo Youtube. Voici un exemple:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
&amp;quot;url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;cover&amp;quot;:&amp;quot;https:\/\/i.ytimg.com\/vi\/eVGrSCrRiy8\/maxresdefault.jpg&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;author&amp;quot;:&amp;quot;ElectroDanceMixes&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;title&amp;quot;:&amp;quot;FESTIVAL MIX - Best EDM &amp;amp; Electro House Dance Party Mix 2018&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;id&amp;quot;:&amp;quot;eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;videos&amp;quot;:[&amp;quot;...&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/cover/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la &#039;&#039;pochette&#039;&#039; de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/listen/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère le contenu de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Player=&lt;br /&gt;
Joue la musique sur la carte son du Pi (intégration VLC)&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/pause&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Met en pause la music&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/stop&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Stop la lecture&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/volume/$$PERCENT$$&lt;br /&gt;
*$$PERCENT$$ : le volume en poucentage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Règle le volume du lecteur&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/device/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le périphérique &#039;&#039;UUID&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier et le périphérique existent&lt;br /&gt;
*400 : si le fichier ou le périphérique n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le partage &#039;&#039;SHARE&#039;&#039; sur l&#039;hôte &#039;&#039;HOST&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier, le partage et l&#039;hôte existent&lt;br /&gt;
*400 : si le fichier, le partage ou l&#039;hôte n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/youtube/$$ID$$&lt;br /&gt;
||&lt;br /&gt;
* $$ID$$ : un ID de vidéo Youtube (https://www.youtube.com/watch?v=mEYyVY9ffDM &amp;amp;rarr; mEYyVY9ffDM)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le son de la vidéo, quand c&#039;est possible (certaines vidéos ne fonctionnent pas)&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la vidéo existe&lt;br /&gt;
* 400 : si le vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/url&lt;br /&gt;
||&lt;br /&gt;
* path : un lien vers un fichier musical&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Indexer (WIP)=&lt;br /&gt;
Permet d&#039;avoir des informations sur les travaux d&#039;indexation en cours. Voici un exemple:&lt;br /&gt;
* d&#039;identifiant de travail &amp;amp;rarr; 5c2e724887be4;&lt;br /&gt;
* d&#039;informations sur un travail &amp;amp;rarr; {&amp;quot;files&amp;quot;:{&amp;quot;directory&amp;quot;:&amp;quot;\/opt\/mount\/192.168.1.252-torrent\/\/Best of POP JCF&amp;quot;,&amp;quot;total&amp;quot;:8,&amp;quot;current&amp;quot;:[],&amp;quot;processed&amp;quot;:8,&amp;quot;remaining&amp;quot;:0,&amp;quot;success&amp;quot;:[1,2,3,4,5,6,7,8],&amp;quot;failure&amp;quot;:[]},&amp;quot;time&amp;quot;:{&amp;quot;start&amp;quot;:1546547784,&amp;quot;elapsed&amp;quot;:1,&amp;quot;end&amp;quot;:1546547785},&amp;quot;state&amp;quot;:2}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la liste des identifiants des travaux en cours&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la liste des identifiants des travaux disponibles pour consultation&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Stop le travail d&#039;indexation désignè par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Supprime les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=309</id>
		<title>Music sender api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=309"/>
		<updated>2019-01-13T11:16:48Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Device */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=User=&lt;br /&gt;
L&#039;objet user est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;pseudo&amp;quot;:&amp;quot;tala&amp;quot;,&amp;quot;email&amp;quot;:&amp;quot;tala@tala.com&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/&lt;br /&gt;
||&lt;br /&gt;
* pseudo : le pseudo de l&#039;utilisateur&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
* password : le mot de passe de l&#039;utilisateur&lt;br /&gt;
* image : l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Crée un nouvel utilisateur et renvoie son identifiant&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussi avec en réponse l&#039;identifiant (eg. {&amp;quot;id&amp;quot;:1} )&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/email/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;email du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/password/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* password : le nouveau mot de passe utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le mot de passe du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Genre=&lt;br /&gt;
L&#039;objet genre est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Electro-Jazz&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets genre&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet genre&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom du genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface le genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Artist=&lt;br /&gt;
L&#039;objet artiste est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;84&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;Yolanda Be Cool &amp;amp; Dcup&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;artist&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet artiste&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’artiste&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Album=&lt;br /&gt;
L&#039;objet album est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;album&amp;quot;:&amp;quot;Electro Swing Collection 1&amp;quot;,&amp;quot;coverId&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;album&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet album&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’album&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Music=&lt;br /&gt;
L&#039;objet musique est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;title&amp;quot;:&amp;quot;All Night&amp;quot;,&amp;quot;artists&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;genres&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;bitrate&amp;quot;:&amp;quot;128&amp;quot;,&amp;quot;hit&amp;quot;:&amp;quot;4&amp;quot;,&amp;quot;duration&amp;quot;:&amp;quot;163&amp;quot;,&amp;quot;id_image&amp;quot;:&amp;quot;1&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet musique au format Json &lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/content/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu de la musique (fichier son)&amp;lt;br&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json appartenant à l&#039;album associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json dont le créateur est l&#039;artiste associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Image=&lt;br /&gt;
L&#039;objet image est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;/9j/4B4…T0+7RRW/2Q==&amp;quot;,&amp;quot;mime&amp;quot;:&amp;quot;image\jpeg&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0aebaad7…4f265bd&amp;quot;} }&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/images&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets image&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/info/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/content/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Device=&lt;br /&gt;
L&#039;objet périphérique est composé comme suit : {&amp;quot;name&amp;quot;:&amp;quot;\/dev\/sda1&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;MUSIC&amp;quot;,&amp;quot;size&amp;quot;:&amp;quot;7.2 GiB&amp;quot;,&amp;quot;UUID&amp;quot;:&amp;quot;84B9-A853&amp;quot;,&amp;quot;fstype&amp;quot;:&amp;quot;vfat&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les périphériques&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/list/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers et dossiers:&lt;br /&gt;
&lt;br /&gt;
{&amp;quot;directories&amp;quot;:[&amp;quot;Pop&amp;quot;,&amp;quot;Rock&amp;quot;],&amp;quot;files&amp;quot;:[&amp;quot;Gala - Freed From Desire.mp3&amp;quot;,&amp;quot;13)Jacques Your Body (Make Me Sweat)(Jcf Pitch Edit).mp3&amp;quot;]}&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/content/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête &lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/tag/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/size/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la taille du fichiers ou répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques montés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/umounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques démontés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le périphérique sur le système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Active le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/index/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le périphérique du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Désactive le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Share=&lt;br /&gt;
L&#039;objet partage est composé comme suit : {&amp;quot;host&amp;quot;:&amp;quot;hades&amp;quot;,&amp;quot;share&amp;quot;:&amp;quot;downloads&amp;quot;,&amp;quot;login&amp;quot;:&amp;quot;nobody&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les partages montés&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des partages disponibles sur l&#039;hôte&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
** extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive de tous les fichiers disponibles sur le partage&lt;br /&gt;
&lt;br /&gt;
Attention, l&#039;appel peut être long, surtout lorsque les partages contiennent beaucoup de fichiers&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le partage existe&lt;br /&gt;
* 400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
** extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si le partage existe&lt;br /&gt;
*400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/content/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/tag/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* login : le login à utiliser (optionnel)&lt;br /&gt;
* password : le mot de passe associé (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le partage sur le système. Si aucun couple d&#039;authentification n&#039;est fourni, &#039;&#039;nobody&#039;&#039; sera utilisé&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/index/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le partage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Youtube =&lt;br /&gt;
Permet de récupérer des informations sur les vidéo Youtube&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère des informations sur la vidéo Youtube. Voici un exemple:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
&amp;quot;url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;cover&amp;quot;:&amp;quot;https:\/\/i.ytimg.com\/vi\/eVGrSCrRiy8\/maxresdefault.jpg&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;author&amp;quot;:&amp;quot;ElectroDanceMixes&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;title&amp;quot;:&amp;quot;FESTIVAL MIX - Best EDM &amp;amp; Electro House Dance Party Mix 2018&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;id&amp;quot;:&amp;quot;eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;videos&amp;quot;:[&amp;quot;...&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/cover/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la &#039;&#039;pochette&#039;&#039; de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/listen/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère le contenu de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Player=&lt;br /&gt;
Joue la musique sur la carte son du Pi (intégration VLC)&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/pause&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Met en pause la music&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/stop&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Stop la lecture&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/volume/$$PERCENT$$&lt;br /&gt;
*$$PERCENT$$ : le volume en poucentage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Règle le volume du lecteur&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/device/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le périphérique &#039;&#039;UUID&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier et le périphérique existent&lt;br /&gt;
*400 : si le fichier ou le périphérique n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le partage &#039;&#039;SHARE&#039;&#039; sur l&#039;hôte &#039;&#039;HOST&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier, le partage et l&#039;hôte existent&lt;br /&gt;
*400 : si le fichier, le partage ou l&#039;hôte n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/youtube/$$ID$$&lt;br /&gt;
||&lt;br /&gt;
* $$ID$$ : un ID de vidéo Youtube (https://www.youtube.com/watch?v=mEYyVY9ffDM &amp;amp;rarr; mEYyVY9ffDM)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le son de la vidéo, quand c&#039;est possible (certaines vidéos ne fonctionnent pas)&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la vidéo existe&lt;br /&gt;
* 400 : si le vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/url&lt;br /&gt;
||&lt;br /&gt;
* path : un lien vers un fichier musical&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Indexer (WIP)=&lt;br /&gt;
Permet d&#039;avoir des informations sur les travaux d&#039;indexation en cours. Voici un exemple:&lt;br /&gt;
* d&#039;identifiant de travail &amp;amp;rarr; 5c2e724887be4;&lt;br /&gt;
* d&#039;informations sur un travail &amp;amp;rarr; {&amp;quot;files&amp;quot;:{&amp;quot;directory&amp;quot;:&amp;quot;\/opt\/mount\/192.168.1.252-torrent\/\/Best of POP JCF&amp;quot;,&amp;quot;total&amp;quot;:8,&amp;quot;current&amp;quot;:[],&amp;quot;processed&amp;quot;:8,&amp;quot;remaining&amp;quot;:0,&amp;quot;success&amp;quot;:[1,2,3,4,5,6,7,8],&amp;quot;failure&amp;quot;:[]},&amp;quot;time&amp;quot;:{&amp;quot;start&amp;quot;:1546547784,&amp;quot;elapsed&amp;quot;:1,&amp;quot;end&amp;quot;:1546547785},&amp;quot;state&amp;quot;:2}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la liste des identifiants des travaux en cours&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la liste des identifiants des travaux disponibles pour consultation&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Stop le travail d&#039;indexation désignè par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Supprime les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=308</id>
		<title>Music sender api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=308"/>
		<updated>2019-01-13T11:15:25Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Share */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=User=&lt;br /&gt;
L&#039;objet user est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;pseudo&amp;quot;:&amp;quot;tala&amp;quot;,&amp;quot;email&amp;quot;:&amp;quot;tala@tala.com&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/&lt;br /&gt;
||&lt;br /&gt;
* pseudo : le pseudo de l&#039;utilisateur&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
* password : le mot de passe de l&#039;utilisateur&lt;br /&gt;
* image : l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Crée un nouvel utilisateur et renvoie son identifiant&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussi avec en réponse l&#039;identifiant (eg. {&amp;quot;id&amp;quot;:1} )&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/email/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;email du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/password/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* password : le nouveau mot de passe utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le mot de passe du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Genre=&lt;br /&gt;
L&#039;objet genre est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Electro-Jazz&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets genre&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet genre&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom du genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface le genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Artist=&lt;br /&gt;
L&#039;objet artiste est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;84&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;Yolanda Be Cool &amp;amp; Dcup&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;artist&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet artiste&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’artiste&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Album=&lt;br /&gt;
L&#039;objet album est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;album&amp;quot;:&amp;quot;Electro Swing Collection 1&amp;quot;,&amp;quot;coverId&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;album&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet album&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’album&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Music=&lt;br /&gt;
L&#039;objet musique est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;title&amp;quot;:&amp;quot;All Night&amp;quot;,&amp;quot;artists&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;genres&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;bitrate&amp;quot;:&amp;quot;128&amp;quot;,&amp;quot;hit&amp;quot;:&amp;quot;4&amp;quot;,&amp;quot;duration&amp;quot;:&amp;quot;163&amp;quot;,&amp;quot;id_image&amp;quot;:&amp;quot;1&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet musique au format Json &lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/content/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu de la musique (fichier son)&amp;lt;br&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json appartenant à l&#039;album associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json dont le créateur est l&#039;artiste associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Image=&lt;br /&gt;
L&#039;objet image est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;/9j/4B4…T0+7RRW/2Q==&amp;quot;,&amp;quot;mime&amp;quot;:&amp;quot;image\jpeg&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0aebaad7…4f265bd&amp;quot;} }&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/images&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets image&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/info/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/content/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Device=&lt;br /&gt;
L&#039;objet périphérique est composé comme suit : {&amp;quot;name&amp;quot;:&amp;quot;\/dev\/sda1&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;MUSIC&amp;quot;,&amp;quot;size&amp;quot;:&amp;quot;7.2 GiB&amp;quot;,&amp;quot;UUID&amp;quot;:&amp;quot;84B9-A853&amp;quot;,&amp;quot;fstype&amp;quot;:&amp;quot;vfat&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les périphériques&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/list/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers et dossiers:&lt;br /&gt;
&lt;br /&gt;
{&amp;quot;directories&amp;quot;:[&amp;quot;Pop&amp;quot;,&amp;quot;Rock&amp;quot;],&amp;quot;files&amp;quot;:[&amp;quot;Gala - Freed From Desire.mp3&amp;quot;,&amp;quot;13)Jacques Your Body (Make Me Sweat)(Jcf Pitch Edit).mp3&amp;quot;]}&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/content/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête &lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/tag/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques montés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/umounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques démontés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le périphérique sur le système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Active le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/index/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le périphérique du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Désactive le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Share=&lt;br /&gt;
L&#039;objet partage est composé comme suit : {&amp;quot;host&amp;quot;:&amp;quot;hades&amp;quot;,&amp;quot;share&amp;quot;:&amp;quot;downloads&amp;quot;,&amp;quot;login&amp;quot;:&amp;quot;nobody&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les partages montés&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des partages disponibles sur l&#039;hôte&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
** extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive de tous les fichiers disponibles sur le partage&lt;br /&gt;
&lt;br /&gt;
Attention, l&#039;appel peut être long, surtout lorsque les partages contiennent beaucoup de fichiers&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le partage existe&lt;br /&gt;
* 400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
** extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si le partage existe&lt;br /&gt;
*400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/content/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/tag/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* login : le login à utiliser (optionnel)&lt;br /&gt;
* password : le mot de passe associé (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le partage sur le système. Si aucun couple d&#039;authentification n&#039;est fourni, &#039;&#039;nobody&#039;&#039; sera utilisé&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/index/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le partage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le partage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Youtube =&lt;br /&gt;
Permet de récupérer des informations sur les vidéo Youtube&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère des informations sur la vidéo Youtube. Voici un exemple:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
&amp;quot;url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;cover&amp;quot;:&amp;quot;https:\/\/i.ytimg.com\/vi\/eVGrSCrRiy8\/maxresdefault.jpg&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;author&amp;quot;:&amp;quot;ElectroDanceMixes&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;title&amp;quot;:&amp;quot;FESTIVAL MIX - Best EDM &amp;amp; Electro House Dance Party Mix 2018&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;id&amp;quot;:&amp;quot;eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;videos&amp;quot;:[&amp;quot;...&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/cover/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la &#039;&#039;pochette&#039;&#039; de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/listen/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère le contenu de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Player=&lt;br /&gt;
Joue la musique sur la carte son du Pi (intégration VLC)&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/pause&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Met en pause la music&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/stop&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Stop la lecture&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/volume/$$PERCENT$$&lt;br /&gt;
*$$PERCENT$$ : le volume en poucentage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Règle le volume du lecteur&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/device/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le périphérique &#039;&#039;UUID&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier et le périphérique existent&lt;br /&gt;
*400 : si le fichier ou le périphérique n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le partage &#039;&#039;SHARE&#039;&#039; sur l&#039;hôte &#039;&#039;HOST&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier, le partage et l&#039;hôte existent&lt;br /&gt;
*400 : si le fichier, le partage ou l&#039;hôte n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/youtube/$$ID$$&lt;br /&gt;
||&lt;br /&gt;
* $$ID$$ : un ID de vidéo Youtube (https://www.youtube.com/watch?v=mEYyVY9ffDM &amp;amp;rarr; mEYyVY9ffDM)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le son de la vidéo, quand c&#039;est possible (certaines vidéos ne fonctionnent pas)&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la vidéo existe&lt;br /&gt;
* 400 : si le vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/url&lt;br /&gt;
||&lt;br /&gt;
* path : un lien vers un fichier musical&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Indexer (WIP)=&lt;br /&gt;
Permet d&#039;avoir des informations sur les travaux d&#039;indexation en cours. Voici un exemple:&lt;br /&gt;
* d&#039;identifiant de travail &amp;amp;rarr; 5c2e724887be4;&lt;br /&gt;
* d&#039;informations sur un travail &amp;amp;rarr; {&amp;quot;files&amp;quot;:{&amp;quot;directory&amp;quot;:&amp;quot;\/opt\/mount\/192.168.1.252-torrent\/\/Best of POP JCF&amp;quot;,&amp;quot;total&amp;quot;:8,&amp;quot;current&amp;quot;:[],&amp;quot;processed&amp;quot;:8,&amp;quot;remaining&amp;quot;:0,&amp;quot;success&amp;quot;:[1,2,3,4,5,6,7,8],&amp;quot;failure&amp;quot;:[]},&amp;quot;time&amp;quot;:{&amp;quot;start&amp;quot;:1546547784,&amp;quot;elapsed&amp;quot;:1,&amp;quot;end&amp;quot;:1546547785},&amp;quot;state&amp;quot;:2}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la liste des identifiants des travaux en cours&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la liste des identifiants des travaux disponibles pour consultation&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Stop le travail d&#039;indexation désignè par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Supprime les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=307</id>
		<title>Music sender api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=307"/>
		<updated>2019-01-13T11:12:59Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Device */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=User=&lt;br /&gt;
L&#039;objet user est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;pseudo&amp;quot;:&amp;quot;tala&amp;quot;,&amp;quot;email&amp;quot;:&amp;quot;tala@tala.com&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/&lt;br /&gt;
||&lt;br /&gt;
* pseudo : le pseudo de l&#039;utilisateur&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
* password : le mot de passe de l&#039;utilisateur&lt;br /&gt;
* image : l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Crée un nouvel utilisateur et renvoie son identifiant&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussi avec en réponse l&#039;identifiant (eg. {&amp;quot;id&amp;quot;:1} )&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/email/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;email du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/password/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* password : le nouveau mot de passe utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le mot de passe du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Genre=&lt;br /&gt;
L&#039;objet genre est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Electro-Jazz&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets genre&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet genre&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom du genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface le genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Artist=&lt;br /&gt;
L&#039;objet artiste est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;84&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;Yolanda Be Cool &amp;amp; Dcup&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;artist&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet artiste&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’artiste&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Album=&lt;br /&gt;
L&#039;objet album est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;album&amp;quot;:&amp;quot;Electro Swing Collection 1&amp;quot;,&amp;quot;coverId&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;album&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet album&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’album&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Music=&lt;br /&gt;
L&#039;objet musique est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;title&amp;quot;:&amp;quot;All Night&amp;quot;,&amp;quot;artists&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;genres&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;bitrate&amp;quot;:&amp;quot;128&amp;quot;,&amp;quot;hit&amp;quot;:&amp;quot;4&amp;quot;,&amp;quot;duration&amp;quot;:&amp;quot;163&amp;quot;,&amp;quot;id_image&amp;quot;:&amp;quot;1&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet musique au format Json &lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/content/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu de la musique (fichier son)&amp;lt;br&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json appartenant à l&#039;album associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json dont le créateur est l&#039;artiste associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Image=&lt;br /&gt;
L&#039;objet image est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;/9j/4B4…T0+7RRW/2Q==&amp;quot;,&amp;quot;mime&amp;quot;:&amp;quot;image\jpeg&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0aebaad7…4f265bd&amp;quot;} }&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/images&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets image&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/info/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/content/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Device=&lt;br /&gt;
L&#039;objet périphérique est composé comme suit : {&amp;quot;name&amp;quot;:&amp;quot;\/dev\/sda1&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;MUSIC&amp;quot;,&amp;quot;size&amp;quot;:&amp;quot;7.2 GiB&amp;quot;,&amp;quot;UUID&amp;quot;:&amp;quot;84B9-A853&amp;quot;,&amp;quot;fstype&amp;quot;:&amp;quot;vfat&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les périphériques&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/list/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
** extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers et dossiers:&lt;br /&gt;
&lt;br /&gt;
{&amp;quot;directories&amp;quot;:[&amp;quot;Pop&amp;quot;,&amp;quot;Rock&amp;quot;],&amp;quot;files&amp;quot;:[&amp;quot;Gala - Freed From Desire.mp3&amp;quot;,&amp;quot;13)Jacques Your Body (Make Me Sweat)(Jcf Pitch Edit).mp3&amp;quot;]}&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/content/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête &lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/tag/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques montés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/umounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques démontés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le périphérique sur le système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Active le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/index/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
* paramètre(s):&lt;br /&gt;
** path : un chemin sur le périphérique&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le périphérique du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Désactive le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Share=&lt;br /&gt;
L&#039;objet partage est composé comme suit : {&amp;quot;host&amp;quot;:&amp;quot;hades&amp;quot;,&amp;quot;share&amp;quot;:&amp;quot;downloads&amp;quot;,&amp;quot;login&amp;quot;:&amp;quot;nobody&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les partages montés&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des partages disponibles sur l&#039;hôte&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
* extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive de tous les fichiers disponibles sur le partage&lt;br /&gt;
&lt;br /&gt;
Attention, l&#039;appel peut être long, surtout lorsque les partages contiennent beaucoup de fichiers&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le partage existe&lt;br /&gt;
* 400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un répertoire sur le partage&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si le partage existe&lt;br /&gt;
*400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/content/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/tag/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* login : le login à utiliser (optionnel)&lt;br /&gt;
* password : le mot de passe associé (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le partage sur le système. Si aucun couple d&#039;authentification n&#039;est fourni, &#039;&#039;nobody&#039;&#039; sera utilisé&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/index/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le partage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Youtube =&lt;br /&gt;
Permet de récupérer des informations sur les vidéo Youtube&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère des informations sur la vidéo Youtube. Voici un exemple:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
&amp;quot;url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;cover&amp;quot;:&amp;quot;https:\/\/i.ytimg.com\/vi\/eVGrSCrRiy8\/maxresdefault.jpg&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;author&amp;quot;:&amp;quot;ElectroDanceMixes&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;title&amp;quot;:&amp;quot;FESTIVAL MIX - Best EDM &amp;amp; Electro House Dance Party Mix 2018&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;id&amp;quot;:&amp;quot;eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;videos&amp;quot;:[&amp;quot;...&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/cover/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la &#039;&#039;pochette&#039;&#039; de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/listen/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère le contenu de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Player=&lt;br /&gt;
Joue la musique sur la carte son du Pi (intégration VLC)&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/pause&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Met en pause la music&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/stop&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Stop la lecture&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/volume/$$PERCENT$$&lt;br /&gt;
*$$PERCENT$$ : le volume en poucentage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Règle le volume du lecteur&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/device/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le périphérique &#039;&#039;UUID&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier et le périphérique existent&lt;br /&gt;
*400 : si le fichier ou le périphérique n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le partage &#039;&#039;SHARE&#039;&#039; sur l&#039;hôte &#039;&#039;HOST&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier, le partage et l&#039;hôte existent&lt;br /&gt;
*400 : si le fichier, le partage ou l&#039;hôte n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/youtube/$$ID$$&lt;br /&gt;
||&lt;br /&gt;
* $$ID$$ : un ID de vidéo Youtube (https://www.youtube.com/watch?v=mEYyVY9ffDM &amp;amp;rarr; mEYyVY9ffDM)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le son de la vidéo, quand c&#039;est possible (certaines vidéos ne fonctionnent pas)&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la vidéo existe&lt;br /&gt;
* 400 : si le vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/url&lt;br /&gt;
||&lt;br /&gt;
* path : un lien vers un fichier musical&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Indexer (WIP)=&lt;br /&gt;
Permet d&#039;avoir des informations sur les travaux d&#039;indexation en cours. Voici un exemple:&lt;br /&gt;
* d&#039;identifiant de travail &amp;amp;rarr; 5c2e724887be4;&lt;br /&gt;
* d&#039;informations sur un travail &amp;amp;rarr; {&amp;quot;files&amp;quot;:{&amp;quot;directory&amp;quot;:&amp;quot;\/opt\/mount\/192.168.1.252-torrent\/\/Best of POP JCF&amp;quot;,&amp;quot;total&amp;quot;:8,&amp;quot;current&amp;quot;:[],&amp;quot;processed&amp;quot;:8,&amp;quot;remaining&amp;quot;:0,&amp;quot;success&amp;quot;:[1,2,3,4,5,6,7,8],&amp;quot;failure&amp;quot;:[]},&amp;quot;time&amp;quot;:{&amp;quot;start&amp;quot;:1546547784,&amp;quot;elapsed&amp;quot;:1,&amp;quot;end&amp;quot;:1546547785},&amp;quot;state&amp;quot;:2}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la liste des identifiants des travaux en cours&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la liste des identifiants des travaux disponibles pour consultation&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Stop le travail d&#039;indexation désignè par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Supprime les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=306</id>
		<title>Music sender api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=306"/>
		<updated>2019-01-03T23:30:00Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Player */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=User=&lt;br /&gt;
L&#039;objet user est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;pseudo&amp;quot;:&amp;quot;tala&amp;quot;,&amp;quot;email&amp;quot;:&amp;quot;tala@tala.com&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/&lt;br /&gt;
||&lt;br /&gt;
* pseudo : le pseudo de l&#039;utilisateur&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
* password : le mot de passe de l&#039;utilisateur&lt;br /&gt;
* image : l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Crée un nouvel utilisateur et renvoie son identifiant&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussi avec en réponse l&#039;identifiant (eg. {&amp;quot;id&amp;quot;:1} )&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/email/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;email du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/password/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* password : le nouveau mot de passe utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le mot de passe du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Genre=&lt;br /&gt;
L&#039;objet genre est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Electro-Jazz&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets genre&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet genre&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom du genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface le genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Artist=&lt;br /&gt;
L&#039;objet artiste est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;84&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;Yolanda Be Cool &amp;amp; Dcup&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;artist&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet artiste&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’artiste&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Album=&lt;br /&gt;
L&#039;objet album est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;album&amp;quot;:&amp;quot;Electro Swing Collection 1&amp;quot;,&amp;quot;coverId&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;album&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet album&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’album&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Music=&lt;br /&gt;
L&#039;objet musique est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;title&amp;quot;:&amp;quot;All Night&amp;quot;,&amp;quot;artists&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;genres&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;bitrate&amp;quot;:&amp;quot;128&amp;quot;,&amp;quot;hit&amp;quot;:&amp;quot;4&amp;quot;,&amp;quot;duration&amp;quot;:&amp;quot;163&amp;quot;,&amp;quot;id_image&amp;quot;:&amp;quot;1&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet musique au format Json &lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/content/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu de la musique (fichier son)&amp;lt;br&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json appartenant à l&#039;album associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json dont le créateur est l&#039;artiste associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Image=&lt;br /&gt;
L&#039;objet image est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;/9j/4B4…T0+7RRW/2Q==&amp;quot;,&amp;quot;mime&amp;quot;:&amp;quot;image\jpeg&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0aebaad7…4f265bd&amp;quot;} }&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/images&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets image&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/info/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/content/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Device=&lt;br /&gt;
L&#039;objet périphérique est composé comme suit : {&amp;quot;name&amp;quot;:&amp;quot;\/dev\/sda1&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;MUSIC&amp;quot;,&amp;quot;size&amp;quot;:&amp;quot;7.2 GiB&amp;quot;,&amp;quot;UUID&amp;quot;:&amp;quot;84B9-A853&amp;quot;,&amp;quot;fstype&amp;quot;:&amp;quot;vfat&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les périphériques&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/list/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un répertoire sur le périphérique&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers et dossiers:&lt;br /&gt;
&lt;br /&gt;
{&amp;quot;directories&amp;quot;:[&amp;quot;Pop&amp;quot;,&amp;quot;Rock&amp;quot;],&amp;quot;files&amp;quot;:[&amp;quot;Gala - Freed From Desire.mp3&amp;quot;,&amp;quot;13)Jacques Your Body (Make Me Sweat)(Jcf Pitch Edit).mp3&amp;quot;]}&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/content/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête &lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/tag/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques montés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/umounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques démontés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le périphérique sur le système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Active le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/index/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le périphérique du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Désactive le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Share=&lt;br /&gt;
L&#039;objet partage est composé comme suit : {&amp;quot;host&amp;quot;:&amp;quot;hades&amp;quot;,&amp;quot;share&amp;quot;:&amp;quot;downloads&amp;quot;,&amp;quot;login&amp;quot;:&amp;quot;nobody&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les partages montés&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des partages disponibles sur l&#039;hôte&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
* extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive de tous les fichiers disponibles sur le partage&lt;br /&gt;
&lt;br /&gt;
Attention, l&#039;appel peut être long, surtout lorsque les partages contiennent beaucoup de fichiers&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le partage existe&lt;br /&gt;
* 400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un répertoire sur le partage&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si le partage existe&lt;br /&gt;
*400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/content/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/tag/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* login : le login à utiliser (optionnel)&lt;br /&gt;
* password : le mot de passe associé (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le partage sur le système. Si aucun couple d&#039;authentification n&#039;est fourni, &#039;&#039;nobody&#039;&#039; sera utilisé&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/index/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le partage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Youtube =&lt;br /&gt;
Permet de récupérer des informations sur les vidéo Youtube&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère des informations sur la vidéo Youtube. Voici un exemple:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
&amp;quot;url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;cover&amp;quot;:&amp;quot;https:\/\/i.ytimg.com\/vi\/eVGrSCrRiy8\/maxresdefault.jpg&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;author&amp;quot;:&amp;quot;ElectroDanceMixes&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;title&amp;quot;:&amp;quot;FESTIVAL MIX - Best EDM &amp;amp; Electro House Dance Party Mix 2018&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;id&amp;quot;:&amp;quot;eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;videos&amp;quot;:[&amp;quot;...&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/cover/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la &#039;&#039;pochette&#039;&#039; de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/listen/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère le contenu de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Player=&lt;br /&gt;
Joue la musique sur la carte son du Pi (intégration VLC)&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/pause&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Met en pause la music&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/stop&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Stop la lecture&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/volume/$$PERCENT$$&lt;br /&gt;
*$$PERCENT$$ : le volume en poucentage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Règle le volume du lecteur&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/device/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le périphérique &#039;&#039;UUID&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier et le périphérique existent&lt;br /&gt;
*400 : si le fichier ou le périphérique n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le partage &#039;&#039;SHARE&#039;&#039; sur l&#039;hôte &#039;&#039;HOST&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier, le partage et l&#039;hôte existent&lt;br /&gt;
*400 : si le fichier, le partage ou l&#039;hôte n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/youtube/$$ID$$&lt;br /&gt;
||&lt;br /&gt;
* $$ID$$ : un ID de vidéo Youtube (https://www.youtube.com/watch?v=mEYyVY9ffDM &amp;amp;rarr; mEYyVY9ffDM)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le son de la vidéo, quand c&#039;est possible (certaines vidéos ne fonctionnent pas)&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la vidéo existe&lt;br /&gt;
* 400 : si le vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/url&lt;br /&gt;
||&lt;br /&gt;
* path : un lien vers un fichier musical&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Indexer (WIP)=&lt;br /&gt;
Permet d&#039;avoir des informations sur les travaux d&#039;indexation en cours. Voici un exemple:&lt;br /&gt;
* d&#039;identifiant de travail &amp;amp;rarr; 5c2e724887be4;&lt;br /&gt;
* d&#039;informations sur un travail &amp;amp;rarr; {&amp;quot;files&amp;quot;:{&amp;quot;directory&amp;quot;:&amp;quot;\/opt\/mount\/192.168.1.252-torrent\/\/Best of POP JCF&amp;quot;,&amp;quot;total&amp;quot;:8,&amp;quot;current&amp;quot;:[],&amp;quot;processed&amp;quot;:8,&amp;quot;remaining&amp;quot;:0,&amp;quot;success&amp;quot;:[1,2,3,4,5,6,7,8],&amp;quot;failure&amp;quot;:[]},&amp;quot;time&amp;quot;:{&amp;quot;start&amp;quot;:1546547784,&amp;quot;elapsed&amp;quot;:1,&amp;quot;end&amp;quot;:1546547785},&amp;quot;state&amp;quot;:2}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la liste des identifiants des travaux en cours&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la liste des identifiants des travaux disponibles pour consultation&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Stop le travail d&#039;indexation désignè par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Supprime les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=305</id>
		<title>Music sender api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=305"/>
		<updated>2019-01-03T23:28:49Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Indexer (WIP) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=User=&lt;br /&gt;
L&#039;objet user est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;pseudo&amp;quot;:&amp;quot;tala&amp;quot;,&amp;quot;email&amp;quot;:&amp;quot;tala@tala.com&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/&lt;br /&gt;
||&lt;br /&gt;
* pseudo : le pseudo de l&#039;utilisateur&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
* password : le mot de passe de l&#039;utilisateur&lt;br /&gt;
* image : l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Crée un nouvel utilisateur et renvoie son identifiant&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussi avec en réponse l&#039;identifiant (eg. {&amp;quot;id&amp;quot;:1} )&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/email/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;email du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/password/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* password : le nouveau mot de passe utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le mot de passe du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Genre=&lt;br /&gt;
L&#039;objet genre est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Electro-Jazz&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets genre&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet genre&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom du genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface le genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Artist=&lt;br /&gt;
L&#039;objet artiste est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;84&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;Yolanda Be Cool &amp;amp; Dcup&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;artist&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet artiste&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’artiste&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Album=&lt;br /&gt;
L&#039;objet album est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;album&amp;quot;:&amp;quot;Electro Swing Collection 1&amp;quot;,&amp;quot;coverId&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;album&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet album&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’album&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Music=&lt;br /&gt;
L&#039;objet musique est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;title&amp;quot;:&amp;quot;All Night&amp;quot;,&amp;quot;artists&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;genres&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;bitrate&amp;quot;:&amp;quot;128&amp;quot;,&amp;quot;hit&amp;quot;:&amp;quot;4&amp;quot;,&amp;quot;duration&amp;quot;:&amp;quot;163&amp;quot;,&amp;quot;id_image&amp;quot;:&amp;quot;1&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet musique au format Json &lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/content/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu de la musique (fichier son)&amp;lt;br&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json appartenant à l&#039;album associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json dont le créateur est l&#039;artiste associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Image=&lt;br /&gt;
L&#039;objet image est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;/9j/4B4…T0+7RRW/2Q==&amp;quot;,&amp;quot;mime&amp;quot;:&amp;quot;image\jpeg&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0aebaad7…4f265bd&amp;quot;} }&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/images&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets image&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/info/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/content/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Device=&lt;br /&gt;
L&#039;objet périphérique est composé comme suit : {&amp;quot;name&amp;quot;:&amp;quot;\/dev\/sda1&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;MUSIC&amp;quot;,&amp;quot;size&amp;quot;:&amp;quot;7.2 GiB&amp;quot;,&amp;quot;UUID&amp;quot;:&amp;quot;84B9-A853&amp;quot;,&amp;quot;fstype&amp;quot;:&amp;quot;vfat&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les périphériques&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/list/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un répertoire sur le périphérique&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers et dossiers:&lt;br /&gt;
&lt;br /&gt;
{&amp;quot;directories&amp;quot;:[&amp;quot;Pop&amp;quot;,&amp;quot;Rock&amp;quot;],&amp;quot;files&amp;quot;:[&amp;quot;Gala - Freed From Desire.mp3&amp;quot;,&amp;quot;13)Jacques Your Body (Make Me Sweat)(Jcf Pitch Edit).mp3&amp;quot;]}&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/content/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête &lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/tag/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques montés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/umounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques démontés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le périphérique sur le système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Active le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/index/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le périphérique du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Désactive le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Share=&lt;br /&gt;
L&#039;objet partage est composé comme suit : {&amp;quot;host&amp;quot;:&amp;quot;hades&amp;quot;,&amp;quot;share&amp;quot;:&amp;quot;downloads&amp;quot;,&amp;quot;login&amp;quot;:&amp;quot;nobody&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les partages montés&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des partages disponibles sur l&#039;hôte&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
* extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive de tous les fichiers disponibles sur le partage&lt;br /&gt;
&lt;br /&gt;
Attention, l&#039;appel peut être long, surtout lorsque les partages contiennent beaucoup de fichiers&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le partage existe&lt;br /&gt;
* 400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un répertoire sur le partage&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si le partage existe&lt;br /&gt;
*400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/content/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/tag/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* login : le login à utiliser (optionnel)&lt;br /&gt;
* password : le mot de passe associé (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le partage sur le système. Si aucun couple d&#039;authentification n&#039;est fourni, &#039;&#039;nobody&#039;&#039; sera utilisé&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/index/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le partage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Youtube =&lt;br /&gt;
Permet de récupérer des informations sur les vidéo Youtube&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère des informations sur la vidéo Youtube. Voici un exemple:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
&amp;quot;url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;cover&amp;quot;:&amp;quot;https:\/\/i.ytimg.com\/vi\/eVGrSCrRiy8\/maxresdefault.jpg&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;author&amp;quot;:&amp;quot;ElectroDanceMixes&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;title&amp;quot;:&amp;quot;FESTIVAL MIX - Best EDM &amp;amp; Electro House Dance Party Mix 2018&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;id&amp;quot;:&amp;quot;eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;videos&amp;quot;:[&amp;quot;...&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/cover/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la &#039;&#039;pochette&#039;&#039; de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/listen/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère le contenu de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Player=&lt;br /&gt;
Joue la musique sur la carte son du Pi (intégration VLC)&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/pause&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Met en pause la music&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/stop&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Stop la lecture&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/volume/$$PERCENT$$&lt;br /&gt;
*$$PERCENT$$ : le volume en poucentage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Règle le volume du lecteur&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/device/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le périphérique &#039;&#039;UUID&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier et le périphérique existent&lt;br /&gt;
*400 : si le fichier ou le périphérique n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le partage &#039;&#039;SHARE&#039;&#039; sur l&#039;hôte &#039;&#039;HOST&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier, le partage et l&#039;hôte existent&lt;br /&gt;
*400 : si le fichier, le partage ou l&#039;hôte n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/youtube&lt;br /&gt;
||&lt;br /&gt;
* path : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=mEYyVY9ffDM ou mEYyVY9ffDM)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le son de la vidéo, quand c&#039;est possible (certaines vidéos ne fonctionnent pas)&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la vidéo existe&lt;br /&gt;
* 400 : si le vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/url&lt;br /&gt;
||&lt;br /&gt;
* path : un lien vers un fichier musical&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Indexer (WIP)=&lt;br /&gt;
Permet d&#039;avoir des informations sur les travaux d&#039;indexation en cours. Voici un exemple:&lt;br /&gt;
* d&#039;identifiant de travail &amp;amp;rarr; 5c2e724887be4;&lt;br /&gt;
* d&#039;informations sur un travail &amp;amp;rarr; {&amp;quot;files&amp;quot;:{&amp;quot;directory&amp;quot;:&amp;quot;\/opt\/mount\/192.168.1.252-torrent\/\/Best of POP JCF&amp;quot;,&amp;quot;total&amp;quot;:8,&amp;quot;current&amp;quot;:[],&amp;quot;processed&amp;quot;:8,&amp;quot;remaining&amp;quot;:0,&amp;quot;success&amp;quot;:[1,2,3,4,5,6,7,8],&amp;quot;failure&amp;quot;:[]},&amp;quot;time&amp;quot;:{&amp;quot;start&amp;quot;:1546547784,&amp;quot;elapsed&amp;quot;:1,&amp;quot;end&amp;quot;:1546547785},&amp;quot;state&amp;quot;:2}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la liste des identifiants des travaux en cours&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la liste des identifiants des travaux disponibles pour consultation&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Stop le travail d&#039;indexation désignè par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Supprime les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Roadmap_orange_pi_music&amp;diff=304</id>
		<title>Roadmap orange pi music</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Roadmap_orange_pi_music&amp;diff=304"/>
		<updated>2019-01-03T22:59:43Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* GUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Fonctionnalités ==&lt;br /&gt;
* Réfléchir à un système de playlist, avec ou sans indexation;&lt;br /&gt;
== API ==&lt;br /&gt;
* Finir la partie relative à Youtube ;&lt;br /&gt;
* Procéder à une authentification (OAuth);&lt;br /&gt;
== GUI ==&lt;br /&gt;
===Partie device===&lt;br /&gt;
* Listage des périphériques USB montés / démontés&lt;br /&gt;
[[Fichier:device_available.png|centré|500px]]&lt;br /&gt;
* Montage d&#039;un périphérique USB&lt;br /&gt;
[[Fichier:device_mount.png|centré|500px]]&lt;br /&gt;
* Parcours d&#039;un périphérique USB monté&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:device_explorer.png|centré|500px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:device_explorer1.png|centré|500px]]&lt;br /&gt;
|}&lt;br /&gt;
===Partie share===&lt;br /&gt;
* Parcours des partages SMB/CIFS sur un hôte&lt;br /&gt;
[[Fichier:share_host.png|centré|500px]]&lt;br /&gt;
* Montage d&#039;un partage avec automount&lt;br /&gt;
[[Fichier:share_mount.png|centré|500px]]&lt;br /&gt;
*Parcours d&#039;un partage&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:share_explorer1.png|centré|500px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:share_explorer.png|centré|500px]]&lt;br /&gt;
|}&lt;br /&gt;
===Partie player===&lt;br /&gt;
*Lecture d&#039;un MP3 avec tag&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:player_1.png|centré|500px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:player_2.png|centré|500px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Kernel ==&lt;br /&gt;
* Écrire un démon ou faire un CRON ;&lt;br /&gt;
* Utiliser un fichier de configuration global ;&lt;br /&gt;
* Tester la présence de périphérique USB ;&lt;br /&gt;
&lt;br /&gt;
== BUGS ==&lt;br /&gt;
=== BDD ===&lt;br /&gt;
* La partie indexation mérite réflexion, dans cet état elle est trop restrictive et nécessite un TAG trop parfait pour réussir. Voir pour faire une indexation plus souple qui réussie même en l&#039;absence de certain champ (artiste, album, genre, pochette, etc...). Problème à régler dans la classe &#039;&#039;DaoMusique&#039;&#039; et &#039;&#039;Tag&#039;&#039;.&lt;br /&gt;
* Problème de typage pour le champ &#039;&#039;duration&#039;&#039;, il faut le repasser en secondes pour que cela fonctionne&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 select * from music;&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
| id_music | title                  | bitrate | hit  | duration | path                                         | id_image |&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
|        1 | Five More hours        |     128 |    0 |        3 | Deorro &amp;amp; Chris Brown   Five More Hours.mp3   |        1 |&lt;br /&gt;
|        2 | Milkshake (TRFN Remix) |     192 |    0 |        2 | 2018/Kelis - Milkshake (TRFN Remix).mp3      |        2 |&lt;br /&gt;
|        3 | Uptown Funk            |     128 |    0 |        4 | Mark Ronson ft. Bruno Mars - Uptown Funk.mp3 |        3 |&lt;br /&gt;
|        4 | Want To Want Me        |     128 |    0 |        3 | Jason Derulo - Want To Want Me.mp3           |        4 |&lt;br /&gt;
|        5 | Love Me Like You Do    |     128 |    0 |        4 | Ellie Goulding - Love Me Like You Do.mp3     |        1 |&lt;br /&gt;
|        6 | Take Me To Church      |     128 |    0 |        4 | Hozier - Take Me To Church.mp3               |        1 |&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Device_mount.png&amp;diff=303</id>
		<title>Fichier:Device mount.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Device_mount.png&amp;diff=303"/>
		<updated>2019-01-03T22:59:04Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Device_available.png&amp;diff=302</id>
		<title>Fichier:Device available.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Device_available.png&amp;diff=302"/>
		<updated>2019-01-03T22:58:43Z</updated>

		<summary type="html">&lt;p&gt;Tala : Tala a téléversé une nouvelle version de Fichier:Device available.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Device_available.png&amp;diff=301</id>
		<title>Fichier:Device available.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Device_available.png&amp;diff=301"/>
		<updated>2019-01-03T22:57:59Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Device_explorer.png&amp;diff=300</id>
		<title>Fichier:Device explorer.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Device_explorer.png&amp;diff=300"/>
		<updated>2019-01-03T22:56:50Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Device_explorer1.png&amp;diff=299</id>
		<title>Fichier:Device explorer1.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Device_explorer1.png&amp;diff=299"/>
		<updated>2019-01-03T22:56:29Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Share_host.png&amp;diff=298</id>
		<title>Fichier:Share host.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Share_host.png&amp;diff=298"/>
		<updated>2019-01-03T22:54:32Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Share_mount.png&amp;diff=297</id>
		<title>Fichier:Share mount.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Share_mount.png&amp;diff=297"/>
		<updated>2019-01-03T22:54:17Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Share_explorer1.png&amp;diff=296</id>
		<title>Fichier:Share explorer1.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Share_explorer1.png&amp;diff=296"/>
		<updated>2019-01-03T22:53:40Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Share_explorer.png&amp;diff=295</id>
		<title>Fichier:Share explorer.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Share_explorer.png&amp;diff=295"/>
		<updated>2019-01-03T22:52:23Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Player_2.png&amp;diff=294</id>
		<title>Fichier:Player 2.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Player_2.png&amp;diff=294"/>
		<updated>2019-01-03T22:51:06Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Fichier:Player_1.png&amp;diff=293</id>
		<title>Fichier:Player 1.png</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Fichier:Player_1.png&amp;diff=293"/>
		<updated>2019-01-03T22:50:35Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Roadmap_orange_pi_music&amp;diff=292</id>
		<title>Roadmap orange pi music</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Roadmap_orange_pi_music&amp;diff=292"/>
		<updated>2019-01-03T22:37:50Z</updated>

		<summary type="html">&lt;p&gt;Tala : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Fonctionnalités ==&lt;br /&gt;
* Réfléchir à un système de playlist, avec ou sans indexation;&lt;br /&gt;
== API ==&lt;br /&gt;
* Finir la partie relative à Youtube ;&lt;br /&gt;
* Procéder à une authentification (OAuth);&lt;br /&gt;
== GUI ==&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
== Kernel ==&lt;br /&gt;
* Écrire un démon ou faire un CRON ;&lt;br /&gt;
* Utiliser un fichier de configuration global ;&lt;br /&gt;
* Tester la présence de périphérique USB ;&lt;br /&gt;
&lt;br /&gt;
== BUGS ==&lt;br /&gt;
=== BDD ===&lt;br /&gt;
* La partie indexation mérite réflexion, dans cet état elle est trop restrictive et nécessite un TAG trop parfait pour réussir. Voir pour faire une indexation plus souple qui réussie même en l&#039;absence de certain champ (artiste, album, genre, pochette, etc...). Problème à régler dans la classe &#039;&#039;DaoMusique&#039;&#039; et &#039;&#039;Tag&#039;&#039;.&lt;br /&gt;
* Problème de typage pour le champ &#039;&#039;duration&#039;&#039;, il faut le repasser en secondes pour que cela fonctionne&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 select * from music;&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
| id_music | title                  | bitrate | hit  | duration | path                                         | id_image |&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
|        1 | Five More hours        |     128 |    0 |        3 | Deorro &amp;amp; Chris Brown   Five More Hours.mp3   |        1 |&lt;br /&gt;
|        2 | Milkshake (TRFN Remix) |     192 |    0 |        2 | 2018/Kelis - Milkshake (TRFN Remix).mp3      |        2 |&lt;br /&gt;
|        3 | Uptown Funk            |     128 |    0 |        4 | Mark Ronson ft. Bruno Mars - Uptown Funk.mp3 |        3 |&lt;br /&gt;
|        4 | Want To Want Me        |     128 |    0 |        3 | Jason Derulo - Want To Want Me.mp3           |        4 |&lt;br /&gt;
|        5 | Love Me Like You Do    |     128 |    0 |        4 | Ellie Goulding - Love Me Like You Do.mp3     |        1 |&lt;br /&gt;
|        6 | Take Me To Church      |     128 |    0 |        4 | Hozier - Take Me To Church.mp3               |        1 |&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Roadmap_orange_pi_music&amp;diff=291</id>
		<title>Roadmap orange pi music</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Roadmap_orange_pi_music&amp;diff=291"/>
		<updated>2019-01-03T22:03:20Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Kernel */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== API ==&lt;br /&gt;
* Finir la partie relative à Youtube ;&lt;br /&gt;
&lt;br /&gt;
== GUI ==&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
== Kernel ==&lt;br /&gt;
* Écrire un démon ou faire un CRON ;&lt;br /&gt;
* Utiliser un fichier de configuration global ;&lt;br /&gt;
* Tester la présence de périphérique USB ;&lt;br /&gt;
&lt;br /&gt;
== BUGS ==&lt;br /&gt;
=== BDD ===&lt;br /&gt;
* La partie indexation mérite réflexion, dans cet état elle est trop restrictive et nécessite un TAG trop parfait pour réussir. Voir pour faire une indexation plus souple qui réussie même en l&#039;absence de certain champ (artiste, album, genre, pochette, etc...). Problème à régler dans la classe &#039;&#039;DaoMusique&#039;&#039; et &#039;&#039;Tag&#039;&#039;.&lt;br /&gt;
* Problème de typage pour le champ &#039;&#039;duration&#039;&#039;, il faut le repasser en secondes pour que cela fonctionne&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 select * from music;&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
| id_music | title                  | bitrate | hit  | duration | path                                         | id_image |&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
|        1 | Five More hours        |     128 |    0 |        3 | Deorro &amp;amp; Chris Brown   Five More Hours.mp3   |        1 |&lt;br /&gt;
|        2 | Milkshake (TRFN Remix) |     192 |    0 |        2 | 2018/Kelis - Milkshake (TRFN Remix).mp3      |        2 |&lt;br /&gt;
|        3 | Uptown Funk            |     128 |    0 |        4 | Mark Ronson ft. Bruno Mars - Uptown Funk.mp3 |        3 |&lt;br /&gt;
|        4 | Want To Want Me        |     128 |    0 |        3 | Jason Derulo - Want To Want Me.mp3           |        4 |&lt;br /&gt;
|        5 | Love Me Like You Do    |     128 |    0 |        4 | Ellie Goulding - Love Me Like You Do.mp3     |        1 |&lt;br /&gt;
|        6 | Take Me To Church      |     128 |    0 |        4 | Hozier - Take Me To Church.mp3               |        1 |&lt;br /&gt;
+----------+------------------------+---------+------+----------+----------------------------------------------+----------+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=290</id>
		<title>Music sender api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=290"/>
		<updated>2019-01-03T20:39:19Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Indexer (WIP) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=User=&lt;br /&gt;
L&#039;objet user est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;pseudo&amp;quot;:&amp;quot;tala&amp;quot;,&amp;quot;email&amp;quot;:&amp;quot;tala@tala.com&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/&lt;br /&gt;
||&lt;br /&gt;
* pseudo : le pseudo de l&#039;utilisateur&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
* password : le mot de passe de l&#039;utilisateur&lt;br /&gt;
* image : l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Crée un nouvel utilisateur et renvoie son identifiant&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussi avec en réponse l&#039;identifiant (eg. {&amp;quot;id&amp;quot;:1} )&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/email/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;email du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/password/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* password : le nouveau mot de passe utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le mot de passe du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Genre=&lt;br /&gt;
L&#039;objet genre est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Electro-Jazz&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets genre&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet genre&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom du genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface le genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Artist=&lt;br /&gt;
L&#039;objet artiste est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;84&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;Yolanda Be Cool &amp;amp; Dcup&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;artist&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet artiste&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’artiste&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Album=&lt;br /&gt;
L&#039;objet album est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;album&amp;quot;:&amp;quot;Electro Swing Collection 1&amp;quot;,&amp;quot;coverId&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;album&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet album&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’album&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Music=&lt;br /&gt;
L&#039;objet musique est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;title&amp;quot;:&amp;quot;All Night&amp;quot;,&amp;quot;artists&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;genres&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;bitrate&amp;quot;:&amp;quot;128&amp;quot;,&amp;quot;hit&amp;quot;:&amp;quot;4&amp;quot;,&amp;quot;duration&amp;quot;:&amp;quot;163&amp;quot;,&amp;quot;id_image&amp;quot;:&amp;quot;1&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet musique au format Json &lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/content/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu de la musique (fichier son)&amp;lt;br&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json appartenant à l&#039;album associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json dont le créateur est l&#039;artiste associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Image=&lt;br /&gt;
L&#039;objet image est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;/9j/4B4…T0+7RRW/2Q==&amp;quot;,&amp;quot;mime&amp;quot;:&amp;quot;image\jpeg&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0aebaad7…4f265bd&amp;quot;} }&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/images&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets image&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/info/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/content/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Device=&lt;br /&gt;
L&#039;objet périphérique est composé comme suit : {&amp;quot;name&amp;quot;:&amp;quot;\/dev\/sda1&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;MUSIC&amp;quot;,&amp;quot;size&amp;quot;:&amp;quot;7.2 GiB&amp;quot;,&amp;quot;UUID&amp;quot;:&amp;quot;84B9-A853&amp;quot;,&amp;quot;fstype&amp;quot;:&amp;quot;vfat&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les périphériques&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/list/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un répertoire sur le périphérique&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers et dossiers:&lt;br /&gt;
&lt;br /&gt;
{&amp;quot;directories&amp;quot;:[&amp;quot;Pop&amp;quot;,&amp;quot;Rock&amp;quot;],&amp;quot;files&amp;quot;:[&amp;quot;Gala - Freed From Desire.mp3&amp;quot;,&amp;quot;13)Jacques Your Body (Make Me Sweat)(Jcf Pitch Edit).mp3&amp;quot;]}&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/content/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête &lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/tag/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques montés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/umounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques démontés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le périphérique sur le système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Active le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/index/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le périphérique du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Désactive le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Share=&lt;br /&gt;
L&#039;objet partage est composé comme suit : {&amp;quot;host&amp;quot;:&amp;quot;hades&amp;quot;,&amp;quot;share&amp;quot;:&amp;quot;downloads&amp;quot;,&amp;quot;login&amp;quot;:&amp;quot;nobody&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les partages montés&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des partages disponibles sur l&#039;hôte&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
* extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive de tous les fichiers disponibles sur le partage&lt;br /&gt;
&lt;br /&gt;
Attention, l&#039;appel peut être long, surtout lorsque les partages contiennent beaucoup de fichiers&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le partage existe&lt;br /&gt;
* 400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un répertoire sur le partage&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si le partage existe&lt;br /&gt;
*400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/content/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/tag/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* login : le login à utiliser (optionnel)&lt;br /&gt;
* password : le mot de passe associé (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le partage sur le système. Si aucun couple d&#039;authentification n&#039;est fourni, &#039;&#039;nobody&#039;&#039; sera utilisé&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/index/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le partage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Youtube =&lt;br /&gt;
Permet de récupérer des informations sur les vidéo Youtube&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère des informations sur la vidéo Youtube. Voici un exemple:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
&amp;quot;url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;cover&amp;quot;:&amp;quot;https:\/\/i.ytimg.com\/vi\/eVGrSCrRiy8\/maxresdefault.jpg&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;author&amp;quot;:&amp;quot;ElectroDanceMixes&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;title&amp;quot;:&amp;quot;FESTIVAL MIX - Best EDM &amp;amp; Electro House Dance Party Mix 2018&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;id&amp;quot;:&amp;quot;eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;videos&amp;quot;:[&amp;quot;...&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/cover/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la &#039;&#039;pochette&#039;&#039; de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/listen/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère le contenu de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Player=&lt;br /&gt;
Joue la musique sur la carte son du Pi (intégration VLC)&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/pause&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Met en pause la music&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/stop&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Stop la lecture&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/volume/$$PERCENT$$&lt;br /&gt;
*$$PERCENT$$ : le volume en poucentage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Règle le volume du lecteur&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/device/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le périphérique &#039;&#039;UUID&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier et le périphérique existent&lt;br /&gt;
*400 : si le fichier ou le périphérique n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le partage &#039;&#039;SHARE&#039;&#039; sur l&#039;hôte &#039;&#039;HOST&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier, le partage et l&#039;hôte existent&lt;br /&gt;
*400 : si le fichier, le partage ou l&#039;hôte n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/youtube&lt;br /&gt;
||&lt;br /&gt;
* path : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=mEYyVY9ffDM ou mEYyVY9ffDM)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le son de la vidéo, quand c&#039;est possible (certaines vidéos ne fonctionnent pas)&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la vidéo existe&lt;br /&gt;
* 400 : si le vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/url&lt;br /&gt;
||&lt;br /&gt;
* path : un lien vers un fichier musical&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Indexer (WIP)=&lt;br /&gt;
Permet d&#039;avoir des informations sur les travaux d&#039;indexation en cours. Voici un exemple:&lt;br /&gt;
* d&#039;identifiant de travai &amp;amp;rarr; 5c2e724887be4;&lt;br /&gt;
* d&#039;informations sur un travail &amp;amp;rarr; {&amp;quot;files&amp;quot;:{&amp;quot;directory&amp;quot;:&amp;quot;\/opt\/mount\/192.168.1.252-torrent\/\/Best of POP JCF&amp;quot;,&amp;quot;total&amp;quot;:8,&amp;quot;current&amp;quot;:[],&amp;quot;processed&amp;quot;:8,&amp;quot;remaining&amp;quot;:0,&amp;quot;success&amp;quot;:[1,2,3,4,5,6,7,8],&amp;quot;failure&amp;quot;:[]},&amp;quot;time&amp;quot;:{&amp;quot;start&amp;quot;:1546547784,&amp;quot;elapsed&amp;quot;:1,&amp;quot;end&amp;quot;:1546547785},&amp;quot;state&amp;quot;:2}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la liste des identifiants des travaux en cours&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la liste des identifiants des travaux disponibles pour consultation&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Stop le travail d&#039;indexation désignè par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Supprime les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=289</id>
		<title>Music sender api</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Music_sender_api&amp;diff=289"/>
		<updated>2019-01-03T20:35:47Z</updated>

		<summary type="html">&lt;p&gt;Tala : /* Indexer (WIP) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=User=&lt;br /&gt;
L&#039;objet user est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;pseudo&amp;quot;:&amp;quot;tala&amp;quot;,&amp;quot;email&amp;quot;:&amp;quot;tala@tala.com&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/&lt;br /&gt;
||&lt;br /&gt;
* pseudo : le pseudo de l&#039;utilisateur&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
* password : le mot de passe de l&#039;utilisateur&lt;br /&gt;
* image : l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Crée un nouvel utilisateur et renvoie son identifiant&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussi avec en réponse l&#039;identifiant (eg. {&amp;quot;id&amp;quot;:1} )&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/email/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* email : le mail de l&#039;utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;email du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/password/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant utilisateur&lt;br /&gt;
||&lt;br /&gt;
* password : le nouveau mot de passe utilisateur&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le mot de passe du compte&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
*404 : si l&#039;utilisateur n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/user/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;utilisateur&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Genre=&lt;br /&gt;
L&#039;objet genre est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Electro-Jazz&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets genre&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet genre&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*genre : le nom du genre&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom du genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface le genre&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Artist=&lt;br /&gt;
L&#039;objet artiste est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;84&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;Yolanda Be Cool &amp;amp; Dcup&amp;quot;,&amp;quot;id_image&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets artiste&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;artist&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet artiste&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’artiste&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/artist/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Album=&lt;br /&gt;
L&#039;objet album est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;album&amp;quot;:&amp;quot;Electro Swing Collection 1&amp;quot;,&amp;quot;coverId&amp;quot;:null}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant d&#039;un genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/like/$$EXPR$$&lt;br /&gt;
*$$EXPR$$ : une expression contenu dans un nom d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objets album&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album&lt;br /&gt;
||&lt;br /&gt;
*name : le nom de l&#039;album&lt;br /&gt;
*image : l&#039;identifiant d&#039;une image (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet album&lt;br /&gt;
||&lt;br /&gt;
*201 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/name/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*name: le nom de l’album&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie le nom de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/album/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*image: l&#039;identifiant de l&#039;image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image de l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/genre/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;album&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Music=&lt;br /&gt;
L&#039;objet musique est composé comme suit : {&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;title&amp;quot;:&amp;quot;All Night&amp;quot;,&amp;quot;artists&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;genres&amp;quot;:[&amp;quot;1&amp;quot;],&amp;quot;bitrate&amp;quot;:&amp;quot;128&amp;quot;,&amp;quot;hit&amp;quot;:&amp;quot;4&amp;quot;,&amp;quot;duration&amp;quot;:&amp;quot;163&amp;quot;,&amp;quot;id_image&amp;quot;:&amp;quot;1&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet musique au format Json &lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/content/$$ID$$&lt;br /&gt;
* $$ID$$ : un identifiant de musique&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu de la musique (fichier son)&amp;lt;br&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/album/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;album&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json appartenant à l&#039;album associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/music/artist/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;artiste&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau d&#039;objet musiques au format Json dont le créateur est l&#039;artiste associé à l&#039;identifiant&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe;&lt;br /&gt;
*400 : si une erreur survient;&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Image=&lt;br /&gt;
L&#039;objet image est composé comme suit : {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;/9j/4B4…T0+7RRW/2Q==&amp;quot;,&amp;quot;mime&amp;quot;:&amp;quot;image\jpeg&amp;quot;,&amp;quot;hash&amp;quot;:&amp;quot;0aebaad7…4f265bd&amp;quot;} }&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/images&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les objets image&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/info/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/content/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;objet existe&lt;br /&gt;
*404 : si l&#039;objet n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Créé un nouvel objet image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la création réussie&lt;br /&gt;
*400 : si la création échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id d&#039;image&lt;br /&gt;
||&lt;br /&gt;
*content : le contenu du fichier image&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
PUT&lt;br /&gt;
||&lt;br /&gt;
Modifie l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si la modification réussie&lt;br /&gt;
*400 : si la modification échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_red_cross.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/image/$$ID$$&lt;br /&gt;
*$$ID$$ : un id de genre&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Efface l&#039;image&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;effacement réussie&lt;br /&gt;
*400 : si l&#039;effacement échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Device=&lt;br /&gt;
L&#039;objet périphérique est composé comme suit : {&amp;quot;name&amp;quot;:&amp;quot;\/dev\/sda1&amp;quot;,&amp;quot;label&amp;quot;:&amp;quot;MUSIC&amp;quot;,&amp;quot;size&amp;quot;:&amp;quot;7.2 GiB&amp;quot;,&amp;quot;UUID&amp;quot;:&amp;quot;84B9-A853&amp;quot;,&amp;quot;fstype&amp;quot;:&amp;quot;vfat&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les périphériques&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/list/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un répertoire sur le périphérique&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers et dossiers:&lt;br /&gt;
&lt;br /&gt;
{&amp;quot;directories&amp;quot;:[&amp;quot;Pop&amp;quot;,&amp;quot;Rock&amp;quot;],&amp;quot;files&amp;quot;:[&amp;quot;Gala - Freed From Desire.mp3&amp;quot;,&amp;quot;13)Jacques Your Body (Make Me Sweat)(Jcf Pitch Edit).mp3&amp;quot;]}&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;UUID existe&lt;br /&gt;
*400 : si l&#039;UUID n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/content/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête &lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/tag/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques montés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/umounted&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des périphériques démontés&lt;br /&gt;
||&lt;br /&gt;
*200 : si aucune erreur&lt;br /&gt;
*400 : si une erreur survient&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le périphérique sur le système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Active le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/index/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier existe&lt;br /&gt;
*400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/mount/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le périphérique du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/enable/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Désactive le montage du périphérique au démarrage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Share=&lt;br /&gt;
L&#039;objet partage est composé comme suit : {&amp;quot;host&amp;quot;:&amp;quot;hades&amp;quot;,&amp;quot;share&amp;quot;:&amp;quot;downloads&amp;quot;,&amp;quot;login&amp;quot;:&amp;quot;nobody&amp;quot;}&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec tous les partages montés&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
||&lt;br /&gt;
* vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des partages disponibles sur l&#039;hôte&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/list/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
* extension : filtre à appliquer sur les fichiers (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste récursive de tous les fichiers disponibles sur le partage&lt;br /&gt;
&lt;br /&gt;
Attention, l&#039;appel peut être long, surtout lorsque les partages contiennent beaucoup de fichiers&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le partage existe&lt;br /&gt;
* 400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/device/explore/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un répertoire sur le partage&lt;br /&gt;
* extension : un filtre par extension de fichier (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau avec la liste des fichiers&lt;br /&gt;
||&lt;br /&gt;
*200 : si le partage existe&lt;br /&gt;
*400 : si le partage n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/content/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne le contenu du fichier avec le type mime en entête&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/tag/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne un tableau contenant les tags du ou des fichiers présent dans le répertoire&lt;br /&gt;
||&lt;br /&gt;
* 200 : si le fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* login : le login à utiliser (optionnel)&lt;br /&gt;
* password : le mot de passe associé (optionnel)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Monte le partage sur le système. Si aucun couple d&#039;authentification n&#039;est fourni, &#039;&#039;nobody&#039;&#039; sera utilisé&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/index/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
* path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Index le répertoire ou le fichier désigné par le paramètre path&lt;br /&gt;
||&lt;br /&gt;
*200 : si le montage réussie&lt;br /&gt;
*400 : si le montage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Démonte le partage du système&lt;br /&gt;
||&lt;br /&gt;
*200 : si le démontage réussie&lt;br /&gt;
*400 : si le démontage échoue&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Youtube =&lt;br /&gt;
Permet de récupérer des informations sur les vidéo Youtube&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/info/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère des informations sur la vidéo Youtube. Voici un exemple:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
&amp;quot;url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;cover&amp;quot;:&amp;quot;https:\/\/i.ytimg.com\/vi\/eVGrSCrRiy8\/maxresdefault.jpg&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;author&amp;quot;:&amp;quot;ElectroDanceMixes&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;title&amp;quot;:&amp;quot;FESTIVAL MIX - Best EDM &amp;amp; Electro House Dance Party Mix 2018&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;id&amp;quot;:&amp;quot;eVGrSCrRiy8&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;videos&amp;quot;:[&amp;quot;...&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/cover/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la &#039;&#039;pochette&#039;&#039; de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/youtube/listen/$$ID$$&lt;br /&gt;
* $$ID$$ : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=eVGrSCrRiy8 ou eVGrSCrRiy8)&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère le contenu de la vidéo&lt;br /&gt;
||&lt;br /&gt;
*200 : si la vidéo existe&lt;br /&gt;
*200 : si la vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
=Player=&lt;br /&gt;
Joue la musique sur la carte son du Pi (intégration VLC)&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/pause&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Met en pause la music&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/stop&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Stop la lecture&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/volume/$$PERCENT$$&lt;br /&gt;
*$$PERCENT$$ : le volume en poucentage&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Règle le volume du lecteur&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/device/$$UUID$$&lt;br /&gt;
*$$UUID$$ : un UUID de périphérique&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le périphérique&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le périphérique &#039;&#039;UUID&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier et le périphérique existent&lt;br /&gt;
*400 : si le fichier ou le périphérique n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/share/$$HOST$$/$$SHARE$$&lt;br /&gt;
*$$HOST$$ : un hôte supportant le protocole SMB/CIFS&lt;br /&gt;
*$$SHARE$$ : le nom du partage sur cet hôte&lt;br /&gt;
||&lt;br /&gt;
*path : un chemin sur le partage&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier désigné par &#039;&#039;path&#039;&#039; sur le partage &#039;&#039;SHARE&#039;&#039; sur l&#039;hôte &#039;&#039;HOST&#039;&#039;&lt;br /&gt;
||&lt;br /&gt;
*200 : si le fichier, le partage et l&#039;hôte existent&lt;br /&gt;
*400 : si le fichier, le partage ou l&#039;hôte n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/youtube&lt;br /&gt;
||&lt;br /&gt;
* path : un lien ou ID de vidéo Youtube (https://www.youtube.com/watch?v=mEYyVY9ffDM ou mEYyVY9ffDM)&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le son de la vidéo, quand c&#039;est possible (certaines vidéos ne fonctionnent pas)&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la vidéo existe&lt;br /&gt;
* 400 : si le vidéo n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/player/url&lt;br /&gt;
||&lt;br /&gt;
* path : un lien vers un fichier musical&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
POST&lt;br /&gt;
||&lt;br /&gt;
Joue le fichier&lt;br /&gt;
||&lt;br /&gt;
* 200 : si la fichier existe&lt;br /&gt;
* 400 : si le fichier n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Indexer (WIP)=&lt;br /&gt;
Permet d&#039;avoir des informations sur les travaux d&#039;indexation en cours&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! URL !! Corps !! Verbe  !! Action !! Code retour !! Implémentée&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Retourne la liste des identifiants des travaux en cours&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère la liste des identifiants des travaux disponibles pour consultation&lt;br /&gt;
||&lt;br /&gt;
*200&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
GET&lt;br /&gt;
||&lt;br /&gt;
Récupère les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/run/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Stop le travail d&#039;indexation désignè par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;br /&gt;
|-&lt;br /&gt;
||&lt;br /&gt;
/api/index/info/$$ID$$&lt;br /&gt;
*$$ID$$ : l&#039;identifiant du travail&lt;br /&gt;
||&lt;br /&gt;
*vide&lt;br /&gt;
|align=&#039;center&#039;|&lt;br /&gt;
DELETE&lt;br /&gt;
||&lt;br /&gt;
Supprime les informations liées au travail désigné par $$ID$$&lt;br /&gt;
||&lt;br /&gt;
*200 : si l&#039;identifiant existe&lt;br /&gt;
*400 : si l&#039;identifiant n&#039;existe pas&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:implemented_green_tick.png|center|40px]]&lt;/div&gt;</summary>
		<author><name>Tala</name></author>
	</entry>
</feed>