Affichage dynamique en Python

Le projet

J’ai travaillé sur un projet d’affichage dynamique, un diaporama sur un écran TV. Recherchant une solution peu onéreuse s’appuyant sur des logiciels libres, j’ai trouvé un script Shell pouvant être exécuté sur un Raspberry Pi sur le site suivant :

http://wiki.dane.ac-versailles.fr/

Un partage sur un réseau local héberge un diaporama réalisé avec LibreOffice Impress (.odp). Lorsque ce fichier est modifié, il est automatiquement téléchargé par le Raspberry Pi qui se trouve sur le même réseau et est affiché. Cela fonctionne très bien et actuellement dans un collège, j’ai deux Raspberry Pi pour deux écrans TV qui affichent le même diaporama. Le script Shell est lancé automatiquement aux démarrages des Raspberry Pi.

Un petit schéma de mon installation

Programme en Python

J’ai décidé de réaliser une version en Python de ce script Shell. J’ai créé deux petits programmes, le premier avec une interface graphique permettant de configurer plus facilement mon logiciel, le second permettant l’affichage du diaporama. Les difficultés étaient d’accéder au partage réseau depuis Python et d’exécuter des commandes Shell Bash.


Programme de configuration

Ce programme permet d’enregistrer dans un fichier les paramètres de configuration de mon logiciel depuis une interface graphique. Si vous êtes en groupe de travail lors des tests, enregistrez son nom en guise de nom de domaine, cela doit fonctionner.

Le programme Diapo-ini.py

!/usr/bin/env python3.7
 -- coding: utf-8 --
 from tkinter import *
 import pickle
 import os.path
 def Lancer_Diaporama():
     exec(open("./Diapo-py.py").read())
 def Enregistrer():
     serveursmb = Serveur_Entry.get()
     partagesmb = Partage_Entry.get()
     utilisateur = Utilisateur_Entry.get()
     mot_de_passe = Mot_de_passe_Entry.get()
     domaine = Domaine_Entry.get()
     fichier_diaporama = Fichier_du_diaporama_Entry.get()
 #Enregistrer mes variables sous forme d'une liste dans un fichier variables = [serveursmb, partagesmb, utilisateur, mot_de_passe, domaine, fichier_diaporama] fichierSauvegarde = open("diaporamaini","wb") pickle.dump(variables, fichierSauvegarde) fichierSauvegarde.close()
 Lecture du fichier ini
 fichierini = "diaporamaini"
 Ouverture du fichier s'il existe et récupération de la liste
 if os.path.isfile(fichierini):
     fichierSauvegarde = open(fichierini,"rb")
     variables = pickle.load(fichierSauvegarde)
     fichierSauvegarde.close()
 # Affichage d'informations print("Initialisation des variables") # Récupération des données dans les variables serveursmb = variables[0] partagesmb = variables[1] utilisateur = variables[2] mot_de_passe = variables[3] domaine = variables[4] fichier_diaporama = variables[5]
 else:
     # Le fichier n'existe pas
     print("Fichier " + fichierini + " non trouvé")
     serveursmb = partagesmb = utilisateur = mot_de_passe = domaine = fichier_diaporama = "vide"
 Fenetre = Tk() #création de la fenêtre, avec un nom de votre choix Fenetre
 Fenetre.title('Paramètres Diaporama') #Titre de la fenêtre
 Fenetre.geometry("420x170") # On définit la taille de la fenêtre
 Fenetre.resizable(width=False,height=False) #Empêcher de redimentionner la fenêtre
 Création d'un interface graphique avec grid
 Serveur_Label= Label(Fenetre, text = 'Votre serveur - Nom ou IP :') #Un label pour afficher du texte
 Serveur_Label.grid(row=0)
 Serveur_Entry= Entry(Fenetre) #On définit l'objet Entry (zone de saisie) qui porte le nom Serveur_Entry
 Serveur_Entry.insert(0, serveursmb)
 Serveur_Entry.grid(row=0,column=1,ipadx=30) # ipadx=30 pour créer 10 pixels de plus horizontalement
 Partage_Label= Label(Fenetre, text = 'Votre partage réseau :')
 Partage_Label.grid(row=1,column=0)
 Partage_Entry= Entry(Fenetre)
 Partage_Entry.insert(0, partagesmb)
 Partage_Entry.grid(row=1,column=1,ipadx=30)
 Utilisateur_Label= Label(Fenetre, text = 'Votre utilisateur :')
 Utilisateur_Label.grid(row=2,column=0)
 Utilisateur_Entry= Entry(Fenetre)
 Utilisateur_Entry.insert(0, utilisateur)
 Utilisateur_Entry.grid(row=2,column=1,ipadx=30)
 Mot_de_passe_Label= Label(Fenetre, text = 'Votre mot de passe :')
 Mot_de_passe_Label.grid(row=3,column=0)
 Mot_de_passe_Entry= Entry(Fenetre) # Saisie du mot de passe
 Mot_de_passe_Entry.insert(0, mot_de_passe)
 Mot_de_passe_Entry.grid(row=3,column=1,ipadx=30)
 Domaine_Label= Label(Fenetre, text = 'Votre nom de domaine:')
 Domaine_Label.grid(row=4,column=0)
 Domaine_Entry= Entry(Fenetre)
 Domaine_Entry.insert(0, domaine)
 Domaine_Entry.grid(row=4,column=1,ipadx=30)
 Fichier_du_diaporama_Label= Label(Fenetre, text = 'Votre fichier de diaporama :')
 Fichier_du_diaporama_Label.grid(row=5,column=0)
 Fichier_du_diaporama_Entry= Entry(Fenetre)
 Fichier_du_diaporama_Entry.insert(0, fichier_diaporama)
 Fichier_du_diaporama_Entry.grid(row=5,column=1,ipadx=30)
 Mon_bouton_Lancer_Diaporama = Button(Fenetre, text = 'Lancer le Diaporama',command = Lancer_Diaporama)
 Mon_bouton_Lancer_Diaporama.grid(row=6,column=0,ipadx=0)
 Mon_bouton_Enregistrer = Button(Fenetre, text = ' Enregistrer le fichier', command = Enregistrer)
 Mon_bouton_Enregistrer.grid(row=6,column=1,ipadx=0)
 Fenetre.mainloop() # lance la boucle principale
L’interface graphique pour la saisie des paramètres du diaporama

Programme d’affichage du diaporama

Ce programme lit le fichier de configuration pour attribuer aux variables les valeurs qui ont été enregistrées puis il affiche le diaporama. Lorsque le diaporama est modifié sur le partage réseau, il est automatiquement téléchargé et affiché.

Le programme Diapo-py.py

!/usr/bin/env python3.7
 -- coding: utf-8 --
 import pickle
 import os.path
 import smbclient
 import subprocess
 import time
 Lecture du fichier ini
 fichierini = "diaporamaini"
 Ouverture du fichier s'il existe et récupération de la liste
 if os.path.isfile(fichierini):
     fichierSauvegarde = open(fichierini,"rb")
     variables = pickle.load(fichierSauvegarde)
     fichierSauvegarde.close()
 # Affichage d'informations print("Initialisation des variables") # Récupération des données dans les variables serveursmb = variables[0] partagesmb = variables[1] utilisateur = variables[2] mot_de_passe = variables[3] domaine = variables[4] fichier_diaporama = variables[5]
 else:
     # Le fichier n'existe pas
     print("Fichier " + fichierini + " non trouvé")
 initialisation des variables
 Version_Old = "vide"
 local_path = "./" + fichier_diaporama
 smb = smbclient.SambaClient(server=serveursmb, share=partagesmb, username=utilisateur, password=mot_de_passe, domain=domaine)
 Boucle = True
 while Boucle == True:
     try:
         # Afficher des informations sur le fichier
         Version_New = smb.info(fichier_diaporama)
     except:
         Version_New = Version_Old
     if Version_New != Version_Old:
         try:
             ### On arrête l'application LibreOffice ###
             subprocess.Popen(['/bin/sh', '-c', "pkill office"])
             time.sleep(2)
             ### On supprime l'ancien fichier diaporama s'il existe ###
             if os.path.isfile(local_path):
                 os.remove(local_path)
             ### Téléchargement du nouveau fichier ###
             smb.download(fichier_diaporama, local_path)
             time.sleep(2)
             ### Affichage du diaporama ###
             Affichage = subprocess.Popen(["libreoffice", "--norestore", "--show", fichier_diaporama], shell=False)
             Version_Old = Version_New
         except:
             print("Erreur lors du téléchargement et de l'affichage du diaporama")
     else:
         time.sleep(20) # Pas de mise à jour - On attend 20 secondes avant de revérifier

Prérequis pour l’installation du programme en Python sur le Raspberry Pi

Version de Python installée

python3 --version
 Python 3.7.3

Pour l’interface graphique avec Tkinter

Le paquet python3-tk doit être présent sinon on l’installe :

sudo apt-get install python3-tk

Accès au partage Samba

Vous devez disposer d’un partage réseau Windows ou sous Linux (Samba) avec les login/mot de passe pour y avoir accès.

Pour pouvoir accéder au partage réseau depuis le Raspberry Pi vous devez installer le paquet smbclient (client samba) sous Linux :

sudo apt-get install smbclient

En cas de problème, il peut être utile de vérifier la connexion au partage depuis l’explorateur de fichiers du Raspberry Pi :

smb://ip_du_serveur/nom_du_partage

Installer la bibliothèque pysmbclient (client samba) pour l’accès au partage réseau depuis Python :

pip3 install pysmbclient

Plus d’informations :

https://pypi.org/project/PySmbClient/

Les droits sur les fichiers

Les deux programmes doivent être exécutables et je réduis les droits au seul utilisateur pi :

chmod 700 nom_du_fichier

Pour le fichier diaporamaini, droits en lecture et en écriture au seul utilisateur :

chmod 600 diaporamaini

Lancer et arrêter les programmes

Pour lancer les programmes depuis un terminal :

./nom_du_fichier

Pour arrêter la diffusion du diaporama depuis le Raspberry Pi :

[Alt] + [F4] Pour fermer LibreOffice Impress.

[Ctrl] + [C] Pour stopper l’exécution du programme dans le terminal.

Par la suite, on pourra automatiser le lancement du programme qui affiche le diaporama au démarrage du Raspberry Pi.


Et maintenant…

Je ne suis pas programmeur, j’ai une formation de technicien d’assistance informatique et une autre de technicien réseau. Vous avez peut-être des idées pour améliorer ce programme et ajouter de nouvelles fonctionnalités. Si vous êtes intéressé, n’hésitez pas. Vous pouvez laisser des commentaires ou me contacter pour faire évoluer le code.

Programmes mis à jour le 21/12/2020

Dominique Renaudeau

Lecture d’une vidéo en boucle sur un Raspberry Pi

Raspberry Pi sous Raspbian GNU/Linux 9.13 (stretch).

On m’a demandé la lecture d’une vidéo en boucle sur un écran TV depuis un Raspberry Pi 3. Habituellement, j’utilise ce matériel pour un affichage dynamique (Diaporama). Je pensais utiliser le logiciel VLC, mais il n’affichait pas correctement la vidéo malgré plusieurs tentatives de réencodages avec le logiciel Handbrake. À la recherche d’une solution, j’ai testé le logiciel Omxplayer et cela a fonctionné.

Pour lancer l’affichage de la vidéo en boucle (depuis le dossier où se trouve la vidéo, dans un terminal) :

omxplayer --loop fichier_vidéo

Pour stopper l’affichage de la vidéo [Alt] + [F4] ou [Q].

Le logiciel Omxplayer était déjà installé sur le Raspberry Pi, on peut vérifier cela avec la commande :

dpkg -l omxplayer
 Souhait=inconnU/Installé/suppRimé/Purgé/H=à garder
 | État=Non/Installé/fichier-Config/dépaqUeté/échec-conFig/H=semi-installé/W=atte
 |/ Err?=(aucune)/besoin Réinstallation (État,Err: majuscule=mauvais)
 ||/ Nom            Version               Architecture Description
 +++-==============-=====================-============-==========================
 ii  omxplayer      20190723+gitf543a0d-1 armhf        Command line media player
 lines 1-6/6 (END)

Tapez [Q] pour reprendre la main.

Si comme pour moi votre fichier vidéo se trouve sur une clé USB vous retrouverez celle-ci dans le dossier /media/pi/.

Linux – commande introuvable

Sous Linux, si vous avez le message commande introuvable alors que vous pensez qu’elle est bien installée.

Exemple sous Debian 10 avec la commande pwck :

pwck -r
 bash: pwck : commande introuvable

On peut effectuer une recherche de la commande, ici pwck, avec whereis :

whereis pwck
 pwck: /usr/sbin/pwck /usr/share/man/man8/pwck.8.gz

On voit ici que la commande pwck se trouve sous /usr/sbin, à noter que l’on voit également où se trouvent les pages de manuel.

Si le système ne trouve pas la commande pwck, c’est que son chemin d’accès /usr/bin est absent de la variable d’environnement PATH.

Si l’on veut consulter le contenu de la variable PATH (en respectant la casse) :

echo $PATH
 /home/dominique/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Je vois que /usr/sbin ne figure pas dans la variable.

Pour la durée de la session

Pour ajouter /usr/sbin à la variable PATH :

export PATH=$PATH:/usr/sbin

Si je contrôle à nouveau le contenu de la variable PATH, /usr/sbin doit s’y trouver.

Ma commande pwck -r est maintenant fonctionnelle à condition d’être administrateur, root, sous Debian ou avec sudo sous Ubuntu (dans son cas).

Pour modifier PATH de façon permanente

Voir l’article :

Recherche des fichiers sous Linux et la variable PATH

Recherche des fichiers sous Linux et la variable PATH

locate et updatedb

updatedb

En administrateur.

updatedb

ou

sudo updatedb

Pour mettre à jour la base d’indexation utilisée par la commande locate.

locate

locate sources.list
 /etc/apt/sources.list
 /etc/apt/sources.list.d
 /etc/apt/sources.list.d/official-package-repositories.list
 /usr/share/doc/apt/examples/sources.list
 /usr/share/man/de/man5/sources.list.5.gz
 /usr/share/man/fr/man5/sources.list.5.gz
 /usr/share/man/it/man5/sources.list.5.gz
 /usr/share/man/ja/man5/sources.list.5.gz
 /usr/share/man/man5/sources.list.5.gz
 /usr/share/man/nl/man5/sources.list.5.gz
 /usr/share/man/pt/man5/sources.list.5.gz
 /var/lib/dpkg/info/mintsources.list
 /var/lib/dpkg/info/python3-pkg-resources.list

Pour effectuer une recherche rapide d’un chemin.

Si les commandes locate et updatedb ne sont pas présentes, on installe le paquet mlocate. Vous pouvez exécuter updatedb (en administrateur ou avec sudo) avant locate si nécessaire.

find

Recherche de fichiers depuis un répertoire de départ et sa descendance avec la commande find (en administrateur ou avec sudo).

find /etc -name sources.list ou sudo find /etc -name sources.list
 /etc/apt/sources.list
find /var/log/ -name "syslog" ou sudo find /var/log/ -name "syslog"
 /var/log/syslog
 /var/log/installer/syslog

Avec le caractère jockers * qui correspond à 0 ou n caractères pour rechercher par exemple tous les fichiers .png.

find -name ".png" ou sudo find -name ".png"
 ./Images/test.png
 ….

which

Les commandes externes sont fournies par des fichiers, which permet de les retrouver (pas besoin d’être administrateur).

which python
 /usr/bin/python
which bash
 /bin/bash
which pwd
 /bin/pwd

whereis

whereis localise l’exécutable (comme which) , les sources et la page de manuel d’une commande (pas besoin d’être administrateur).

whereis python
 python: /usr/bin/python /usr/bin/python2.7-config /usr/bin/python3.7m-config /usr/bin/python3.7m /usr/bin/python3.7-config /usr/bin/python2.7 /usr/bin/python3.7 /usr/lib/python2.7 /usr/lib/python3.7 /etc/python /etc/python2.7 /etc/python3.7 /usr/local/lib/python2.7 /usr/local/lib/python3.7 /usr/include/python3.7m /usr/include/python2.7 /usr/include/python3.7 /usr/share/python /usr/share/man/man1/python.1.gz
whereis -m bash    -m pour les pages de manuel
 bash: /usr/share/man/man1/bash.1.gz

La variable d’environnement PATH

Si vous avez installé un paquet, une commande, que le système ne trouve pas, vous pouvez la localiser avec whereis et ajouter le chemin d’accès de son dossier à la variable PATH.

Pour voir le contenu de la variable PATH (pas besoin d’être administrateur) :

 echo $PATH

Exemple, pour ajouter /usr/sbin à la variable d’environnement PATH (pas besoin d’être administrateur) :

export PATH=$PATH:/usr/sbin

Voir un cas dans l’article suivant :

Iftop surveiller le trafic réseau depuis un terminal sous Ubuntu ou Linux Mint et Debian

À la déconnexion PATH reprendra sa valeur par défaut, donc /usr/sbin n’existera plus dans PATH.

Pour modifier PATH de façon permanente

On peut éditer le fichier de configuration du Shell de connexion. Pour le Shell BASH il s’agit de /home/user/.bashrc.

Attention, vous devez remplacer user par votre nom d’utilisateur !

On peut utiliser un éditeur de texte ou utiliser la commande suivante :

echo 'export PATH=$PATH:/usr/sbin' >> /home/user/.bashrc

La ligne est ajoutée à la fin du fichier. Pour que la modification soit prise en compte, vous devez redémarrer votre ordinateur.

Plus d’informations

Si vous travaillez sur un système sans interface graphique, il peut être nécessaire de modifier la variable PATH pour la session afin d’avoir accès aux commandes permettant de redémarrer le système et de modifier également la variable PATH de façon permanente pour que cela soit pris en compte après le redémarrage.

J’ai dû modifier la variable PATH sous Debian 10.


Fichiers systèmes

Les fichiers systèmes que j’ai déjà eu l’occasion de modifier ou de consulter.

Quelques fichiers systèmes sous Linux

Les commandes host et hostname – noms de domaines sous Linux

Les commandes

La commande host

 host google.fr
 google.fr has address 172.217.19.227
 google.fr has IPv6 address 2a00:1450:4007:80b::2003
 google.fr mail is handled by 40 alt3.aspmx.l.google.com.
 google.fr mail is handled by 30 alt2.aspmx.l.google.com.
 google.fr mail is handled by 50 alt4.aspmx.l.google.com.
 google.fr mail is handled by 20 alt1.aspmx.l.google.com.
 google.fr mail is handled by 10 aspmx.l.google.com.

Donne l’IP associée au nom de domaine (ici . 172.217.19.227).

host 8.8.8.8
 8.8.8.8.in-addr.arpa domain name pointer dns.google.

Donne le nom de domaine principal associé à l’IP (ici dns.google). Sous Windows, depuis l’invite de commande, on utilisera la commande nslookup google.fr.

La commande hostname

 hostname
 debian-10

Donne le nom d’hôte de la machine

hostname --fqdn
 S4211Debian7.tsrit.2isa.local

Affiche le FQDN (nom de domaine complètement qualifié/Fully Qualified Domain Name).

hostname nouveau_nom

En administrateur, modifie le nom d’hôte de la machine.


Les fichiers

On peut voir le contenu des fichiers avec la commande cat. Pour modifier des fichiers, on peut utiliser un éditeur comme nano.

Le fichier host

Le fichier hosts donne un moyen d’assurer la résolution de noms, de donner un nom FQDN à un hôte.

cat /etc/hosts

Le fichier host.conf

Le fichier host.conf sert à indiquer à votre poste les méthodes successives qu’il va utiliser pour effectuer sa résolution de nom, par exemple : consulter avant tout son propre fichier host, puis s’adresser à un service DNS.

cat /etc/host.conf

Le fichier resolv.conf

Le fichier resolv.conf sert à indiquer la liste des serveurs DNS que vous allez interroger (exemple avec Debian 10). Des programmes tels que dhcpd, networkmanager, etc. peuvent modifier le fichier resolv.conf. Si vous voulez le paramétrer vous-même, il vous faudra faire en sorte d’empêcher ces modifications.

 cat /etc/resolv.conf
 Generated by NetworkManager
 search home
 nameserver 192.168.1.1
 nameserver 8.8.8.8

Le fichier hostname

Le nom de votre machine est sauvegardé dans le fichier hostname.

cat /etc/hostname
 debian-10