まこと の ブログ

MaKoTo no burogu — Journal de bord…

Aller au contenu | Aller au menu | Aller à la recherche

WebRadioRéveilWifi -5-

Suite de l'étude précédente :

L'Horloge/Réveil étant fin prête, il est temps de réviser la configuration de la WebRadio.
J'ai tout repris de zero… C'est qu'il s'est passé pas mal de temps depuis les premières expérimentations, et pas mal de version de Raspbian sont passées sous les ponts !

Pour rappel, j'ai décidé d'articuler la WebRadio autour d'un Raspberry Pi 1 (où Rpi zeroW car le 1 n'est plus en vente), de quelques boutons d'interactions, d'une cellule infrarouge et d'un écran LCD (facultatif) bon marché type radar de recul.

  • On va ici étudier la partie software, la partie hardware concernant le câblage des GPIO, relais et interfaçage horloge, pilotée par le programme mpc.py venant au prochain billet.

1 - Installer et configurer Raspbian Lite :

  • Déployer l'image sur une carte SD depuis un système GNU/Linux, avec la commande DD

(attention, of=/dev/sdx à adapter pour la cible de votre carte SD, en cas d'erreur risque d'effacement d'un disque dur non désiré)

dd bs=4M if=2017-11-29-raspbian-stretch-lite.img of=/dev/sdx; sync
  • Placer la carte SD dans le Raspberry, et le mettre sous tension.

Exécuter raspi-config, et configurer tous les trucs comme on veut, notamment les variables locales (time zone, clavier, etc), et surtout le login automatique de l'utilisateur.

sudo raspi-config

raspi-config01.png
raspi-config02.png
raspi-config03.png

Après le reboot, pour rappel :

Login : pi
Pass : raspberry

  • Effectuer les mises à jour :
sudo apt update
sudo apt upgrade
  • Mettre les fichiers temporaires en ram pour économiser sur la durée de vie la la carte SD.
sudo nano /etc/fstab
tmpfs      /tmp		tmpfs	defaults,size=256M	0    0
tmpfs      /var/tmp	tmpfs	defaults,size=256M	0    0
tmpfs      /var/log	tmpfs	defaults,size=256M	0    0
  • Pour configurer le wifi, éditer le fichier /etc/wpa_supplicant/wpa_supplicant.conf et modifier comme suit la section wlan0 : (ou par raspi-config)
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=FR

network={
        ssid="le nom du réseau wi-fi"
        psk="le mot de passe du réseau wi-fi"
}
  • Relancer ensuite le réseau avec la commande :
sudo service networking restart
  • Pour régler la résolution d'écran afin de l'adapter au petit écran type radar de recul :
sudo nano /boot/config.txt
framebuffer_width=320 
framebuffer_height=240
  • Configurer la sortie sonore sur le jack plutôt que le HDMI (par défaut) :
amixer cset numid=3 1
  • Régler le niveau sonore, puis sauvegarder les modifications :
alsamixer
sudo alsactl store 0



2 - Les logiciels pour la WebRadio :

  • Installer le lecteur de musique, le pilotage GPIO et la synthèse vocale :
sudo apt install mpd mpc wiringpi espeak
  • Configuration du lecteur mpc/mpd, éditer :
sudo nano /etc/mpd.conf

Indiquer les chemins où seront stockés les playlists et les fichiers mp3 :

music_directory         "/home/pi/music"
playlist_directory              "/home/pi/playlists"

Puis relancer le service mpd

sudo service mpd restart
  • Écriture d'une playlist de station de radio :

Créer un fichier portant l’extension .m3u avec simplement la liste des URL des stations radio

nano /home/pi/playlists/radio.m3u
# StahlRadio - Metal - http://stahlradio.de/
http://streamplus52.leonex.de:22810/;
# Radio Metal - http://www.radiometal.com/
http://stream.radiometal.com:8010
# EBM Radio - Industrial, Futurepop, Synthipop, Dark Wave, Gothic, ... et Depeche Mode
http://ebm-radio.org:9000/ebm.ogg
# japanfm
http://radio.japanfm.fr/japan
# TSF Jazz
http://tsfjazz.ice.infomaniak.ch:80/tsfjazz-high
# Radio Neo - Français
http://stream.radioneo.org:8000/;chat.mp3
# Radio Equinoxe - Electo - http://radioequinoxe.com/radio/liens-decoute/
http://www.radioking.com/play/radio-equinoxe/76118
  • Écriture d'une playlist de fichier mp3 :

Créer un fichier portant l’extension .m3u avec simplement la liste des fichiers mp3 (stockés dans le dossier /home/pi/music)

nano /home/pi/playlists/FarCryBloodDragon.m3u
01. Rex Colt.mp3
02. Blood Dragon Theme.mp3
03. HELO-73.mp3
04. Warzone.mp3
05. Moment of Calm.mp3
06. Dr Elizabeth Darling.mp3
07. Power Core.mp3
08. Protektor.mp3
09. Sloan.mp3
10. Sloan's Assault.mp3
11. Blood Scope.mp3
12. Combat I.mp3
13. Combat II.mp3
14. Combat III.mp3
15. Katana.mp3
16. Omega Force.mp3
17. Nest.mp3
18. Rex's Escape.mp3
19. Love Theme.mp3
20. Sleeping Dragon.mp3
  • Et attention, pour que les fichiers mp3 soient pris en compte, il est nécessaire de scanner le dossier « music », sinon les mp3 ne fonctionneront pas !!
mpc update
  • La config est prête, voici le programme python mpc.py qui exploite tout ça pour fournir le service :
#!/usr/bin/env python2.7
# coding: utf-8
# on importe les modules nécessaires

import time
import os, sys
import RPi.GPIO as GPIO
import subprocess
import socket
# on met RPi.GPIO en mode notation BCM (numéro des pins)
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
# on initialise les GPIO en mode "écoute" (GPIO1 sur la nappe)
GPIO.setup(17, GPIO.OUT, initial = GPIO.LOW)        # GPIO0 - pin11 - Relais Ampli
#GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # GPIO1 - pin12 - LIRC
GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_UP)   # GPIO2 - pin13 - Station suivante
GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_UP)   # GPIO3 - pin15 - PowerOFF
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)   # GPIO4 - pin16 - Station précédente
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP)   # GPIO5 - pin18 - LCD ON/OFF
GPIO.setup(25, GPIO.IN, pull_up_down=GPIO.PUD_UP)   # GPIO6 - pin22 - Play/pause/stop   ne fonctionne plus à cause de la tempo 1H
GPIO.setup(4, GPIO.OUT, initial = GPIO.LOW)     # GPIO7 - pin7  - Relais LCD

long_press = 1
very_long_press = 3
site = 'www.google.fr'

# Nettoyage lecteur média
os.system('mpc clear')

def is_connected(REMOTE_SERVER):
        try:
                # see if we can resolve the host name -- tells us if there is a DNS listening
                host = socket.gethostbyname(REMOTE_SERVER)
                # connect to the host -- tells us if the host is actually reachable
                s = socket.create_connection((host, 80), 2)
                return True
        except:
                pass
                return False

# Chargement de la playlist
if is_connected(site):
#     print "Site disponible"
     os.system('mpc load radio')
else:
#     print "Site indisponible"
     os.system('mpc load foo')

# au bout de QUelques minutes, stopper la lecture
heure=0
fin=9999999999

# fonction qui sera appelée quand on appuiera sur le bouton 25
def bouton25(a):
    global fin
    button_press_timer = 0
    GPIO.remove_event_detect(25) # empéche le bouton d'etre détecté x fois de plus
    while True:
        if(GPIO.input(a) == GPIO.LOW ): # bouton appuyé
            button_press_timer += 0.2 # incrémente tant que le bouton est maintenu

        else: # bouton relaché
            if (button_press_timer > very_long_press):
                # Arret du lecteur media
                os.system("espeak 'Arrêt de la wéb-radio !' -v fr+f5 -s150 -p 75 -a 300") # Voix synthétique
                subprocess.call(["mpc stop"], shell=True)
                GPIO.output(17, GPIO.LOW) # relais ampli OFF
            elif (button_press_timer > long_press):
                # Pause du lecteur media
                os.system("espeak 'playlist Far Cry Blood Dragon' -v en+f5 -s150 -p 75 -a 300")
                os.system('mpc clear')
                os.system('mpc load FarCryBloodDragon')
                os.system('mpc play')
            elif (button_press_timer > 0):
                # Lecture du lecteur media
                GPIO.output(17, GPIO.HIGH) # relais ampli ON
                os.system('mpc clear')
                   # Chargement de la playlist
                if is_connected(site):
                   # print "Site disponible"
                    os.system('mpc load radio')
                    os.system("espeak 'lecture' -v fr+f5 -s150 -p 75 -a 300")
                    os.system('mpc play 2')
                    fin=time.time()+3600	# attend 1h - 3600
                    fin=round(fin)
                else:
                    #print "Site indisponible"
                    os.system('mpc load foo')
                    os.system("espeak 'lecture' -v fr+f5 -s150 -p 75 -a 300")
                    os.system('mpc play')
                    fin=time.time()+3600	# attend 1h - 3600
                    fin=round(fin)

            button_press_timer = 0
        time.sleep(0.2)

# fonction qui sera appelée quand on appuiera sur le bouton 27
def bouton27(channel):
    # entrée suivante du lecteur media
    os.system("espeak 'station suivante' -v fr+f5 -s150 -p 75 -a 300")
    os.system("mpc next")

# fonction qui sera appelée quand on appuiera sur le bouton 23
def bouton23(channel):
    # entrée précédente du lecteur media
    os.system("espeak 'station précédente' -v fr+f5 -s150 -p 75 -a 300")
    os.system("mpc prev")

# fonction qui sera appelée quand on appuiera sur le bouton 22
def bouton22(channel):
    os.system("sudo poweroff")

# fonction qui sera appelée quand on appuiera sur le bouton 24
def bouton24(a):
    global fin
    button_press_timer = 0
    GPIO.remove_event_detect(24) # empéche le bouton d'etre détecté x fois de plus
    while True:
        if(GPIO.input(a) == GPIO.LOW ): # bouton appuyé
            button_press_timer += 0.2 # incrémente tant que le bouton est maintenu
        else: # bouton relaché
            if (button_press_timer > long_press):
                GPIO.output(4, GPIO.LOW) # relais LCD OFF
                os.system("espeak 'Éteindre lécran LCD' -v fr+f5 -s150 -p 75 -a 300")
                GPIO.output(17, GPIO.LOW) # relais ampli OFF
            elif (button_press_timer > 0):
                os.system('mpc stop')   # stop la radio
                GPIO.output(4, GPIO.HIGH) # relais LCD ON
                GPIO.output(17, GPIO.HIGH) # relais ampli ON
                os.system("espeak 'Allumage de lécran LCD' -v fr+f5 -s150 -p 75 -a 300")
                fin=time.time()+3600       # attend 1h - 3600
                fin=round(fin)

            button_press_timer = 0
        time.sleep(0.2)


# on met le bouton en écoute
GPIO.add_event_detect(27, GPIO.FALLING, callback=bouton27, bouncetime=200)
GPIO.add_event_detect(22, GPIO.FALLING, callback=bouton22, bouncetime=200)
GPIO.add_event_detect(23, GPIO.FALLING, callback=bouton23, bouncetime=100)
GPIO.add_event_detect(24, GPIO.FALLING, callback=bouton24, bouncetime=200)
GPIO.add_event_detect(25, GPIO.FALLING, callback=bouton25, bouncetime=200)

# on lance une boucle infinie, pour garder le script actif
while True:

    if (heure>=fin):
        os.system("mpc stop")
        GPIO.output(17, GPIO.LOW) # relais ampli OFF
        GPIO.output(4, GPIO.LOW) # relais LCD OFF
        fin=9999999999
    else:
        heure=time.time()
        heure=round(heure)

    # une petite pause entre chaque boucle, afin de réduire la charge sur le CPU
    time.sleep(2)

# on réinitialise les ports GPIO en sortie de script
GPIO.cleanup()
  • Le fonctionnement est simple :

- Le bouton 25 pour allumer et éteindre la radio, ou lancer une playlist mp3, par des appuies plus ou moins long (l'ampli audio est géré automatiquement).
- Le bouton 27 pour passer à la station radio suivante.
- Le bouton 23 pour passer à la station radio précédente.
- Et enfin, le bouton 24 pour allumer et éteindre l'écran LCD (et l'ampli audio).
- Lorsque la radio est allumée, soit par l'alarme de l'horloge, ou par le bouton 25, elle fonctionne durant 1h avant de s'éteindre. Idem pour l'écran LCD.
- Si internet n'est pas disponible, la radio bascule sur une playlist mp3 de secours.

  • Pour démarrer automatiquement le programme python dés le démarrage du Raspberry, créer un service pistart.service :
sudo nano /etc/systemd/system/RadioReveil.service
[Unit]
Description=Démarre le script de la webradio
[Service]
ExecStart=/usr/bin/python /home/pi/mpc.py
[Install]
WantedBy=multi-user.target
  • Installer le service :
sudo systemctl --system daemon-reload
sudo systemctl enable RadioReveil.service
  • Pour manipuler le service :
sudo systemctl status RadioReveil.service
sudo systemctl start RadioReveil.service



3 - Installer et configurer Kodi :

Le médiacenter est facultatif, il ouvre cependant sur une galaxie de possibilités…

sudo apt-get install kodi
  • Pour lancer Kodi automatiquement après l'autologin, éditer le fichier .profile :
nano ~/.profile

Et ajouter les lignes suivantes à la fin :

tty=`tty`
# Start Kodi only if login in tty1
if [ $tty = '/dev/tty1' ]; then
        kodi
fi


  • On prendra soins de configurer Kodi dans la résolution vidéo minimale (640x480), mais au vu de la faible résolution de l'écran LCD, il s'avère nécessaire d'afficher de grande police de caractère.

Pour cela éditer :

nano .kodi/addons/skin.confluence/720p/Font.xml

À la sous section <Name> font13, augmenter la valeur <Size> à 50 (initialement réglée à 20).

<name>font13</name>
<filename>Roboto-Regular.ttf</filename>
<size>50</size>

À la sous section <Name> fontContextMenu', augmenter la valeur <Size>'' à 50 (initialement réglée à 18).

<name>fontContextMenu</name>
<filename>Roboto-Regular.ttf</filename>
<size>50</size>

À la sous section <Name> font12_title, augmenter la valeur <Size> à 50 (initialement réglée à 17).

<name>font12_title</name>
<filename>Roboto-Bold.ttf</filename>
<size>50</size>



4 - La télécommande infra-rouge :

Utile au médiacenter, cette partie est donc également facultative !

  • Installer le soft de gestion de l'infrarouge :
sudo apt-get install lirc
  • Éditer hardware.conf pour régler les paramètres de LIRC :
sudo nano /etc/lirc/hardware.conf
########################################################
# /etc/lirc/hardware.conf
#
# Arguments which will be used when launching lircd
LIRCD_ARGS="--uinput"
# Don't start lircmd even if there seems to be a good config file
# START_LIRCMD=false
# Don't start irexec, even if a good config file seems to exist.
# START_IREXEC=false
#Try to load appropriate kernel modules
LOAD_MODULES=true
# Run "lircd --driver=help" for a list of supported drivers.
DRIVER="default"
# usually /dev/lirc0 is the correct setting for systems using udev
DEVICE="/dev/lirc0"
MODULES="lirc_rpi"
# Default configuration files for your hardware if any
LIRCD_CONF=""
LIRCMD_CONF=""
########################################################
  • Activer le module sur le RpiPi en éditant config.txt
sudo nano /boot/config.txt

Dé-commenter la ligne (sans autre argument, c'est le GPIO18 qui sera écouté par le module, sinon pour par exemple le GPIO23, on indiquera dtoverlay=lirc-rpi,gpio_in_pin=23) et redémarrer le RpiPi.

dtoverlay=lirc-rpi
  • Pour tester si les commandes infrarouge sont bien reçues :
sudo killall lircd
sudo mode2 -d /dev/lirc0

Si jamais le programme ça répond ceci :

Using driver devinput on device /dev/lirc0
Trying device: /dev/lirc0
Using device: /dev/lirc0
Partial read 8 bytes on /dev/lirc0

Alors on est en présence d'une Raspbian stretch (9), lircd buggée, pour corriger le problème, lancer le script :

sudo /usr/share/lirc/lirc-old2new
  • À chaque appuie sur une touche de la télécommande, devrait s'afficher ce genre de truc :
space 1223
pulse 281
space 1193
pulse 350
space 1199
pulse 264
space 1901
  • Bien, maintenant on va identifier la télécommande et associer chacun de ses boutons à une touche du clavier. Le programme va demander d'appuyer anarchiquement sur toutes les touches, puis de nommer les touches une à une. La syntaxe à respecter pour les noms est disponible en exécutant :
irrecord --list-namespace

Il est temps de procéder :

sudo irrecord -d /dev/lirc0 telecommande

Suivre la procédure indiquée par le programme…
J'ai choisis ces touches du clavier, qui correspondent aux raccourcis clavier les plus utile de Kodi, pour la simple raison que ça fonctionnera directement ! Pas la peine de configurer quoi que ce soit dans Kodi !

KEY_Up
KEY_Down
KEY_Right
KEY_Left
KEY_Enter
KEY_C (click droit)
KEY_PageUp
KEY_Esc (retour menu principal)
KEY_Back (retour menu précédent)
KEY_Rewind
KEY_Stop
KEY_PlayPause
KEY_FastForward

  • Voici le contenu de telecommande.lircd.conf' qui a été créé, le déplacer dans /etc/lirc/lircd.conf.d/ pour qu'il soit pris en compte par lirc''
begin remote

  name  remoteLongue
  bits           16
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  header       9053  4449
  one           609  1642
  zero          609   514
  ptrail        608
  repeat       9051  2202
  pre_data_bits   16
  pre_data       0x807F
  gap          108017
  toggle_bit_mask 0x0

      begin codes
          KEY_Up                   0x10EF
          KEY_Down                 0x08F7
          KEY_Right                0x807F
          KEY_Left                 0x30CF
          KEY_C                    0xA05F
          KEY_PageUp               0xB04F
          KEY_Back                 0x20DF
          KEY_Rewind               0x708F
          KEY_Stop                 0x8877
          KEY_PlayPause            0x50AF
          KEY_FastForward          0x48B7
          KEY_Enter                0x00FF
      end codes

end remote
  • Reste à redémarrer le service LIRC
sudo service lircd restart
  • Un moyen simple de savoir si ça marche, c'est de simplement appuyer sur les touches de la télécommande, ça devrait agir dans la console GNU/Linux ![1]

Par exemple la touche correspondant à KEY_C affichera le caractère C, normal quoi, puisque LIRC permet ainsi d'assigner l'entièreté des touches du clavier, et plus encore.

  • Au lancement de Kodi la télécommande devrait fonctionner

Si ce n'est pas le cas, ressortir et vérifier que le processus lircd tourne bien.

ps -A | grep lirc



À suivre…

Note

[1] La console tty de votre choix connecté en HDMI, ça ne fonctionne pas depuis ssh !

Ajouter un commentaire

Les commentaires peuvent être formatés en utilisant une syntaxe wiki simplifiée.

Fil des commentaires de ce billet