Tremplin des Scienceshttps://blog.tremplin.ens-lyon.fr/GerardVidal/2023-04-15T11:55:00+02:00Transcription, traduction, sous-titrage avec un outil d'IA2023-04-09T11:13:00+02:002023-04-15T11:55:00+02:00Gérard Vidaltag:blog.tremplin.ens-lyon.fr,2023-04-09:/GerardVidal/subtitles.html<p>Cet article présente les outils et une méthode pour ajouter des sous-titres à une vidéo, il fournit aussi les ressources pour réaliser la transcription d'un audio, éventuellement sa traduction. Ce travail a été réalisé pour le projet INCLUDE en utilisant les ressources du projet "Météo Climat tremplin pour l'enseignement des sciences".</p><p><strong><em>Motivations</em></strong></p>
<p>Le projet INCLUDE a soulevé un certain nombre de questions sur l'accessibilité numérique des documents produits par les enseignants.
L'utilisation des e-pub3.2+accessibility1.0 a été proposé comme l'une des solutions possibles, toutefois le respect de ces normes qui introduit un balisage avec un vocabulaire issu de <code>schema.org</code> ne fournit ni transcription des audio, ni sous-titrage.
Le but de ce travail est de décrire une méthode utilisée pour enrichir les vidéos incluses dans les livres numériques au format e-pub et plus généralement toute vidéo dont on souhaiterait améliorer l'accessibilité pour les malentendants.</p>
<hr>
<p><strong><em>Avertissement</em></strong></p>
<p>Lorsque j'ai réalisé ce travail je n'avais absolument pas perçu que je mettais en oeuvre un outil d'IA. J'avais simplement vérifié que le code était ouvert (licence MIT et communauté ouverte sur <a href="https://github.com/openai/whisper">GitHub</a>) sans aller plus loin dans l'investigation. L'outil whisper est <a href="https://openai.com/research/whisper">partagé avec la communauté par la société OpenAI</a> qui porte aussi <code>chatGPT</code> à propos duquel les discussions occupent le devant de la scène en ce moment. <code>Whisper</code> n'est pas un dérivé de chatGPT mais partage avec lui le même modèle. </p>
<p>GPT signifie "Generative Pre-trained Transformer" et fait partie de la famille des LLM "Large Language Model"; le pré-entrainement consiste à exposer l'algorithme à un gigantesque corpus de ressources à partir duquel par essais/évaluation successifs est affinée une échelle de probabilités d'enchainement de mots (ou de "tokens" selon le langage openAI qui correspondent plus ou mois à une partie de mot liée à une de ses racines). </p>
<p>On conçoit aisément que si en plus d'un outils de génération de texte on dispose d'un moteur capable de transcrire même rudimentairement les phonèmes en représentation textuelle, cela fournit à l'algorithme de génération des indications décisives pour choisir à tout moment de la lecture, avec une probabilité extrêmement forte, le mot suivant de la chaîne constituant la phrase enregistrée. Cela se traduit par la performance élevée de cet outil de transcription qui m'avait séduit. </p>
<p>je ne souhaite pas ici entrer dans le débat sur IA et enseignement, il me semble que le fait que chacun puisse contrôler les résultats de l'exécution avant de les diffuser, intervenir facilement sur quelques paramètres simples du modèle, contribuer à l'évolution ou modifier librement le code source du logiciel suffit à garantir durablement un usage sain et neutre. Un autre argument est fourni par les angagements éthiques d'openAI.</p>
<h3><em>Remerciements</em></h3>
<p>Éric le Jan et Charles-Henri Eyraud, Carole Larose, Benkouar Benyoucef.</p>
<hr>
<h3><em>Sommaire</em></h3>
<p><a href="#head1">Ajouter des sous-titres à une vidéo</a></p>
<ol>
<li><a href="#head1">Installation des logiciels</a><ol>
<li><a href="#head1.1">Linux</a> </li>
<li><a href="#head1.2">Windows</a> </li>
</ol>
</li>
<li><a href="#head2">Extraction de la piste audio d'une vidéo</a></li>
<li><a href="#head3">Transcription du fichier audio</a></li>
<li><a href="#head4">Correction du fichier texte issu de l'audio</a></li>
<li><a href="#head5">Ajout du canal de sous-titres à la vidéo</a><ol>
<li><a href="#head5.1">Sous-titres en "overlay"</a></li>
<li><a href="#head5.2">Sous-titres en "incrustation"</a></li>
</ol>
</li>
<li><a href="head6">Conclusion</a></li>
</ol>
<hr>
<h3><em>Téléchargements</em></h3>
<ol>
<li><a href="https://jubler.org/">jubler/</a></li>
<li><a href="https://openai.com/research/whisper">whisper</a></li>
<li><a href="https://deb-multimedia.org/">ffmpeg (Marillat version)</a></li>
</ol>
<hr>
<h1>Ajouter des sous-titres à une vidéo</h1>
<p>Les sous-titres dérivent forcément d'un fichier audio la procédure de sous-titrage requiert une étape préliminaire de traitement de la vidéo afin d'extraire le son sous forme d'un fichier audio. On utilise trois logiciels pour réaliser complètement la procédure :</p>
<ul>
<li>whisper</li>
<li>jubler</li>
<li>ffmpeg</li>
</ul>
<h2>Déroulé</h2>
<p>La procédure de transcription se déroule en trois étapes utilisant chacune l'un des logiciels installés avec les commandes ci-dessus :</p>
<ol>
<li>on extrait l'audio de la vidéo -> <em>ffmpeg</em></li>
<li>on réalise la transcription de l'audio (avec correction si besoin) -> <em>whisper</em> (+ <em>jubler</em> )</li>
<li>on intègre les sous-titres à la vidéo -> <em>ffmpeg</em></li>
</ol>
<h2><a id="head1"> 1.</a> Installation des logiciels</h2>
<h3><a id="head1.1"> 1.1</a> Linux</h3>
<p>L'installation détaillée ci-dessous concerne l'OS linux, pour les autres OS se reporter aux instructions détaillées depuis les pages de garde des 3 logiciels</p>
<p>Pour <code>whisper</code> il est nécessaire de créer un environnement virtuel python qui est la façon préconnisée pour gérer un logiciel avec des dépendances sans perturber le fonctionnement du système (nous utilisons ici <code>pipenv</code> mais les autres solutions de Virt.Envs python sont tout aussi valides). De plus au moment de l'installation (04-12-23) <code>openai-whisper</code> imposait l'usage de python < 3.11 à cause de la version de <code>numba</code> qui n'est pas encore adaptée à <code>python3.11</code>, cette limitation étant susceptible d'évoluer avec les mises à disposition de nouvelles versions de python3. Deux solutions sont possibles, soit on utilise <code>python3.9</code> ou <code>python3.10</code> soit on installe indépendamment numba avant d'installer whisper avec la commande <code>pipenv install "numba==0.57.0rc1"</code> dans l'environnement virtuel.</p>
<div class="highlight"><pre><span></span>mkdir -p Whisper/VenvWhisper
<span class="nb">cd</span> Whisper/VenvWhisper
pipenv --python <span class="m">3</span>.10 install openai-whisper pycuda torchaudio torchvision openai
</pre></div>
<p>Nous proposons d'installer la version <a href="https://deb-multimedia.org/">deb-multimedia</a> qui propose par défaut l'utilisation de fragments non libres mais qui en contrepartie fournit une grande souplesse d'utilisation en éliminant quelques incompatibilités. Pour les distributions Linux Debian et dérivées, ajouter dans <code>/etc/apt/sources.list.d</code> un fichier <code>ffmpegMarillat.list</code> contenant <code>deb https://www.deb-multimedia.org bookworm main non-free</code> puis effectuer les commandes suivantes.</p>
<div class="highlight"><pre><span></span>sudo apt update -oAcquire::AllowInsecureRepositories<span class="o">=</span><span class="nb">true</span>
sudo apt install deb-multimedia-keyring
sudo apt install ffmpeg
</pre></div>
<p>Jubler propose un <code>appimage</code> directement exécutable, j'ai pris l'habitude de les copier dans mon <code>/usr/local/bin</code>.</p>
<div class="highlight"><pre><span></span>wget https://github.com/teras/Jubler/releases/download/v7.0.3/Jubler-7.0.3.x86_64.appimage
chmod a+x Jubler-7.0.3.x86_64.appimage
sudo cp Jubler-7.0.3.x86_64.appimage /usr/local/bin/jubler
</pre></div>
<h3><a id="head1.2"> 1.2</a> Windows</h3>
<p>La méthode la plus simple (la seule que j'ai pu mener à bien) reste d'installer un <a href="https://learn.microsoft.com/fr-fr/windows/wsl/install">linux à l'intérieur de windows</a> puis de suivre ensuite la procédure proposée pour linux hormis pour <code>jubler</code>qui peut être directement installé depuis le <a href="https://jubler.org/download.html">site</a>. Windows limite les ressources et les affichages de linux mais le logiciel est fonctionnel.</p>
<h2><a id="head2"> 2.</a> Extraction de la piste audio d'une vidéo</h2>
<p>Il est utile de déterminer la structure de la vidéo utilisée afin de reconnaître les différentes pistes présentes. La commande <code>ffprobe nomVidéo</code> fournie par <em>ffmpeg</em> fait parfaitement ce travail :</p>
<div class="highlight"><pre><span></span>Input <span class="c1">#0, mov,mp4,m4a,3gp,3g2,mj2, from 'video1.mp4':</span>
Metadata:
major_brand : mp42
minor_version : <span class="m">1</span>
compatible_brands: mp41mp42isom
creation_time : <span class="m">2023</span>-02-27T22:26:28.000000Z
Duration: <span class="m">00</span>:09:07.10, start: <span class="m">0</span>.000000, bitrate: <span class="m">482</span> kb/s
Stream <span class="c1">#0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), [SAR 1:1 DAR 706:415], 346 kb/s, 60 fps, 60 tbr, 15360 tbn (default)</span>
Metadata:
creation_time : <span class="m">2023</span>-02-27T22:26:28.000000Z
handler_name : Core Media Video
vendor_id : <span class="o">[</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">]</span>
encoder : Lavc59.37.100 libx264
Stream <span class="c1">#0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 127 kb/s (default)</span>
Metadata:
creation_time : <span class="m">2023</span>-02-27T22:26:28.000000Z
handler_name : Core Media Audio
vendor_id : <span class="o">[</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">]</span>
</pre></div>
<p>Sur les données ci-dessus on peut lire que la vidéo utilisée dure <code>00:09:07.10</code> soit 9 minutes 7 secondes, elle fait <code>1412x830</code> pixels
Elle contient 2 flux :</p>
<ul>
<li>Un flux vidéo <code>#0:0[0x1](und): Video: h264</code> le codec est H264<ul>
<li>rapport de forme des pixels stockés <code>SAR 1:1</code></li>
<li>rapport d'aspect de l'affichage de la vidéo attendu <code>DAR 706:415</code> ce rapport bizarre est issu de la taille de la fenêtre de l'ordinateur qui a été enregistrée.</li>
</ul>
</li>
<li>Un flux audio <code>#0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D)</code> le codec est du acc, la désignation mp4a (parfois m4a) signifie qu'il s'agit d'un audio intégrée dans un conteneur mp4</li>
</ul>
<p>Pour extraire l'audio la commande suivante permet de récupérer le fichier audio pour les traitements ultérieurs.</p>
<div class="highlight"><pre><span></span>ffmpeg -i video1.mp4 -vn -acodec copy video1.aac
</pre></div>
<p>Les paramètres indiquent <code>-vn</code> pas de vidéo et <code>-acodec copy</code> copie du codec audio. On obtient un fichier audio au format <code>aac</code> qui est immediatement accessible par <code>whisper</code>.</p>
<h2><a id="head3"> 3.</a> Transcription du fichier audio</h2>
<p>Pour la transcription on utilise le logiciel <code>ai-whisper</code> qui dispose d'un grand nombre de paramètres permettant de moduler le modèle utilisé et les fonctions choisies pour les opérations. On utilise l'environnement virtuel créé dans le <a href="#head1">premier paragraphe</a>. Si vous êtes équipés d'une carte vidéo puissante avec les logiciels d'exploitation de sa puissance de calcul installés, <code>whisper</code> tentera de l'utiliser afin de minimiser le tamps de calcul, attention à la taille mémoire du modèle utilisé ! Si vous n'avez pas trop de mémoire sur la carte vidéo pensez à utiliser les petits modèles sinon le manque de mémoire indut des fautes aléatoires dont les messages sont peu explicites et ne renvoient pas forcément et explicitement l'avertissement d'un manque de mémoire. Il est toujours possible de contraindre l'exécution sur le CPU central avec l'option <code>--device</code> (<em>Pour les cartes vidéo, j'ai testé seulement l'exécution sur une nvidia avec CUDA qui a parfaitement fonctionné, j'essaierai une AMD si j'en trouve une que je parvienne à configurer</em>). La commande ci-dessous liste les principales options de <code>whisper</code>.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> Whisper/VenvWhisper/
pipenv run whisper --help
usage: whisper <span class="o">[</span>-h<span class="o">]</span> <span class="o">[</span>--model <span class="o">{</span>tiny.en,tiny,base.en,base,small.en,small,medium.en,medium,large-v1,large-v2,large<span class="o">}]</span> <span class="o">[</span>--model_dir MODEL_DIR<span class="o">]</span> <span class="o">[</span>--device DEVICE<span class="o">]</span>
<span class="o">[</span>--output_dir OUTPUT_DIR<span class="o">]</span> <span class="o">[</span>--output_format <span class="o">{</span>txt,vtt,srt,tsv,json,all<span class="o">}]</span> <span class="o">[</span>--verbose VERBOSE<span class="o">]</span> <span class="o">[</span>--task <span class="o">{</span>transcribe,translate<span class="o">}]</span>
<span class="o">[</span>--language <span class="o">{</span>af,am,ar,as,az,ba,be,bg,bn,bo,br,bs,ca,cs,cy,da,de,el,en,es,et,eu,fa,fi,fo,fr,gl,gu,ha,haw,he,hi,hr,ht,hu,hy,id,is,it,ja,jw,ka,kk,km,kn,ko,la,lb,ln,lo,lt,lv,mg,mi,mk,ml,mn,mr,ms,mt,my,ne,nl,nn,no,oc,pa,pl,ps,pt,ro,ru,sa,sd,si,sk,sl,sn,so,sq,sr,su,sv,sw,ta,te,tg,th,tk,tl,tr,tt,uk,ur,uz,vi,yi,yo,zh,Afrikaans,Albanian,Amharic,Arabic,Armenian,Assamese,Azerbaijani,Bashkir,Basque,Belarusian,Bengali,Bosnian,Breton,Bulgarian,Burmese,Castilian,Catalan,Chinese,Croatian,Czech,Danish,Dutch,English,Estonian,Faroese,Finnish,Flemish,French,Galician,Georgian,German,Greek,Gujarati,Haitian,Haitian Creole,Hausa,Hawaiian,Hebrew,Hindi,Hungarian,Icelandic,Indonesian,Italian,Japanese,Javanese,Kannada,Kazakh,Khmer,Korean,Lao,Latin,Latvian,Letzeburgesch,Lingala,Lithuanian,Luxembourgish,Macedonian,Malagasy,Malay,Malayalam,Maltese,Maori,Marathi,Moldavian,Moldovan,Mongolian,Myanmar,Nepali,Norwegian,Nynorsk,Occitan,Panjabi,Pashto,Persian,Polish,Portuguese,Punjabi,Pushto,Romanian,Russian,Sanskrit,Serbian,Shona,Sindhi,Sinhala,Sinhalese,Slovak,Slovenian,Somali,Spanish,Sundanese,Swahili,Swedish,Tagalog,Tajik,Tamil,Tatar,Telugu,Thai,Tibetan,Turkish,Turkmen,Ukrainian,Urdu,Uzbek,Valencian,Vietnamese,Welsh,Yiddish,Yoruba<span class="o">}]</span>
<span class="o">[</span>--temperature TEMPERATURE<span class="o">]</span> <span class="o">[</span>--best_of BEST_OF<span class="o">]</span> <span class="o">[</span>--beam_size BEAM_SIZE<span class="o">]</span> <span class="o">[</span>--patience PATIENCE<span class="o">]</span> <span class="o">[</span>--length_penalty LENGTH_PENALTY<span class="o">]</span>
<span class="o">[</span>--suppress_tokens SUPPRESS_TOKENS<span class="o">]</span> <span class="o">[</span>--initial_prompt INITIAL_PROMPT<span class="o">]</span> <span class="o">[</span>--condition_on_previous_text CONDITION_ON_PREVIOUS_TEXT<span class="o">]</span> <span class="o">[</span>--fp16 FP16<span class="o">]</span>
<span class="o">[</span>--temperature_increment_on_fallback TEMPERATURE_INCREMENT_ON_FALLBACK<span class="o">]</span> <span class="o">[</span>--compression_ratio_threshold COMPRESSION_RATIO_THRESHOLD<span class="o">]</span>
<span class="o">[</span>--logprob_threshold LOGPROB_THRESHOLD<span class="o">]</span> <span class="o">[</span>--no_speech_threshold NO_SPEECH_THRESHOLD<span class="o">]</span> <span class="o">[</span>--word_timestamps WORD_TIMESTAMPS<span class="o">]</span>
<span class="o">[</span>--prepend_punctuations PREPEND_PUNCTUATIONS<span class="o">]</span> <span class="o">[</span>--append_punctuations APPEND_PUNCTUATIONS<span class="o">]</span> <span class="o">[</span>--threads THREADS<span class="o">]</span>
audio <span class="o">[</span>audio ...<span class="o">]</span>
positional arguments:
audio audio file<span class="o">(</span>s<span class="o">)</span> to transcribe
options:
-h, --help show this <span class="nb">help</span> message and <span class="nb">exit</span>
--model <span class="o">{</span>tiny.en,tiny,base.en,base,small.en,small,medium.en,medium,large-v1,large-v2,large<span class="o">}</span>
name of the Whisper model to use <span class="o">(</span>default: small<span class="o">)</span>
--model_dir MODEL_DIR
the path to save model files<span class="p">;</span> uses ~/.cache/whisper by default <span class="o">(</span>default: None<span class="o">)</span>
--device DEVICE device to use <span class="k">for</span> PyTorch inference <span class="o">(</span>default: cpu<span class="o">)</span>
--output_dir OUTPUT_DIR, -o OUTPUT_DIR
directory to save the outputs <span class="o">(</span>default: .<span class="o">)</span>
--output_format <span class="o">{</span>txt,vtt,srt,tsv,json,all<span class="o">}</span>, -f <span class="o">{</span>txt,vtt,srt,tsv,json,all<span class="o">}</span>
format of the output file<span class="p">;</span> <span class="k">if</span> not specified, all available formats will be produced <span class="o">(</span>default: all<span class="o">)</span>
--verbose VERBOSE whether to print out the progress and debug messages <span class="o">(</span>default: True<span class="o">)</span>
--task <span class="o">{</span>transcribe,translate<span class="o">}</span>
whether to perform X->X speech recognition <span class="o">(</span><span class="s1">'transcribe'</span><span class="o">)</span> or X->English translation <span class="o">(</span><span class="s1">'translate'</span><span class="o">)</span> <span class="o">(</span>default: transcribe<span class="o">)</span>
--language <span class="o">{</span>af,am,ar,as,az,ba,be,bg,bn,bo,br,bs,ca,cs,cy,da,de,el,en,es,et,eu,fa,fi,fo,fr,gl,gu,ha,haw,he,hi,hr,ht,hu,hy,id,is,it,ja,jw,ka,kk,km,kn,ko,la,lb,ln,lo,lt,lv,mg,mi,mk,ml,mn,mr,ms,mt,my,ne,nl,nn,no,oc,pa,pl,ps,pt,ro,ru,sa,sd,si,sk,sl,sn,so,sq,sr,su,sv,sw,ta,te,tg,th,tk,tl,tr,tt,uk,ur,uz,vi,yi,yo,zh,Afrikaans,Albanian,Amharic,Arabic,Armenian,Assamese,Azerbaijani,Bashkir,Basque,Belarusian,Bengali,Bosnian,Breton,Bulgarian,Burmese,Castilian,Catalan,Chinese,Croatian,Czech,Danish,Dutch,English,Estonian,Faroese,Finnish,Flemish,French,Galician,Georgian,German,Greek,Gujarati,Haitian,Haitian Creole,Hausa,Hawaiian,Hebrew,Hindi,Hungarian,Icelandic,Indonesian,Italian,Japanese,Javanese,Kannada,Kazakh,Khmer,Korean,Lao,Latin,Latvian,Letzeburgesch,Lingala,Lithuanian,Luxembourgish,Macedonian,Malagasy,Malay,Malayalam,Maltese,Maori,Marathi,Moldavian,Moldovan,Mongolian,Myanmar,Nepali,Norwegian,Nynorsk,Occitan,Panjabi,Pashto,Persian,Polish,Portuguese,Punjabi,Pushto,Romanian,Russian,Sanskrit,Serbian,Shona,Sindhi,Sinhala,Sinhalese,Slovak,Slovenian,Somali,Spanish,Sundanese,Swahili,Swedish,Tagalog,Tajik,Tamil,Tatar,Telugu,Thai,Tibetan,Turkish,Turkmen,Ukrainian,Urdu,Uzbek,Valencian,Vietnamese,Welsh,Yiddish,Yoruba<span class="o">}</span>
language spoken in the audio, specify None to perform language detection <span class="o">(</span>default: None<span class="o">)</span>
--temperature TEMPERATURE
temperature to use <span class="k">for</span> sampling <span class="o">(</span>default: <span class="m">0</span><span class="o">)</span>
--best_of BEST_OF number of candidates when sampling with non-zero temperature <span class="o">(</span>default: <span class="m">5</span><span class="o">)</span>
--beam_size BEAM_SIZE
number of beams in beam search, only applicable when temperature is zero <span class="o">(</span>default: <span class="m">5</span><span class="o">)</span>
--patience PATIENCE optional patience value to use in beam decoding, as in https://arxiv.org/abs/2204.05424, the default <span class="o">(</span><span class="m">1</span>.0<span class="o">)</span> is equivalent to conventional beam search
<span class="o">(</span>default: None<span class="o">)</span>
--length_penalty LENGTH_PENALTY
optional token length penalty coefficient <span class="o">(</span>alpha<span class="o">)</span> as in https://arxiv.org/abs/1609.08144, uses simple length normalization by default <span class="o">(</span>default: None<span class="o">)</span>
--suppress_tokens SUPPRESS_TOKENS
comma-separated list of token ids to suppress during sampling<span class="p">;</span> <span class="s1">'-1'</span> will suppress most special characters except common punctuations <span class="o">(</span>default: -1<span class="o">)</span>
--initial_prompt INITIAL_PROMPT
optional text to provide as a prompt <span class="k">for</span> the first window. <span class="o">(</span>default: None<span class="o">)</span>
--condition_on_previous_text CONDITION_ON_PREVIOUS_TEXT
<span class="k">if</span> True, provide the previous output of the model as a prompt <span class="k">for</span> the next window<span class="p">;</span> disabling may make the text inconsistent across windows, but the
model becomes less prone to getting stuck in a failure loop <span class="o">(</span>default: True<span class="o">)</span>
--fp16 FP16 whether to perform inference in fp16<span class="p">;</span> True by default <span class="o">(</span>default: True<span class="o">)</span>
--temperature_increment_on_fallback TEMPERATURE_INCREMENT_ON_FALLBACK
temperature to increase when falling back when the decoding fails to meet either of the thresholds below <span class="o">(</span>default: <span class="m">0</span>.2<span class="o">)</span>
--compression_ratio_threshold COMPRESSION_RATIO_THRESHOLD
<span class="k">if</span> the gzip compression ratio is higher than this value, treat the decoding as failed <span class="o">(</span>default: <span class="m">2</span>.4<span class="o">)</span>
--logprob_threshold LOGPROB_THRESHOLD
<span class="k">if</span> the average log probability is lower than this value, treat the decoding as failed <span class="o">(</span>default: -1.0<span class="o">)</span>
--no_speech_threshold NO_SPEECH_THRESHOLD
<span class="k">if</span> the probability of the <<span class="p">|</span>nospeech<span class="p">|</span>> token is higher than this value AND the decoding has failed due to <span class="sb">`</span>logprob_threshold<span class="sb">`</span>, consider the segment
as silence <span class="o">(</span>default: <span class="m">0</span>.6<span class="o">)</span>
--word_timestamps WORD_TIMESTAMPS
<span class="o">(</span>experimental<span class="o">)</span> extract word-level timestamps and refine the results based on them <span class="o">(</span>default: False<span class="o">)</span>
--prepend_punctuations PREPEND_PUNCTUATIONS
<span class="k">if</span> word_timestamps is True, merge these punctuation symbols with the next word <span class="o">(</span>default: <span class="s2">"'“¿([{-)</span>
<span class="s2"> --append_punctuations APPEND_PUNCTUATIONS</span>
<span class="s2"> if word_timestamps is True, merge these punctuation symbols with the previous word (default: "</span><span class="err">'</span>.。,,!!??::”<span class="o">)]}</span>、<span class="o">)</span>
--threads THREADS number of threads used by torch <span class="k">for</span> CPU inference<span class="p">;</span> supercedes MKL_NUM_THREADS/OMP_NUM_THREADS <span class="o">(</span>default: <span class="m">0</span><span class="o">)</span>
</pre></div>
<p>La commande utilisée avec une configuration minimaliste permet de produire un fichier au format <code>srt</code> (le modèle medium ne passe pas sur ma carte NVIDIA GeForce GTX 1660 SUPER avec un bureau ouvert mais Xorg,firefox et thunderbird mobilisent un peu plus de 800M, medium passe peut-être en mode console...). Tous les centres de calcul proposent des machines équipées de grosses cartes graphiques de calcul qui peuvent au besoin sous-traiter ce calcul.</p>
<div class="highlight"><pre><span></span>whisper --model small --task transcribe --output_format srt --language fr video1.aac
</pre></div>
<p>Commande pour produire les sous-titres en anglais (penser à changer le nom du fichier <code>srt</code> qui sera écrasé sinon) :</p>
<div class="highlight"><pre><span></span>whisper --model small --output_format srt --task translate --language fr video1.aac
</pre></div>
<h2><a id="head4"> 4.</a> Correction du fichier texte issu de l'audio</h2>
<p>Le fichier produit par <code>ai-whisper</code> malgré le support d'un modèle d'IA peut ne pas être exempt d'anomalies, il est nécessaire de relire le fichier afin de corriger les éventuelles erreurs qui auraient échappé au dispositif automatisé (À titre d'exemple sur le fichier traité ici on a relevé une seule erreur). On utilise pour cela l'interface graphique du logiciel jubler. Ouvrir le fichier <code>srt</code> puis cliquer sur chaque ligne qui doit être corrigée et effectuer les corrections nécessaires puis sauvegarder le fichier.</p>
<h2><a id="head5"> 5.</a> Ajout du canal de sous-titres à la vidéo</h2>
<p>La dernière opération consiste à ajouter le ou les canaux de sous-titres à la vidéo originelle. Deux méthodes sont possibles et éventuellement complémentaires :</p>
<ul>
<li>ajouter les sous-titres dans des canaux indépendants ("overlay" ce qui requiert, pour les voir, un lecteur capable de détecter ces canaux et d'en afficher un ou un autre ou de les masquer à la demande)</li>
<li>incruster les sous-titres dans l'image sous la forme d'une surcouche (incrustation), il n'y a pas de canal supplémentaire créé et la vidéo affiche en permanence les sous-titres.</li>
</ul>
<h2><a id="head5.1"> 5.1.</a> Sous-titres en "overlay"</h2>
<ul>
<li><a href="https://media.tremplin.ens-lyon.fr/ressources/users/GerardVidal/Accessibility/Video/video1+sstit.mp4">Exemple avec un fichier de sous-titres (mp4)</a></li>
<li><a href="https://media.tremplin.ens-lyon.fr/ressources/users/GerardVidal/Accessibility/Video/video1+sstit.mp4">Exemple avec un fichier de sous-titres (webm)</a></li>
<li><a href="https://media.tremplin.ens-lyon.fr/ressources/users/GerardVidal/Accessibility/Video/video1+2sstit.mp4">Exemple avec deux fichier de sous-titres (mp4)</a></li>
<li><a href="https://media.tremplin.ens-lyon.fr/ressources/users/GerardVidal/Accessibility/Video/video1+2sstit.mp4">Exemple avec udeux fichier de sous-titres (webm)</a></li>
</ul>
<p>Cette méthode est la plus simple et la moins consommatrice de temps car les images de la vidéo ne sont pas modifiées et les sous-titres ajoutés sous la forme d'un canal supplémentaire qui doit être géré par le lecteur. L'intérêt majeur est qu'un utilisateur ne souhaitant pas lire les sous-titres pourra afficher l'image intacte et celui qui souhaite les lire les afficher en transparence. On utilise la commande ffmpeg suivante à partir de la vidéo <code>video1.mp4</code> avec les sous-titres <code>video1.srt</code> produits précédemment :</p>
<div class="highlight"><pre><span></span>ffmpeg -i video1.mp4 -i video1.srt -c copy -c:s mov_text video1+sstit.mp4
</pre></div>
<p>On a alors une vidéo contenant 3 flux :</p>
<div class="highlight"><pre><span></span>ffprobe video1+sstit.mp4
Input <span class="c1">#0, mov,mp4,m4a,3gp,3g2,mj2, from 'video1+sstit.mp4':</span>
Metadata:
major_brand : isom
minor_version : <span class="m">512</span>
compatible_brands: isomiso2avc1mp41
encoder : Lavf59.27.100
Duration: <span class="m">00</span>:09:07.12, start: <span class="m">0</span>.000000, bitrate: <span class="m">487</span> kb/s
Stream <span class="c1">#0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1412x830 [SAR 1:1 DAR 706:415], 346 kb/s, 60 fps, 60 tbr, 15360 tbn (default)</span>
Metadata:
handler_name : Core Media Video
vendor_id : <span class="o">[</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">]</span>
encoder : Lavc59.37.100 libx264
Stream <span class="c1">#0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 127 kb/s (default)</span>
Metadata:
handler_name : Core Media Audio
vendor_id : <span class="o">[</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">]</span>
Stream <span class="c1">#0:2[0x3](und): Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s (default)</span>
Metadata:
handler_name : SubtitleHandler
../...
</pre></div>
<p>Il est aussi possible de rajouter une seconde piste de sous-titres, par exemple ici en anglais avec le fichier <code>video1-en.srt</code> :</p>
<div class="highlight"><pre><span></span>ffmpeg -i video1+sstit.mp4 -i video1-en.srt -map <span class="m">0</span> -map <span class="m">1</span> -vcodec copy -acodec copy -c:s:0 copy -c:s:1 copy -c:s:1 mov_text -metadata:s:s:1 <span class="nv">language</span><span class="o">=</span>English video1+2sstit.mp4
</pre></div>
<p>Le fichier vidéo présentee alors 2 flux de sous-titres :</p>
<div class="highlight"><pre><span></span>ffprobe video1+2sstit.mp4
.../...
Input <span class="c1">#0, mov,mp4,m4a,3gp,3g2,mj2, from 'video1+2sstit.mp4':</span>
Metadata:
major_brand : isom
minor_version : <span class="m">512</span>
compatible_brands: isomiso2avc1mp41
encoder : Lavf59.27.100
Duration: <span class="m">00</span>:09:07.12, start: <span class="m">0</span>.000000, bitrate: <span class="m">487</span> kb/s
Stream <span class="c1">#0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1412x830 [SAR 1:1 DAR 706:415], 346 kb/s, 60 fps, 60 tbr, 15360 tbn (default)</span>
Metadata:
handler_name : Core Media Video
vendor_id : <span class="o">[</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">]</span>
encoder : Lavc59.37.100 libx264
Stream <span class="c1">#0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 127 kb/s (default)</span>
Metadata:
handler_name : Core Media Audio
vendor_id : <span class="o">[</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">]</span>
Stream <span class="c1">#0:2[0x3](und): Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s (default)</span>
Metadata:
handler_name : SubtitleHandler
Stream <span class="c1">#0:3[0x4]: Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s</span>
Metadata:
handler_name : SubtitleHandler
</pre></div>
<p>Il est aussi possible de rajouter plusieurs sous-titres directement en une seule passe ici pour le film <a href="https://media.tremplin.ens-lyon.fr/ressources/users/GerardVidal/IndexationCuration/curationIFE+sstt.mp4">curationIFE</a> Le lien conduit à la vidéo avec sous-titres (à visualiser sur un player capable de les détecter VLC par exemple) :</p>
<div class="highlight"><pre><span></span>ffmpeg -i curationIFE.mp4 -i curationIFE-fr-cor.srt -i curationIFE-en-cor.srt -map <span class="m">0</span>:v -map <span class="m">0</span>:a -map <span class="m">1</span> -map <span class="m">2</span> -c:v copy -c:a copy -c:s mov_text -metadata:s:s:0 <span class="nv">language</span><span class="o">=</span>fre -metadata:s:s:1 <span class="nv">language</span><span class="o">=</span>eng curationIFE+sstt.mp4
</pre></div>
<p>Dans un player capable de détecter les sous-titres (par exemple VLC) on a alors desux "pistes" proposées dans l'onglet sous-titres.</p>
<h2><a id="head5.2"> 5.2.</a> Sous-titres en "incrustation"</h2>
<ul>
<li><a href="https://media.tremplin.ens-lyon.fr/ressources/users/GerardVidal/Accessibility/Video/video1+sstit2.mp4">Exemple avec sous-titres incrustés (mp4)</a></li>
<li><a href="https://media.tremplin.ens-lyon.fr/ressources/users/GerardVidal/Accessibility/Video/video1+sstit2.webm">Exemple avec sous-titres incrustés (webm)</a></li>
</ul>
<p>L'incrustation des sous-titres est une opération un peu plus complexe car les images de la vidéo qui contiennent des sous-titres sont recomposées en incrustant dans l'image le sous-titre ce qui impose de modifier tous les pixels correspondant à la surface des sous-titres. Une difficulté supplémentaire vient (au moins pour la méthode proposée) de ce qu'il faille utiliser le format <code>.ass</code> au lieu de <code>.srt</code> pour les sous-titres, une conversion de format est donc nécessaire en amont. La manipulation a été réalise avec l'enchaînement de commandes suivant :</p>
<div class="highlight"><pre><span></span>ffmpeg -i video1.srt video1.ass <span class="c1"># produit le fichier de sous-titres au format ass</span>
ffmpeg -i video1.mp4 -filter_complex <span class="s2">"subtitles=video1.ass:force_style='BackColour=&H70000000,BorderStyle=4,Outline=1,Shadow=0,MarginV=10'"</span> video1+sstit2.mp4
</pre></div>
<p>La partie <code>filter_complex "subtitles=video1.ass:force_style='BackColour=&H70000000,BorderStyle=4,Outline=1,Shadow=0,MarginV=10'"</code> gère le détail des options de présentation des sous-titres, comme souvent dans ffmpeg ces options sont délicates à manipuler parce qu'elles agissent au plus bas niveau et sans "garde-fou"; consultez la documentation et agissez avec précaution pour les manipuler, de nombreuses options cont possibles tant sur le texte que sur le fond.</p>
<p>La vidéo produite ne contient <strong>aucun</strong> flux de sous-titre, le texte est directement incrusté dans les images.</p>
<div class="highlight"><pre><span></span>ffprobe video1+sstit2.mp4
.../...
Input <span class="c1">#0, mov,mp4,m4a,3gp,3g2,mj2, from 'video1+sstit2.mp4':</span>
Metadata:
major_brand : isom
minor_version : <span class="m">512</span>
compatible_brands: isomiso2avc1mp41
encoder : Lavf59.27.100
Duration: <span class="m">00</span>:09:07.12, start: <span class="m">0</span>.000000, bitrate: <span class="m">578</span> kb/s
Stream <span class="c1">#0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1412x830 [SAR 1:1 DAR 706:415], 437 kb/s, 60 fps, 60 tbr, 15360 tbn (default)</span>
Metadata:
handler_name : VideoHandler
vendor_id : <span class="o">[</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">]</span>
encoder : Lavc59.37.100 libx264
Stream <span class="c1">#0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)</span>
Metadata:
handler_name : Core Media Audio
vendor_id : <span class="o">[</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">][</span><span class="m">0</span><span class="o">]</span>
</pre></div>
<h1><a id="head6"> 6.</a> Conclusion</h1>
<p>Cet article présente une des nombreuses façons de sous-titrer une vidéo, la méthode proposée peut certainement être améliorée ou modifiée en fonction de contraintes ou de choix éditoriaux. Un des intérêts est de montrer la faisabilité de l'opération sans qu'il soit besoin de connaissances avancées en media ou en numérique. Il est toutefois parfaitement clair qu'une production qe qualité professionnelle requiert des compétences professionnelles, toutefois il est probable que des étudiants malentendants apprécieront de disposer des sous-titres, de même la possibilité de proposer les sous-titres en anglais ouvre des perspectives importantes.</p>Installer un Serveur DNS sur debian (raspberry Pi)2022-07-10T11:51:00+02:002022-07-10T11:51:00+02:00Gérard Vidaltag:blog.tremplin.ens-lyon.fr,2022-07-10:/GerardVidal/DNSserver.html<p>Cet article récapitule les commandes utilisées pour installer un serveur DNS sur une machine linux Debian avec <code>bind</code>. Cet installation a été effectuée en <code>bookworm</code>.</p><h1>DNS server installation <code>debian</code></h1>
<p>machine 3littlehills 192.168.10.111 passerelle 192.168.10.1</p>
<h2>Modification de l'environnement existant</h2>
<p>Modifier les fichiers <code>hostname</code>et <code>hosts</code> pour introduire ne nom de la zone.</p>
<div class="highlight"><pre><span></span>sudo jed /etc/hostname
cat /etc/hostname
<span class="c1">#</span>
3littlehills.raspinet
</pre></div>
<div class="highlight"><pre><span></span>sudo jed /etc/hosts
cat /etc/hosts
<span class="c1">#</span>
<span class="m">127</span>.0.0.1 localhost
<span class="m">127</span>.0.1.1 3littlehills.raspinet 3littlehills
<span class="m">192</span>.168.10.111 3littlehills.raspinet 3littlehills
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
</pre></div>
<p>Mettre à jour les paquets <code>sudo apt update</code>puis installer bind9 <code>sudo apt install bind9 dnsutils</code> modifier le fichier <code>/etc/systemd/resolved.conf</code> afin que le fichier <code>/etc/resolv.conf</code>prenne en compte la nouvelle zone.</p>
<div class="highlight"><pre><span></span>sudo jed /etc/systemd/resolved.conf
cat /etc/systemd/resolved.conf
<span class="c1">#</span>
<span class="c1"># This file is part of systemd.</span>
<span class="c1">#</span>
<span class="c1"># systemd is free software; you can redistribute it and/or modify it</span>
<span class="c1"># under the terms of the GNU Lesser General Public License as published by</span>
<span class="c1"># the Free Software Foundation; either version 2.1 of the License, or</span>
<span class="c1"># (at your option) any later version.</span>
<span class="c1">#</span>
<span class="c1"># Entries in this file show the compile time defaults.</span>
<span class="c1"># You can change settings by editing this file.</span>
<span class="c1"># Defaults can be restored by simply deleting this file.</span>
<span class="c1">#</span>
<span class="c1"># See resolved.conf(5) for details</span>
<span class="o">[</span>Resolve<span class="o">]</span>
<span class="c1"># Some examples of DNS servers which may be used for DNS= and FallbackDNS=:</span>
<span class="c1"># Cloudflare: 1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001</span>
<span class="c1"># Google: 8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844</span>
<span class="c1"># Quad9: 9.9.9.9 2620:fe::fe</span>
<span class="nv">DNS</span><span class="o">=</span><span class="m">192</span>.168.10.1 <span class="m">9</span>.9.9.9 <span class="m">2620</span>:fe::fe
<span class="nv">FallbackDNS</span><span class="o">=</span><span class="m">9</span>.9.9.9 <span class="m">2620</span>:fe::fe
<span class="nv">Domains</span><span class="o">=</span>raspinet
<span class="c1">#DNSSEC=no</span>
<span class="c1">#DNSOverTLS=no</span>
<span class="c1">#MulticastDNS=yes</span>
<span class="c1">#LLMNR=yes</span>
<span class="c1">#Cache=yes</span>
<span class="c1">#DNSStubListener=yes</span>
<span class="c1">#DNSStubListenerExtra=</span>
<span class="c1">#ReadEtcHosts=yes</span>
<span class="c1">#ResolveUnicastSingleLabel=no</span>
</pre></div>
<h2>Configuration de bind</h2>
<p>Accéder au dossier de configuration de <code>bind</code> modifier les fichiers de configuration puis ajouter les fichiers de définition de la nouvelle zone <code>cd /etc/bind</code>.</p>
<div class="highlight"><pre><span></span>sudo cp named.conf.local named.conf.local-orig
sudo jed named.conf.local
cat named.conf.local
<span class="c1">#</span>
//
// Do any <span class="nb">local</span> configuration here
//
// Consider adding the <span class="m">1918</span> zones here, <span class="k">if</span> they are not used in your
// organization
//include <span class="s2">"/etc/bind/zones.rfc1918"</span><span class="p">;</span>
zone <span class="s2">"raspinet"</span> <span class="o">{</span>
<span class="nb">type</span> master<span class="p">;</span>
file <span class="s2">"/etc/bind/db.raspinet"</span><span class="p">;</span>
<span class="o">}</span><span class="p">;</span>
zone <span class="s2">"10.168.192.in-addr.arpa"</span> <span class="o">{</span>
<span class="nb">type</span> master<span class="p">;</span>
file <span class="s2">"/etc/bind/db.1O.168.192.in-addr.arpa"</span><span class="p">;</span>
<span class="o">}</span><span class="p">;</span>
</pre></div>
<div class="highlight"><pre><span></span>sudo jed db.raspinet
<span class="c1">#</span>
<span class="nv">$TTL</span> <span class="m">10800</span>
<span class="nv">$ORIGIN</span> raspinet.
@ IN SOA 3littlehills.raspinet. root.raspinet. <span class="o">(</span>
<span class="m">20220710</span><span class="p">;</span>
3h<span class="p">;</span>
1h<span class="p">;</span>
1w<span class="p">;</span>
1h<span class="o">)</span><span class="p">;</span>
@ IN NS 3littlehills.raspinet.
3littlehills IN A <span class="m">192</span>.168.10.111
host IN A <span class="m">192</span>.168.10.1
</pre></div>
<div class="highlight"><pre><span></span>sudo jed db.1O.168.192.in-addr.arpa
<span class="c1">#</span>
<span class="nv">$TTL</span> <span class="m">10800</span>
<span class="nv">$ORIGIN</span> <span class="m">10</span>.168.192.in-addr.arpa.
@ IN SOA 3littlehills.raspinet. root.raspinet. <span class="o">(</span>
<span class="m">20220710</span><span class="p">;</span>
3h<span class="p">;</span>
1h<span class="p">;</span>
1w<span class="p">;</span>
1h<span class="o">)</span><span class="p">;</span>
@ IN NS 3littlehills.raspinet.
<span class="m">132</span> IN PTR 3littlehills.raspinet.
<span class="m">1</span> IN PTR host.raspinet.
</pre></div>
<p>Vérifier le fonctionnement du dispositif avec <code>named-checkconf -z</code>.</p>
<div class="highlight"><pre><span></span>zone raspinet/IN: loaded serial <span class="m">20220710</span>
zone <span class="m">10</span>.168.192.in-addr.arpa/IN: loaded serial <span class="m">20220710</span>
zone localhost/IN: loaded serial <span class="m">2</span>
zone <span class="m">127</span>.in-addr.arpa/IN: loaded serial <span class="m">1</span>
zone <span class="m">0</span>.in-addr.arpa/IN: loaded serial <span class="m">1</span>
zone <span class="m">255</span>.in-addr.arpa/IN: loaded serial <span class="m">1</span>
</pre></div>Comment créer une image Debian pour Raspberry Pi0 -> Pi4, buster ou bullseye adaptée à vos besoins (exemple : Codage, Météo-Climat, ...)2022-01-11T17:21:00+01:002018-01-20T17:06:00+01:00Gérard Vidaltag:blog.tremplin.ens-lyon.fr,2022-01-11:/GerardVidal/RaspberryPiBuildImage.html<p>Comment construire une image <code>debian buster</code> ou <code>debian bullseye</code> standard</p><p>pour une Raspberry Pi (0 1 2 3 ou 4). les images sont construites pour êtres
directement utilisables dans un univers Météo/Climat pour piloter une station
Météorologique et gérer les données, apprendre ou enseigner le codage avec
les outils <code>SNAP!BYOB</code> (comme scratch) et <code>jupyter</code> pour aborder <code>python</code> et
<code>javascript</code>. Les versions <code>debian stretch</code>sont maintenant obsolètes, il subsiste
quelques références pour des raisons de compatibilité et les anciennes versions des
articles se trouvent dans le répertoire <code>Archives</code>.</p>
<p><strong><em>Motivations</em></strong></p>
<p>Le but de cet article est de décrire la procédure technique permettant de construire
un système d'exploitation Debian "orthodoxe" (totalement analogue à celui qui
est installé sur un ordinateur ordinaire) et qui fonctionne sur une Raspberry Pi.
La motivation principale est de disposer d'une distribution standard augmentée de tous les logiciels
nécessaires pour piloter le <code>GPIO</code>, gérer une station météorologique, apprendre à
coder en python ou C++ à l'aide d'une interface web <code>jupyter</code>ou <code>jupyterlab</code>. La seconde
motivation est de proposer une explication de TOUT ce qui est fait pour
construire le système d'exploitation en évitant les commandes parfois perçues
comme "magiques".</p>
<p>Cet article décrit la construction d'images apparentées, chacune dédiée à un mode de fonctionnement particulier :</p>
<ul>
<li>Une image raspberry Pi0 buster pour piloter une station météo et partager des données</li>
<li>Une image raspberry Pi1 buster pour apprendre à coder (en cours)</li>
<li>Une image raspberry Pi2 buster pour apprendre à coder</li>
<li>Une image raspberry Pi3 buster pour piloter une station météo et partager des données</li>
<li>Une image raspberry Pi3 buster pour apprendre à coder </li>
<li>Une image raspberry Pi4 buster pour apprendre à coder</li>
<li>Deux images raspberry Pi3 Pi4 bullseye tous terrains permettant de suivre tous les
aspects innovants du projet et de préparer les migrations à venir</li>
</ul>
<hr>
<h3><em>Remerciements</em></h3>
<p>Carole Larose, Myriam Bentoumi, Éric le Jan et Charles-Henri Eyraud.</p>
<hr>
<h3><em>Sommaire</em></h3>
<ol>
<li>
<p><a href="#head1">Stratégie adoptée</a></p>
<p>1.1. <a href="#head1.1">Trois phases de construction</a></p>
<ul>
<li><a href="#head1.1.1">Construction de l'image avec le script automatisé "rpi23genimage" et premiers services</a></li>
<li><a href="#head1.1.2">Ajustements manuels génériques</a></li>
<li><a href="#head1.1.3">Configuration particulière avancée</a></li>
</ul>
<p>1.2. <a href="#head1.2">Quatre générations de RaspberryPi (rpi2-rpi3-rpi3B+-rpi4), deux familles d'images (codage-station météo) et deux distributions (buster-bullseye)</a></p>
<p>1.3. <a href="#head1.3">Mode de classement et moyen de retrouver une information</a></p>
</li>
<li>
<p><a href="#head2">Construction de l'image avec le script "rpi23genimage" et premiers services</a></p>
<p>2.1. <a href="#head2.1">Raspberry Pi0 Buster</a></p>
<p>2.2. <a href="#head2.2">Raspberry Pi1 Buster</a></p>
<p>2.3. <a href="#head2.3">Raspberry Pi2 Buster</a></p>
<p>2.4. <a href="#head2.4">Raspberry Pi3 Buster</a></p>
<p>2.5. <a href="#head2.5">Raspberry Pi3B+ Buster</a></p>
<p>2.6. <a href="#head2.6">Raspberry Pi3 Buster sans serveur graphique</a></p>
<p>2.7. <a href="#head2.7">Raspberry Pi3 BullsEye</a></p>
<p>2.8. <a href="#head2.8">Raspberry Pi4 Buster</a></p>
<p>2.9. <a href="#head2.9">Raspberry Pi4 BullsEye</a></p>
</li>
<li>
<p><a href="#head3">Ajustements manuels génériques</a></p>
<p>3.1. <a href="#head3.1">Copie de l'image sur une micro-SD</a></p>
<p>3.2. <a href="#head3.2">ajustement de la taille de l'image</a></p>
<p>3.3. <a href="#head3.3">Particularités de la Pi0</a></p>
<p>3.4. <a href="#head3.4">Configuration du réseau</a></p>
<ul>
<li><a href="#head3.4.1">Configuration par défaut <code>connman</code></a></li>
<li><a href="#head3.4.2">Configuration via <code>systemd-networkd</code> et <code>wpa_spplicant</code></a> <ul>
<li><a href="#head3.4.2.1">IP fixe</a></li>
<li><a href="#head3.4.2.2">IP dynamique fournie par le DHCP</a> </li>
</ul>
</li>
<li><a href="#head3.4.3">Détection de l'interface WIFI</a><ul>
<li><a href="#head3.4.3.1">Logiciel <code>connman</code> en bullseye</a></li>
<li><a href="#head3.4.3.2">Logiciel <code>wicd</code> par défaut jusqu'à <code>buster</code></a></li>
<li><a href="#head3.4.3.3">Logiciel <code>wpa_cli</code> en bullseye</a></li>
</ul>
</li>
<li><a href="#head3.4.4">(Optionnel) Configuration de <code>systemd-networkd</code> au lieu de <code>wicd</code></a></li>
</ul>
</li>
<li>
<p><a href="#head4">Ajustements après démarrage de la Raspberry munie de sa nouvelle image</a></p>
<p>4.1. <a href="#head4.1">Modification de la taille de l'espace utilisé (au besoin seulement)</a></p>
<p>4.2. <a href="#head4.2">Mises à jour et installation d'utilitaires</a></p>
<p>4.3. <a href="#head4.3">Ajout d'une interface graphique</a></p>
<p>4.4. <a href="#head4.4">Ajout d'utilisateurs et distribution des droits</a></p>
<p>4.5. <a href="#head4.5">Activation du serveur de terminaux à distance</a></p>
<ul>
<li><a href="#head4.5.1">Mise en place de <code>tigervnc</code></a></li>
<li><a href="#head4.5.2">Mise en place de <code>xrdp</code></a></li>
<li><a href="#head4.5.3">(Seulement si besoin incontournable) Dégradation de la sécurité ou retour à <code>tightvncserver</code></a></li>
</ul>
<p>4.6 <a href="#head4.6">Modification des accès au <code>GPIO</code> et à la caméra</a></p>
</li>
<li>
<p><a href="#head5">Utilisation de la Raspberrry en point d'accès web (Hotspot)</a></p>
</li>
<li>
<p><a href="#head6">Configurations particulières avancées</a></p>
<p>6.1. <a href="#head6.1">Image stretch ou buster ou bullseye "tous terrains Pi3 ou Pi3B+ ou 4" permettant entre autres l'apprentissage de la programmation</a></p>
<ul>
<li><a href="#head6.1.1">Compilation d'un cmake récent</a></li>
<li><a href="#head6.1.2">Ajout de fontes</a></li>
<li><a href="#head6.1.3">Activation de la caméra raspberry Pi</a> <ul>
<li><a href="#head6.1.3.1">Détection de la caméra</a></li>
<li><a href="#head6.1.3.2">Ajout des logiciels de pilotage de la caméra </a></li>
</ul>
</li>
<li><a href="#head6.1.4">Activation du réseau WIFI et du réseau filaire</a> <ul>
<li><a href="#head6.1.4.1">Configurer le réseau filaire</a></li>
<li><a href="#head6.1.4.2">Configurer le WIFI</a></li>
</ul>
</li>
</ul>
<p>6.2 <a href="#head6.2">Installation et mise à jour de l'nvironnement logiciel</a></p>
<ul>
<li><a href="#head6.2.1">Récupération et installation de Node.js</a><ul>
<li><a href="#head6.2.1.1">Récupération et installation de <code>nvm</code></a></li>
<li><a href="#head6.2.1.2">Récupération et installation de <code>nodejs</code></a></li>
</ul>
</li>
<li><a href="#head6.2.2">Récupération et construction du paquet swig</a></li>
<li><a href="#head6.2.3">Récupération et construction du paquet libopenzwave</a></li>
<li><a href="#head6.2.4">Récupération et construction du paquet modbus</a></li>
<li><a href="#head6.2.5">Récupération et construction du paquet tinyb</a></li>
<li><a href="#head6.2.6">Récupération et Construction de mraa et upm</a></li>
<li><a href="#head6.2.7">Installation de compléments Python</a></li>
</ul>
<p>6.3 <a href="#head6.3">Installation d'un simulateur graphique de réseau après avoir installé un docker</a> </p>
<p>6.4 <a href="#head6.4">Installation de Jupyterlab et Jupyterhub</a></p>
<ul>
<li><a href="#head6.4.1">Configuration de la sécurité et du lancement par le user callisto</a></li>
<li><a href="#head6.4.2">Ajout d'un moteur nodeJS dans l'environnement jupyter/jupyterhub</a></li>
<li><a href="#head6.4.3">Installation d'un service <code>jupyterhub</code> ou <code>jupyterlabhub</code></a><ul>
<li><a href="#head6.4.3.1">Mise en place de jupyterhub </a></li>
<li><a href="#head6.4.3.2">Mise en place de jupyterlabhub</a></li>
</ul>
</li>
<li><a href="#head6.4.4">(Option obsolète) Installation d'une alternative entre jupyterlab et jupyter</a></li>
</ul>
<p>6.5 <a href="#head6.5">Installation de Snap!BYOB</a>
6.6 <a href="#head6.6">Installation de Domoticz pour piloter des objets connectés du commerce</a></p>
<p>6.7 <a href="#head6.7">Ajout de scripts pour démarrer ou supprimer un service au démarrage</a></p>
<ul>
<li><a href="#head6.7.1">Pour <code>jupyterhub</code></a></li>
<li><a href="#head6.7.2">Pour <code>vncserver</code></a></li>
<li><a href="#head6.7.3">Pour <code>weewx</code></a></li>
<li><a href="#head6.7.4">Pour <code>domoticz</code></a></li>
</ul>
<p>6.8 <a href="#head6.8">Ajout des cahiers de programmes pour apprendre/enseigner la programmation</a></p>
<p>6.9 <a href="#head6.9">Ajout d'un media-center</a></p>
<p>6.10 <a href="#head6.10">Image sans interface graphique (type serveur) pour le pilotage de la station météorologique et le partage de données</a> </p>
<ul>
<li><a href="#head6.10.1">Configuration du logiciel de pilotage de stations météorologiques</a></li>
<li><a href="#head6.10.2">Ajout des cadrans interactifs</a></li>
<li><a href="#head6.10.3">Installation et configuration du pare-feu</a></li>
<li><a href="#head6.10.4">Installation et configuration de la base de données relationnelle mariadb</a></li>
<li><a href="#head6.10.5">Mise en place d'un serveur web</a></li>
<li><a href="#head6.10.7"> Mise en place d'une connexion WIFI</a></li>
</ul>
</li>
<li>
<p><a href="#head7">Propagation des images</a></p>
<ul>
<li><a href="#head7.1">Organisation des services au démarrage</a></li>
<li><a href="#head7.2">Clonage et mise à disposition</a></li>
</ul>
</li>
</ol>
<hr>
<h3><em>Téléchargements</em></h3>
<ol>
<li><a href="https://github.com/drtyhlpr/rpi23-gen-image">rpi23-gen-image</a></li>
<li><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/files/tip/">g_vidal rpi23-gen-image</a></li>
<li><a href="http://weewx.com/downloads/released_versions/python3-weewx_4.2.0-1_all.deb">logiciel weewx</a></li>
<li><a href="https://media.tremplin.ens-lyon.fr/isoImages/RaspBerry/">Images téléchargeables raspberryPi du projet Tremplin</a></li>
<li>
<ol>
<li><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/files/1bdc606a42030af4751b66f2ab1e00d849ad1350/templates/raspife2-buster_19-09-08">modèle de création d'image raspberry Pi 2 raspife2-buster_19-09-08</a></li>
</ol>
</li>
</ol>
<hr>
<h1><a id="head1"> 1.</a> Stratégie adoptée</h1>
<p>Lors du développement du projet "Météo et Climat tremplin pour l'enseignement des sciences et dès que l'utilisation d'objets connectés (Raspberry Pi Odroïd Intel edison, Intel joule) a été entérinée, des images ont été construites au coup par coup pour soutenir les fonctions attribuées à chacun des objets connectés. Cet article est le premier d'une série de 3 présentant la création de l'image et les premiers ajustements pour la rendre aisément opérationnelle. Le second décrit les aménagements faits pour avoir des services opérationnels y compris les outils pour la météorologie et le climat. Le troisième décrit les adaptations particulières pour le projet "Tremplin des Sciences".</p>
<ul>
<li><a href="http://blog.tremplin.ens-lyon.fr/GerardVidal/Pi3W_Stretch_install.html"> Construire et installer un système d'exploitation GNU/linux Debian Stretch sur une Raspberry Pi 3 ou Pi3 B+ pour piloter une station météorologique</a></li>
<li><a href="http://blog.tremplin.ens-lyon.fr/GerardVidal/Use_Pi3W_Stretch.html">Piloter une station météorologique avec une Raspberry Pi3 (image ENS-IFÈ) et participer au réseau OpenMetEdu (optionnel)</a></li>
<li><a href="http://blog.climatetmeteo.fr/GerardVidal/Raspberry%20Pi23Buster_install-en.html">A Debian Buster image for Raspberry Pi 3 to learn or teach coding with JupyterHub (python, JS), Snap!BYOB (bloc-programming), MRAA and UPM (maker world)</a></li>
<li><a href="http://blog.tremplin.ens-lyon.fr/GerardVidal/Raspberry%20Pi23Stretch_install.html">Installer un Système d'exploitation linux Debian Stretch sur une Raspberry Pi 2 ou 3 avec les outils Weewx, JupyterHub, MRAA et UPM </a></li>
</ul>
<p>La procédure décrite ci-dessous a été réalisée à partir d'une machine Debian, si on ne dispose pas d'un tel ordinateur il est possible de réaliser ce travail à partir d'une distribution "live" sur une clef USB qui s'installe sur tout ordinateur sans toucher au système d'exploitation et aux données existantes. Pour conserver l'état du système ainsi créé on peut utiliser une distribution "persistante" voir <a href="http://blog.tremplin.ens-lyon.fr/GerardVidal/UsbKey_Pi3W_Config.html">Créer et utiliser une clef USB GNU/linux bootable persistante pour configurer une raspberry Pi</a>.</p>
<h2><a name="head1.1">1.1</a> Trois phases de construction</h2>
<p>La construction d'une image se passe en trois phases:</p>
<ul>
<li>Tout d'abord construction d'une image minimale en utilisant le script automatisé de <a href="https://github.com/drtyhlpr">drtyhlpr</a> disponible sur le dépôt <a href="http://github.com">github</a> <a href="https://github.com/drtyhlpr/rpi23-gen-image">rpi23-gen-image</a> et sur le <a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/files/tip/">dépôt tremplin des sciences</a>,</li>
<li>ensuite réalisation d'un certain nombre d'ajustemts génériques aux quatre images dont une partie est réalisable directement sur la micro-SD l'autre devant être exécutée lors du premier démarrage</li>
<li>enfin modifications adaptées à chacune des fonctions attendues pour la raspberry Pi considérée</li>
</ul>
<h3><a name="head1.1.1.1"> 1.1.1</a> Construction de l'image avec le script automatisé "rpi23genimage" et premiers services <a href="#head2">chap. 2</a></h3>
<p>Cette opération est totalement automatisée grâce au travail piloté par <code>drtyhlpr</code>sur <code>github</code>, le développement de ces scripts a besoin de développeurs et de testeurs n'hésitez pas à contribuer à ce travail si vous le pouvez. L'image créée est minimale bien que de nombreuses options permettent déjà de la profiler (cf. plus bas).</p>
<h3><a name="head1.1.2">1.1.2</a> Ajustements manuels génériques <a href="#head3">chap. 3</a></h3>
<p>Dans cette partie du travail sont réalisés tous les ajustements possibles après le premier démarrage de la raspberry avec sa nouvelle image. Cela permet entre autres de prendre en compte le support physique utilisé, l'environnement opérationnel de la future raspberry et quelques fonctionnalités qui ne peuvent être ajoutées lors de la création. L'image fournie contient un ensemble d'usagers et de services préinstallés.</p>
<h3><a name="head1.1.3">1.1.3</a> Configuration particulière avancée <a href="#head4">chap. 4</a></h3>
<p>Les Raspberries Pi sont d'admirables petites machines mais leur puissance reste limitée et il est judicieux de les cantonner à un nombre limité de fonctions en supprimant autant que possible tout ce qui est superflu. par exemple l'image qui pilote la station n'a pas besoin d'écran et toute l'infrastructure d'affichage graphique est supprimée ce qui améliore grandement les performances de pilotage de la station et de manipulation des données.</p>
<h2><a name="head1.2">1.2</a> Quatre générations de RaspberryPi (rpi2-rpi3-rpi3B+-rpi4), deux familles d'images (codage-station météo) et deux distributions (buster-bullseye)</h2>
<p>Au cours du projet nous avons manipulé des raspbrries Pi-2, Pi-3, Pi-3B+ et pi4 ; afin de conserver une compatibilité avec les premiers matériels installés des images pour raspberries Pi 2, 3, 3B+ sont proposées. Dans la mesure où plus aucune raspberry pi 2 ne pilote de station météorologique il n'y a pas d'image de raspberry Pi2 pour le pilotage d'une station météorologique avec <code>weewx</code>. S'il existe un besoin on pourra s'inspirer de la construction de la raspberry Pi W3 en changeant les paramètres liés au modèle et au réseau (On ne peut pas garantir que des problèmes de compilation n'apparaissent pas). </p>
<h2><a name="head1.3"> </a> 1.3 Mode de classement et moyen de retrouver une information</h2>
<p>Le nom des images de raspberries crées est formé en suivant la règle suivante :</p>
<ul>
<li>date AAAA-MM-JJ "-"</li>
<li>modèle rpi2, rpi3, rpi3P (3 BPlus) ou rpi4</li>
<li>fonction W pour la raspberry <code>weewx</code> de pilotage de la station météo et rien pour les autres</li>
<li>distribution de debian utilisée <code>buster</code> ou <code>bullseye</code> (des versions <code>stretch</code> existent dans les archives)</li>
<li>pour les rpi4 32 ou 64 </li>
<li>extension : type de fichier img ou bmap (éventuellement compression xz)</li>
</ul>
<p>Ainsi l'mage du 22 octobre 2019 buster pi3 pour la programmation sera nommée : <code>2019-10-22-rpi3-buster.img.xz</code>. L'image pour raspberry4 64 bits faite le 10/02/2020 avec la distribution buster a pour nom : <code>2020-02-10-rpi4-buster-64.img</code></p>
<h1><a name="head2"> </a> 2. Construction de l'image avec le script "rpi23genimage"</h1>
<p>Le Travail reporté ci-dessous a été effectivement réalisé à partir d'un ordinateur linux. Windows a finalement intégré la possibilité d'utiliser des commandes linux unix (voir l'un des nombreux tutoriaux sur comment installer le bash dans windows10) et l'unix de MacOs est suffisamment proche pour que beaucoup de choses soient faisables de puis ces plateformes. Toutefois, une solution élégante consiste à utiliser une <code>clef bootable Linux live</code> dont la description est <a href="https://blog.tremplin.ens-lyon.fr/GerardVidal/UsbKey_Pi3W_Config.html">ici</a> et d'appliquer les commandes proposées, cela peut s'avérer extrêmemnt utile pour la copie de l'image sur une micr-SD.</p>
<p>Toutes les constructions d'images ci-dessous s'appuient sur le travail de <a href="https://github.com/drtyhlpr">drtyhlpr</a> disponible sur le dépôt <a href="http://github.com">github</a> <a href="https://github.com/drtyhlpr/rpi23-gen-image">rpi23-gen-image</a>. Le dépôt <a href="http://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage">g_vidal rpi23-gen-image</a> est un clône de <code>rpi23-gen-image</code> maintenu à jour autant que possible auquel sont ajoutés quelques fichiers décrits dans les chapitres suivants. Des différences peuvent exister entre les versions commentées ici et les versions disponibles en ligne lorsque des modifications doivent être effectuées pour respecter l'évolution de Debian, la version en ligne sur <code>github</code> est à priori et sauf indication contraire toujours la plus à jour (pour des raisons de sécurité les mots de passe et les indications de chemins sont remplacées par des <code>*****</code>).</p>
<p>Le travail s'effectue dans la hiérarchie de fichiers obtenue par clonage du dépôt <a href="http://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage">g_vidal rpi23-gen-image</a>. </p>
<div class="highlight"><pre><span></span>ls -R
.:
bootstrap.d/ functions.sh LICENSE README-CN.md
files/ packages/ README.md rpi23-gen-image.sh* templates/
./bootstrap.d:
<span class="m">10</span>-bootstrap.sh <span class="m">13</span>-kernel.sh <span class="m">30</span>-security.sh <span class="m">42</span>-fbturbo.sh <span class="m">99</span>-reduce.sh
<span class="m">11</span>-apt.sh <span class="m">20</span>-networking.sh <span class="m">31</span>-logging.sh <span class="m">14</span>-fstab.sh <span class="m">32</span>-sshd.sh
<span class="m">43</span>-videocore.sh <span class="m">12</span>-locale.sh <span class="m">15</span>-rpi-config.sh <span class="m">21</span>-firewall.sh <span class="m">41</span>-uboot.sh
<span class="m">50</span>-firstboot.sh
./files:
apt/ dpkg/ firstboot/ iptables/ modules/ network/ xorg/
boot/ etc/ initramfs/ locales/ mount/ sysctl.d/
./files/apt:
02nocache 03compress 04norecommends 10proxy flash-kernel sources.list
./files/boot:
config.txt uboot.mkimage
./files/dpkg:
01nodoc
./files/etc:
<span class="m">99</span>-com.rules rc.local*
./files/firstboot:
<span class="m">10</span>-begin.sh <span class="m">23</span>-regenerate-initramfs.sh <span class="m">26</span>-config-ifnames.sh
<span class="m">21</span>-generate-ssh-keys.sh <span class="m">24</span>-generate-machineid.sh <span class="m">99</span>-finish.sh
<span class="m">22</span>-expandroot.sh <span class="m">25</span>-create-resolv-symlink.sh
./files/initramfs:
expand_encrypted_rootfs expand-premount* expand-tools*
./files/iptables:
flush-ip6tables.sh ip6tables.rules iptables.rules nftables6.rules
flush-iptables.sh ip6tables.service iptables.service nftables.rules
./files/locales:
locale
./files/modules:
raspi-blacklist.conf rpi2.conf
./files/mount:
crypttab fstab
./files/network:
eth.network host.conf hostname hosts interfaces wlan.network
./files/sysctl.d:
<span class="m">81</span>-rpi-vm.conf <span class="m">82</span>-rpi-net-hardening.conf <span class="m">83</span>-rpi-printk.conf
./files/xorg:
<span class="m">99</span>-fbturbo.conf
./packages:
python3-weewx_4.2.0-1_all.deb
./templates:
makebuster.log raspife3-stretch rpi0stretch
rpi1buster raspife2-stretch rpi1Pbuster
rpi1Pstretch raspife3-buster rpi1stretch
rpi2buster rpi2stretch rpi3buster
rpi3Pbuster rpi3Pstretch rpi3stretch
rpi3-stretch-arm64-4.14.y raspife3-buster-arm64 raspife3-jessie
rpi0buster
</pre></div>
<p>Pour construire les images on met en place le noyau linux X.YY proposé par le dépôt officiel <a href="https://github.com/raspberrypi/linux">RaspberrryPi/linux</a>. Au moment de la rédaction on utilise le noyau 4.19 pour <code>buster</code> et 5.4 pour <code>bullseye</code>.</p>
<p>Les 5 parties ci-dessous sont totalement <strong>indépendantes</strong>, le lecteur peut directement se reporter à la construction de l'image souhaitée. Dans tous les cas l'utilisateur privilégié initial s'appelle <code>ens-ife</code> dans les fichiers de configuration et on fournit une clef ssh pour éviter l'utilisation de mots de passe (un mot de passe de secours est toutefois prévu dans la configuration). L'utilisateur privilégié <code>ens-ife</code> est réservé au contructeur de l'image, un autre utilisateur privilégié <code>localadm</code>est créé pour fournir à un tiers installateur de l'image les droits d'administration. les exemples fournis ont été effectivement utilisés pour construire des images <strong>MAIS</strong> l'outil <code>rpi23-gen-image</code> est vivant et la communauté active, des modifications légères peuvent s'avérer nécessaires entre deux mises à jour du blog. </p>
<h2><a name="head2.1"> </a> 2.1 Raspberry Pi0 Buster</h2>
<p>Cette image a été générée en utilisant le fichier template <code>raspife0W-buster_21-01-08</code>
et le script standard <code>rpi23-gen-image.sh</code>. Ce travail étant réalisé dans le cadre
du projet <strong>Météo Climat Tremplin pour l'enseignement des Sciences</strong><br>
le package <a href="http://weewx.com/downloads/">weewx</a> de gestion de stations météorologiques
est introduit par défaut; il permet d'illustrer l'incorporation de paquets debian
non présents dans les dépôts par défaut.</p>
<p>Les instructions sont lancées depuis la racine du dépôt listé ci-dessus.</p>
<div class="highlight"><pre><span></span>sudo rm -r /data/RpiGenImage/Images/buster/build
sudo <span class="nv">CONFIG_TEMPLATE</span><span class="o">=</span>raspife0W-buster_21-01-08 ./rpi23-gen-image.sh
</pre></div>
<p>Les particularités liées au processeur <code>armel6</code> sont précisées dans le texte lorsque nécessaire.</p>
<h2><a name="head2.2"> </a> 2.2 Raspberry Pi1 Buster</h2>
<p>Cette image a été générée en utilisant le fichier template <code>raspife2-buster_20-11-29</code> et
le script standard <code>rpi23-gen-image.sh</code>. Ce travail étant réalisé dans le cadre du
projet <strong>Météo Climat Tremplin pour l'enseignement des Sciences</strong><br>
le package <a href="http://weewx.com/downloads/">weewx</a> de gestion de stations météorologiques
est introduit par défaut; il permet d'illustrer l'incorporation de paquets debian non présents dans les dépôts par défaut.</p>
<p>Les instructions sont lancées depuis la racine du dépôt listé ci-dessus.</p>
<div class="highlight"><pre><span></span>sudo rm -r /data/RpiGenImage/Images/buster/build
sudo <span class="nv">CONFIG_TEMPLATE</span><span class="o">=</span>raspife2 ./rpi23-gen-image.sh
</pre></div>
<h2><a name="head2.3"> </a> 2.3 Raspberry Pi2 Buster</h2>
<p>Cette image a été générée en utilisant le fichier template <code>raspife2-buster_19-09-08</code> et le script standard <code>rpi23-gen-image.sh</code>. Ce travail étant réalisé dans le cadre du projet <strong>Météo Climat Tremplin pour l'enseignement des Sciences</strong> le package <a href="http://weewx.com/downloads/">weewx</a> de gestion de stations météorologiques est introduit par défaut; il permet d'illustrer l'incorporation de paquets debian non présents dans les dépôts par défaut.</p>
<p>Les instructions sont lancées depuis la racine du dépôt listé ci-dessus.</p>
<div class="highlight"><pre><span></span>sudo rm -r /data/RpiGenImage/Images/buster/build
sudo <span class="nv">CONFIG_TEMPLATE</span><span class="o">=</span>raspife2-stretch ./rpi23-gen-image.sh
</pre></div>
<p>Le fichier <code>raspife2-buster_19-09-08</code> se trouve dans le répertoire templates et contient les informations présentées ci-dessous. Se reporter à la documentation de <code>rpi23-gen-image</code> pour avoir des précisions sur les paramètres utilisés. Ces informations sont celles qui ont été extraites du fichier de configuration qui a permis de produire l'image proposée au téléchargement. Les paquets listés dans <code>APT_INCLUDES_LATE=""</code> sont ceux qui sont ajoutés à la construction par défaut pour les besoins du projet. On y trouve les outils de compilation, le langage python et python3, les ressources pour l'affaichage graphique et la manipulation de graphiques et vidéos, firefox et quelques utilitaires ainsi que des paquets ajoutés au coup par coup au cours du développement du projet. </p>
<p><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/files/1bdc606a42030af4751b66f2ab1e00d849ad1350/templates/raspife2-buster_19-09-08">télécharger le fichier raspife2-buster_19-09-08</a></p>
<p>La trace de l'exécution apparait à l'écran la durée dépend de la puissance de la machine utilisée et peut atteindre une heure ou plus. Lorsque tout se passe bien l'exécution s'achève par les messages suivants :</p>
<div class="highlight"><pre><span></span>killing processes using mount point ...
removing temporary mount points ...
/pathTo/Images/debianVersion/isoImageName.img <span class="o">(</span>size in M<span class="o">)</span> : successfully created
</pre></div>
<p>On dispose alors de deux fichiers :
* <code>isoImage.bmap</code>
* <code>isoImage.img</code></p>
<p>qui peuvent être directement utilisés ou être enrichis comme proposé dans les chapitres suivants. Dans les deux cas il est nécessaire de copier cette image sur une micro SD en utilisant la commande <code>bmaptool copy</code> (installer le paquet bmaptools si nécessaire).</p>
<h2><a name="head2.4"> </a> 2.4 Raspberry Pi3 Buster</h2>
<p>Cette image a été générée en utilisant le fichier template <code>raspife3-buster_20-11-21</code> et le script standard <code>rpi23-gen-image.sh</code>. ce travail étant réalisé dans le cadre du projet <strong>Météo Climat Tremplin pour l'enseignement des Sciences</strong> le package <a href="http://weewx.com/downloads/">weewx</a> de gestion de stations météorologiques est introduit par défaut; il permet d'illustrer l'incorporation de paquets debian non présents dans les dépôts par défaut.</p>
<p>Les instructions sont lancées depuis la racine du dépôt listé ci-dessus.</p>
<div class="highlight"><pre><span></span>sudo rm -r /data/RpiGenImage/Images/stretch/build
sudo <span class="nv">CONFIG_TEMPLATE</span><span class="o">=</span>raspife3-buster_20-11-01 ./rpi23-gen-image.sh
</pre></div>
<p>Le fichier <code>raspife3-buster_20-11-21</code> est homologue de <code>raspife2-buster_19-09-08</code> avec en plus la gestion du WIFI intégré. Il se trouve dans le répertoire templates et contient les informations présentées ci-dessous. Se reporter à la documentation de <code>rpi23-gen-image</code> pour avoir des précisions sur les paramètres utilisés. Ces informations sont celles qui ont été extraites du fichier de configuration qui a permis de produire l'image proposée au téléchargement. Les paquets listés dans <code>APT_INCLUDES_LATE=""</code> sont ceux qui sont ajoutés à la construction par défaut pour les besoins du projet. On y trouve les outils de compilation, le langage python et python3, les ressources pour l'affaichage graphique et la manipulation de graphiques et vidéos, firefox et quelques utilitaires ainsi que des paquets ajoutés au coup par coup au cours du développement du projet. L'installation de java s'est mal passée elle a été supprimée mais laissée dans le fichier de configuration au cas où le problème serait résolu dans un futur proche.</p>
<p><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/download/3695b857462e1b9d62707d8e170a45672841a0bd/templates/raspife3-buster_20-11-01">télécharger le fichier raspife3-buster_20-11-01</a></p>
<p>La trace de l'exécution apparait à l'écran la durée dépend de la puissance de la machine utilisée et peut atteindre une heure ou plus. Lorsque tout se passe bien l'exécution s'achève par les messages suivants :</p>
<div class="highlight"><pre><span></span>killing processes using mount point ...
removing temporary mount points ...
/pathTo/Images/debianVersion/isoImageName.img <span class="o">(</span>size in M<span class="o">)</span> : successfully created
</pre></div>
<p>On dispose alors de deux fichiers :
* <code>raspife3-buster_20-11-01.bmap</code>
* <code>raspife3-buster_20-11-01.img</code></p>
<p>qui peuvent être directement utilisés ou être enrichis comme proposé dans les chapitres suivants. Dans les deux cas il est nécessaire pour poursuivre de copier cette image sur une micro-SD en utilisant la commande <code>bmaptool copy</code> (installer le paquet bmaptools si nécessaire).</p>
<h2><a name="head2.5"> </a> 2.5 Raspberry Pi3B+ Buster</h2>
<p>Cette image a été générée en utilisant le fichier template <code>raspife3P-buster_20-11-01</code> et le script standard <code>rpi23-gen-image.sh</code>. ce travail étant réalisé dans le cadre du projet <strong>Météo Climat Tremplin pour l'enseignement des Sciences</strong> le package <a href="http://weewx.com/downloads/">weewx</a> de gestion de stations météorologiques est introduit par défaut; il permet d'illustrer l'incorporation de paquets debian non présents dans les dépôts par défaut. Cette image a été créée pour respecter les contraintes de securité d'un ordinateur en milieu scolaire et d'une machine de service. Elle dispose d'un serveur graphique, elle obtient une IP via le DHCP de l'établissement. Au delà de ces particularités structurelles, la configuration qui sera appliquée ultérieurement permet d'enseigner la programmation avec la météo ou tout autre capteurs ou effecteurs.</p>
<p>Les instructions sont lancées depuis la racine du dépôt listé ci-dessus.</p>
<div class="highlight"><pre><span></span>sudo rm -r /data/RpiGenImage/Images/stretch/build
sudo <span class="nv">CONFIG_TEMPLATE</span><span class="o">=</span>rraspife3P-buster_20-11-01 ./rpi23-gen-image.sh
</pre></div>
<p>Les instructions sont lancées depuis la racine du dépôt listé ci-dessus.</p>
<p>Le fichier <code>raspife3P-buster_20-11-01</code> est fourni par le site de <a href="https://github.com/drtyhlpr/rpi23-gen-image">drtyhlpr</a> puis modifié. Il se trouve dans le répertoire templates et contient les informations présentées ci-dessous. Se reporter à la documentation de <code>rpi23-gen-image</code> pour avoir des précisions sur les paramètres utilisés. Ces informations sont celles qui ont été extraites du fichier de configuration qui a permis de produire l'image proposée au téléchargement. Les paquets listés dans <code>APT_INCLUDES=""</code> sont ceux qui sont ajoutés à la construction par défaut pour les besoins du projet. On y trouve les outils de compilation, le langage python et python3, les ressources pour l'affaichage graphique et la manipulation de graphiques et vidéos, firefox et quelques utilitaires ainsi que des paquets ajoutés au coup par coup au cours du développement du projet.</p>
<p><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/download/3695b857462e1b9d62707d8e170a45672841a0bd/templates/raspife3P-buster_20-11-01">télécharger le fichier raspife3P-buster_20-11-01</a></p>
<p>La trace de l'exécution apparait à l'écran la durée dépend de la puissance de la machine utilisée et peut atteindre une heure ou plus. Lorsque tout se passe bien l'exécution s'achève par les messages suivants :</p>
<div class="highlight"><pre><span></span>killing processes using mount point ...
removing temporary mount points ...
/pathTo/Images/debianVersion/isoImageName.img <span class="o">(</span>size in M<span class="o">)</span> : successfully created
</pre></div>
<p>On dispose alors de deux fichiers :
* <code>raspife3P-buster_20-11-01.bmap</code>
* <code>raspife3P-buster_20-11-01.img</code></p>
<p>qui peuvent être directement utilisés ou être enrichis comme proposé dans les chapitres suivants. Dans les deux cas il est nécessaire pour poursuivre de copier cette image sur une micro-SD en utilisant la commande <code>bmaptool copy</code> (installer le paquet <code>bmap-tools</code> si nécessaire).</p>
<h2><a name="head2.6"> </a> 2.6 Raspberry Pi3 Buster sans serveur graphique et avec IP fixe</h2>
<p>Cette image a été générée en utilisant le fichier template <code>raspife3W-buster_19-10-20</code> et le script standard <code>rpi23-gen-image.sh</code>. ce travail étant réalisé dans le cadre du projet <strong>Météo Climat Tremplin pour l'enseignement des Sciences</strong> le package <a href="http://weewx.com/downloads/">weewx</a> de gestion de stations météorologiques est introduit par défaut; il permet d'illustrer l'incorporation de paquets debian non présents dans les dépôts par défaut. Cette image a été créée pour respecter les contraintes de securité d'un ordinateur en milieu scolaire et d'une machine de service. Elle ne dispose pas de serveur graphique, elle possède une IP fixe pré-attribuée au sein de l'établissement. Au delà de ces particularités structurelles, la configuration qui sera appliquée ultérieurement sera aussi sensiblement différente. Le "W" ajouté au nom est tiré du nom du logiciel <code>weewx</code> pour signaler que la fonction principale est dédiée à la gestion d'une station météorologique.</p>
<p>Les instructions sont lancées depuis la racine du dépôt listé ci-dessus.</p>
<div class="highlight"><pre><span></span>sudo rm -r /data/RpiGenImage/Images/stretch/build
sudo <span class="nv">CONFIG_TEMPLATE</span><span class="o">=</span>raspife3W-buster_19-10-20 ./rpi23-gen-image.sh
</pre></div>
<p>Le fichier <code>raspife3W-buster_19-10-20</code> est homologue de <code>raspife3-buster_19-09-12</code> et de <code>raspife3P-buster_19-09-12</code> <strong>sans gestion du WIFI intégré</strong>, la Raspberry étant conçue pour se comporter "comme un serveur". Il se trouve dans le répertoire templates et contient les informations présentées ci-dessous. Se reporter à la documentation de <code>rpi23-gen-image</code> pour avoir des précisions sur les paramètres utilisés. Ces informations sont celles qui ont été extraites du fichier de configuration qui a permis de produire l'image proposée au téléchargement. Les paquets listés dans <code>APT_INCLUDES_LATE=""</code> sont ceux qui sont ajoutés à la construction par défaut pour les besoins du projet. On y trouve les outils de compilation, le langage python et python3 et quelques utilitaires ainsi que des paquets ajoutés au coup par coup au cours du développement du projet. </p>
<p>Pour que l'image soit construite convenablement <strong>il est impératif</strong> que les paramètres <code>NET_ADDRESS</code>, <code>NET_GATEWAY</code> et <code>NET_DNS_1</code> soient correctement configurés. Ils pourront toujours modifiés ou anonymisés plus tard si besoin. L'image ainsi constituée (avec des adresses IP fixes en clair) démarre et se connecte au réseau correspondant aux paramètres entrés (et à celui-là seulement) sans problème.</p>
<p><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/files/1bdc606a42030af4751b66f2ab1e00d849ad1350/templates/raspife3W-buster_19-10-20">télécharger le fichier raspife3W-buster_19-10-20</a></p>
<p>La trace de l'exécution apparait à l'écran, la durée dépend de la puissance de la machine utilisée et peut atteindre une heure ou plus. Lorsque tout se passe bien l'exécution s'achève par les messages suivants :</p>
<div class="highlight"><pre><span></span>killing processes using mount point ...
removing temporary mount points ...
/pathTo/Images/debianVersion/isoImageName.img <span class="o">(</span>size in M<span class="o">)</span> : successfully created
</pre></div>
<p>On dispose alors de deux fichiers :
* <code>raspife3W-buster_19-10-20.bmap</code>
* <code>raspife3W-buster_19-10-20.img</code></p>
<p>qui peuvent être directement utilisés ou être enrichis comme proposé dans les chapitres suivants. Dans les deux cas il est nécessaire pour poursuivre de copier cette image sur une micro-SD en utilisant la commande <code>bmaptool copy</code> (installer le paquet bmaptools si nécessaire).</p>
<h2><a name="head2.7"> </a> 2.7 Raspberry Pi3 BullsEye</h2>
<p>Cette image a été générée en utilisant le fichier template <code>raspife3-bullseye_20-11-19</code> et le script standard <code>rpi23-gen-image.sh</code>. ce travail étant réalisé dans le cadre du projet <strong>Météo Climat Tremplin pour l'enseignement des Sciences</strong>. L'utilisation de la distribution buster permet d'assurer une veille sur l'évolution de la distribution Debian et anticiper les effets des changements de certains paquets sur le projet. Cette est image n'est pas recommandée à un utilisateur ordinaire mais fera certainement le bonheur d'un utilisateur avancé à l'affut de dernières mises à jour, cette image présente tous les avantages et inconvénients d'une distribution "debian testing". Le package <a href="http://weewx.com/downloads/">weewx</a> de gestion de stations météorologiques est introduit par défaut; il permet d'illustrer l'incorporation de paquets debian non présents dans les dépôts par défaut. Quelques autre paquets supplémentaires ont été ajoutés et certains paquets présents dans la version stretch ont du être retirés du fait d'incompatibilités avec la version deu noyau choisi. Comme son nom l'indique la version est "testing" ce qui occasionne des instabilités temporaires au gré des contributions des auteurs des paquets debian, rien d'insurmontable mais nécessité d'un certain savoir-faire...</p>
<p>Les instructions sont lancées depuis la racine du dépôt listé ci-dessus.</p>
<div class="highlight"><pre><span></span>sudo rm -r /data/RpiGenImage/Images/buster/build
sudo <span class="nv">CONFIG_TEMPLATE</span><span class="o">=</span>raspife3-bullseye_20-11-19 ./rpi23-gen-image.sh
</pre></div>
<p>Le fichier <code>raspife3-bullseye_20-11-19</code> dérive de <code>raspife3-bullseye_20-11-19</code> mais en diffère sur un certain nombre de points assurant la cohérence entre la procédure-le noyau-le choix effectués. Il se trouve dans le répertoire <code>templates</code> et contient les informations présentées ci-dessous. Se reporter à la documentation de <code>rpi23-gen-image</code> pour avoir des précisions sur les paramètres utilisés. Ces informations sont celles qui ont été extraites du fichier de configuration qui a permis de produire l'image proposée au téléchargement. Les paquets listés dans <code>APT_INCLUDES_LATE=""</code> sont ceux qui sont ajoutés à la construction par défaut pour les besoins du projet. On y trouve les outils de compilation, le langage python et python3, les ressources pour l'affaichage graphique et la manipulation de graphiques et vidéos, firefox et quelques utilitaires ainsi que des paquets ajoutés au coup par coup au cours du développement du projet.</p>
<p><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/files/1bdc606a42030af4751b66f2ab1e00d849ad1350/templates/raspife3-bullseye_19-11-09">télécharger le fichier raspife3-bullseye_19-11-09</a></p>
<p>La trace de l'exécution apparait à l'écran, la durée dépend de la puissance de la machine utilisée et peut atteindre une heure ou plus. Lorsque tout se passe bien l'exécution s'achève par les messages suivants :</p>
<div class="highlight"><pre><span></span>killing processes using mount point ...
removing temporary mount points ...
/data/RpiGenImage/Images/buster/rpi3-buster.img <span class="o">(</span>4390M<span class="o">)</span> : successfully created
</pre></div>
<p>On dispose alors de deux fichiers :
* <code>rpi3-buster.bmap</code>
* <code>rpi3-buster.img</code></p>
<p>qui peuvent être directement utilisés ou être enrichis comme proposé dans les chapitres suivants. Dans les deux cas il est nécessaire pour poursuivre de copier cette image sur une micro-SD en utilisant la commande <code>bmaptool copy</code> (installer le paquet bmaptools si nécessaire).</p>
<h2><a name="head2.8"> </a> 2.8 Raspberry Pi4 Buster</h2>
<p>Cette image a été générée en utilisant le fichier template <code>raspife4-buster_20-02-04</code> et le script standard <code>rpi23-gen-image.sh</code>. ce travail étant réalisé dans le cadre du projet <strong>Météo Climat Tremplin pour l'enseignement des Sciences</strong>. L'utilisation de la distribution buster permet d'assurer une veille sur l'évolution de la distribution Debian et anticiper les effets des changements de certains paquets sur le projet. Cette est image n'est pas recommandée à un utilisateur ordinaire mais fera certainement le bonheur d'un utilisateur avancé à l'affut de dernières mises à jour, cette image présente tous les avantages et inconvénients d'une distribution "debian testing". Le package <a href="http://weewx.com/downloads/">weewx</a> de gestion de stations météorologiques est introduit par défaut; il permet d'illustrer l'incorporation de paquets debian non présents dans les dépôts par défaut. Quelques autre paquets supplémentaires ont été ajoutés et certains paquets présents dans la version stretch ont du être retirés du fait d'incompatibilités avec la version deu noyau choisi. Comme son nom l'indique la version est "testing" ce qui occasionne des instabilités temporaires au gré des contributions des auteurs des paquets debian, rien d'insurmontable mais nécessité d'un certain savoir-faire...</p>
<p>Les instructions sont lancées depuis la racine du dépôt listé ci-dessus.</p>
<div class="highlight"><pre><span></span>sudo rm -r /data/RpiGenImage/Images/buster/build
sudo <span class="nv">CONFIG_TEMPLATE</span><span class="o">=</span>raspife4-buster_20-11-01 ./rpi23-gen-image.sh
</pre></div>
<p><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/download/3695b857462e1b9d62707d8e170a45672841a0bd/templates/raspife4-buster_20-11-01">télécharger le fichier raspife4-buster_20-11-01</a></p>
<p>La trace de l'exécution apparait à l'écran, la durée dépend de la puissance de la machine utilisée et peut atteindre une heure ou plus. Lorsque tout se passe bien l'exécution s'achève par les messages suivants :</p>
<div class="highlight"><pre><span></span>killing processes using mount point ...
removing temporary mount points ...
/data/RpiGenImage/Images/buster/rpi4-buster.img <span class="o">(</span>4390M<span class="o">)</span> : successfully created
</pre></div>
<p>On dispose alors de deux fichiers :
* <code>rpi4-buster.bmap</code>
* <code>rpi4-buster.img</code></p>
<p>qui peuvent être directement utilisés ou être enrichis comme proposé dans les chapitres suivants. Dans les deux cas il est nécessaire pour poursuivre de copier cette image sur une micro-SD en utilisant la commande <code>bmaptool copy</code> (installer le paquet bmaptools si nécessaire).</p>
<h2><a name="head2.9"> </a> 2.9 Raspberry Pi4 BullsEye</h2>
<p>Cette image a été générée en utilisant le fichier template <code>raspife4-64-bullseye_20-02-04</code> et le script standard <code>rpi23-gen-image.sh</code>. ce travail étant réalisé dans le cadre du projet <strong>Météo Climat Tremplin pour l'enseignement des Sciences</strong>. L'utilisation de la distribution buster permet d'assurer une veille sur l'évolution de la distribution Debian et anticiper les effets des changements de certains paquets sur le projet. Cette est image n'est pas recommandée à un utilisateur ordinaire mais fera certainement le bonheur d'un utilisateur avancé à l'affut de dernières mises à jour, cette image présente tous les avantages et inconvénients d'une distribution "debian testing". Le package <a href="http://weewx.com/downloads/">weewx</a> de gestion de stations météorologiques est introduit par défaut; il permet d'illustrer l'incorporation de paquets debian non présents dans les dépôts par défaut. Quelques autre paquets supplémentaires ont été ajoutés et certains paquets présents dans la version stretch ont du être retirés du fait d'incompatibilités avec la version deu noyau choisi. Comme son nom l'indique la version est "testing" ce qui occasionne des instabilités temporaires au gré des contributions des auteurs des paquets debian, rien d'insurmontable mais nécessité d'un certain savoir-faire...</p>
<p>Les instructions sont lancées depuis la racine du dépôt listé ci-dessus.</p>
<div class="highlight"><pre><span></span>sudo rm -r /data/RpiGenImage/Images/buster/build
sudo <span class="nv">CONFIG_TEMPLATE</span><span class="o">=</span>raspife3-bullseye_19-11-09 ./rpi23-gen-image.sh
</pre></div>
<p>Le fichier <code>raspife3-bullseye_19-11-09</code> dérive de <code>raspife3-buster_19-09-12</code> mais en diffère sur un certain nombre de points assurant la cohérence entre la procédure-le noyau-le choix effectués. Il se trouve dans le répertoire <code>templates</code> et contient les informations présentées ci-dessous. Se reporter à la documentation de <code>rpi23-gen-image</code> pour avoir des précisions sur les paramètres utilisés. Ces informations sont celles qui ont été extraites du fichier de configuration qui a permis de produire l'image proposée au téléchargement. Les paquets listés dans <code>APT_INCLUDES_LATE=""</code> sont ceux qui sont ajoutés à la construction par défaut pour les besoins du projet. On y trouve les outils de compilation, le langage python et python3, les ressources pour l'affaichage graphique et la manipulation de graphiques et vidéos, firefox et quelques utilitaires ainsi que des paquets ajoutés au coup par coup au cours du développement du projet.</p>
<p><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/files/1bdc606a42030af4751b66f2ab1e00d849ad1350/templates/raspife3-bullseye_19-11-09">télécharger le fichier raspife3-bullseye_19-11-09</a></p>
<p>La trace de l'exécution apparait à l'écran, la durée dépend de la puissance de la machine utilisée et peut atteindre une heure ou plus. Lorsque tout se passe bien l'exécution s'achève par les messages suivants :</p>
<div class="highlight"><pre><span></span>killing processes using mount point ...
removing temporary mount points ...
/data/RpiGenImage/Images/buster/rpi3-buster.img <span class="o">(</span>4390M<span class="o">)</span> : successfully created
</pre></div>
<p>On dispose alors de deux fichiers :
* <code>rpi3-buster.bmap</code>
* <code>rpi3-buster.img</code></p>
<p>qui peuvent être directement utilisés ou être enrichis comme proposé dans les chapitres suivants. Dans les deux cas il est nécessaire pour poursuivre de copier cette image sur une micro-SD en utilisant la commande <code>bmaptool copy</code> (installer le paquet bmaptools si nécessaire).</p>
<h1><a name="head3"> </a> 3. Ajustements manuels génériques</h1>
<p>La micro-SD qui va être utlisée deviendra le disque dur de la Raspberry Pi, les accès à la partie système doivent donc être privilégiés c'est pourquoi dans ce qui suit il est impératif d'agir en tant qu'utilisateur privilégé pour pouvoir faire les modifications. <strong>ATTENTION</strong> à ne pas modifer les fichiers de la machine hôte utilisée pour travailler.... Les conséquences seraient dramatiques !
Le tutoriel qui suit est réalisé en plaçant la microSD vierge dans un connecteur de carte SD, sou linux il est en général affecté à <code>/dev/mmcblkO</code>. Le nom du <code>"device"</code> utilisé pour la micro-SD peut varier en fonction de la configuration de la machine hôte. <strong>ATTENTION</strong> l'utilisation d'adapteurs USB fonctionne mais peut prsenter de légères différences avec les situations décrites ci-dessous, notamment le device sera <code>/dev/sd?</code> (? est une lettre a b c d e f...).</p>
<h2><a name="head3.1"> </a> 3.1 Copie de l'image sur une micro-SD</h2>
<p>Une fois l'image terminée elle est opérationnelle et peut donc être chargée dans une Raspberry Pi qui démarrera avec elle sans interface graphique, le but du travail décrit par ce chapître est de lui fournir une interface graphique ainsi que quelques autres améliorations. On copie d'abord l'image sur une microSD. La création de l'image a fourni un fichier <code>.bmap</code> qui permet d'utiliser l'outil d'accélération de la copie <code>bmaptools</code> si on dispose d'un ordinateur équipé de ce logiciel. Le paquet <code>bmap-tools</code> existe dans la plupart des <code>distributions linux</code>(en cas de distribution très ancienne la version de bmap-tools peut être incompatible avec celle qui a été utilisée pour fabriquer l'image dans ce cas utiliser la procédure standard avec la commande dd). Quelques exemples de copie de l'image sur la <code>carte SD</code>, l'option <code>--bmap</code> est devenue inutile si l'image porte le même nom que la bmap. L'intérêt de bmaptool est de ne pas obliger à décompresser l'image. le nom de support de destination dépend de l'ordinateur utilisé (/dev/mmcblk0 ou /dev/sdg /dev/sdc...) La commande de copie est <strong>irréversible</strong> elle détruit tout ce qui se trouve à l'adresse de destination <em>toujours vérifier que la destination écrite est bien celle qui est souhaitée pour ne pas perdre de données</em>.</p>
<div class="highlight"><pre><span></span>sudo bmaptool copy <span class="m">2020</span>-02-05-rpi3P-buster-32.img.xz /dev/mmcblk0
sudo bmaptool copy <span class="m">2020</span>-02-10-rpi4-buster-64.img.xz /dev/mmcblk0
sudo bmaptool copy <span class="m">2020</span>-02-04-rpi4-bullseye-64.img /dev/mmcblk0
</pre></div>
<p>S'il n'est pas possible d'utiliser bmaptool il est toujours possible dedécompresser l'image et de la recopier avec la commande <code>dd</code> qui ait une copie brute (ne pas utiliser de commande de copie de ficher ou un glisser déposer.</p>
<div class="highlight"><pre><span></span>7z x <span class="m">2020</span>-11-08-rpi4-64-testing.img.xz
dd <span class="k">if</span><span class="o">=</span><span class="m">2020</span>-11-08-rpi4-64-testing.img <span class="nv">of</span><span class="o">=</span>/dev/mmcblk0 <span class="nv">bs</span><span class="o">=</span>4M
</pre></div>
<p>La valeuer de <code>block size (bs)</code> dépend de beaucoup de paramètres hard et soft de l'ordinateur utilisé il peut considérablement modifier le temps de copie, éventuellement le modifier pour améliorer les temps de transfert.</p>
<p>Les images créées n'occupent qu'une partie de l'espace disponible, il faut prévoir de redimensionner la partition pour occuper tout l'espace disponible.</p>
<h2><a name="head3.2"> </a> 3.2 Ajustement de la taille de l'image</h2>
<p>L'image qui vient d'être produite est inscrite sur une partition ajustée à la taille de cette image augmentée de quelques mégaoctets. Afin de pouvoir effectuer les modifications suivantes il est impératif d'agrandir la partition pour accomoder l'espace nécessaire pour stocker les différents fichiers de configuration ainsi que tous les nouveaux programmes nécessaires. Pour y parvenir lorsque l'image a été copiée sur une microSD montée sur <code>/dev/mmcblk0</code> utiliser le commande <code>gparted</code> :</p>
<div class="highlight"><pre><span></span>sudo gparted
</pre></div>
<p>Dans le logiciel gparted :</p>
<ul>
<li>démonter les deux partitions de la SD</li>
<li>redimensionner la seconde partition (ext4)</li>
<li>choisir une dimension compatible avec la SD utilisée ou avec les SD cibles, penser à prendre un peu de marge car toutes les SD ne proposent pas <strong>effectivement</strong> tout l'espace annoncé et par ailleurs ne pas oublier que les constructeurs annoncent les tailles en unités du Système International (puissances de 10) alors que les ordinateurs mesurent les tailles en binaire (pussances de 2) ainsi une SD achetée pour 8 Gio contiendra au mieux 8 x 10 ^ 9 octets = 8 000 000 000 octets et pas les 8Go 8 x 2 ^ 30 = 8 x 1073741824 = 8 589 934 592 que vous souhaiteriez y mettre ! (Dans cet exemple 7.4 Go est voisin de la limite des 8Gio)</li>
</ul>
<p>Même si on pent encore en trouver les microSD de taille <code>8 Go</code> ont quasiment disparu et on peut raisonnablement adopter une taille allant jusqu'à <code>16 Go</code> pour cette image de base sans risque d'empêcher un usager d'utiliser l'image ainsi créée. Suivant les logiciels installés à postériori le système peut dépasser <code>20 Go</code> et suivant les usages mis en oeuvre l'espace requis peut être encore plus important. Toujours choisir une taille de SD adaptée aux besoins envisagés ou choisir une autre solution : par exemple utiliser un disque SSD sur l'USB3 de la raspi4.</p>
<p>Une autre méthode est d'utiliser la commande fdisk en tant que superutilisateur.</p>
<div class="highlight"><pre><span></span>sudo fdisk /dev/mmcblk0
</pre></div>
<ul>
<li>Taper <code>m</code> pour voir la liste des commandes (juste pour information)</li>
<li>
<p>Taper <code>p</code> pour voir la liste des partitions disponibles, normalement il y en deux</p>
<ul>
<li>une FAT : /dev/mmcblk0p1 * 2048 133119 131072 64M c W95 FAT32 (LBA)</li>
<li>une linux : /dev/mmcblk0p2 133120 62517247 62384128 29,8G 83 Linux</li>
</ul>
</li>
<li>
<p>Taper ensuite </p>
<ul>
<li><code>d</code> puis </li>
<li><code>2</code> puis </li>
<li><code>n</code> puis </li>
<li><code>p</code> puis </li>
<li><code>2</code> puis </li>
<li>accepter la valeurs par défaut qui correspondent au premier bloc disponible</li>
<li><code>+10000M</code> afin de produire une image qui puisse fonctionner sur une petite cartes SD</li>
<li><code>N</code> pour "remove signature", </li>
<li>pour finir taper <code>w</code>. </li>
</ul>
</li>
</ul>
<p>puis :</p>
<div class="highlight"><pre><span></span>sudo resize2fs /dev/mmcblk0p2
</pre></div>
<h2><a name="head3.3"> </a> 3.3 Particularités de la Pi0</h2>
<p>La <code>Pi0</code> n'a pas d'interface filaire et il est donc impératif que l'interface WIFI fonctionne <strong>par défaut</strong> au démarrage si on ne souhaite/peut pas se connecter à un dispositif <code>écran/souris/clavier</code>, il y a donc 2 possibilités :
* si on peut connecter la PiZero à un tel dispositif; vérifier que <code>connman</code> et <code>cmst</code> sont installés et utiliser l'interface graphique pour configurer le réseau ou les réseaux wifi qui seront utilisés
* si on ne souhaite pas passer par une interface graphique la configuration est plus délicate car on doit disposer d'informations détaillées sur les propriétés du wifi. Le logiciel <code>connman</code> utilise pour chaque réseau wifi un dossier dans le répertoire <code>/var/lib/connman</code>. Le dossier a pour nom une combinaison du <code>SSID</code> complet du réseau, de l'adresse <code>MAC</code> de l'interface de la raspi et de termes la rendant intelligible elle est de la forme <code>wifi_XX-MAC PiZero-XX_XX-ffull-SSID--réseau-XX_managed_psk</code>. Ce dossier contient deux fichiers <code>data</code> et <code>settings</code>, <code>data</code> est un fichier de contrôle qui peut être reconstruit automatiquement par contre il est impératif de fournir un fichier <code>settings</code> correct,pour le wifi 2.4 GHz. Le <code>SSID</code> contient un nombre hexadécimal à 30 chiffres pour du 5GHz il en contient 8 de plus, le contenu minimal du fichier est précisé sur l'exemple ci-dessous :</p>
<div class="highlight"><pre><span></span><span class="o">[</span>wifi_XXXXXXXXXXXX_yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy_managed_psk<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>WIFI_NETWORK_NAME
<span class="nv">SSID</span><span class="o">=</span>yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
<span class="nv">Frequency</span><span class="o">=</span><span class="m">2447</span>
<span class="nv">Favorite</span><span class="o">=</span><span class="nb">true</span>
<span class="nv">AutoConnect</span><span class="o">=</span><span class="nb">true</span>
<span class="nv">Modified</span><span class="o">=</span><span class="m">2022</span>-01-18T09:27:21.243021Z
<span class="nv">Passphrase</span><span class="o">=</span>passphrase
IPv4.method<span class="o">=</span>dhcp
IPv4.DHCP.LastAddress<span class="o">=</span><span class="c1">###.###.###.###</span>
IPv6.method<span class="o">=</span>auto
IPv6.privacy<span class="o">=</span>disabled
</pre></div>
<p>Pour que l'interface soit démarrée au boot il est aussi nécessaire de modifier la configuration du fichier <code>/etc/connman/main.conf</code> comme ci dessous :</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
sudo mv main.conf main.conf-orig
sudo su
cat > main.conf
<span class="o">[</span>General<span class="o">]</span>
<span class="nv">BackgroundScanning</span> <span class="o">=</span> <span class="nb">true</span>
<span class="nv">DefaultAutoConnectTechnologies</span> <span class="o">=</span> wifi
<span class="nv">PreferredTechnologies</span> <span class="o">=</span> wifi
<span class="nv">AlwaysConnectedTechnologies</span> <span class="o">=</span> wifi
<span class="c1"># ctrl-d</span>
</pre></div>
<ul>
<li>Pour faire plus simple, plus robuste et éviter la configuration de <code>connman</code> il est possible de se ramener à la situation <code>ssystemd-networkd</code> + <code>wpa_supplicant</code> décrite plus loin et proposée par défaut.</li>
</ul>
<p>La PiZero utilise le chipset réseau <code>brcmfmac43430</code> dont le driver est propriétaire il faut impérativement veiller à ce que les fichiers le concernat dans <code>/lib/firmware/brcm</code> ainsi que les le module <code>brcmfmac.ko</code> existent et soient das une version compatible avec le noyau. Il manque parfois simple un lien entre raspberrypi,3-model-b ou cypress/brcm43430... et raspberrypi,model-zero-w car ces deux raspberries utilisent le même chipset mais le lien est parfois oublié lors de la construction par les scripts existants ou alors c'est le nom générique qui est utilisé et pas celui de la PiZero. La liste ci-dessous présente une version maximaliste et opérationnelle du dossiers de dirivers <code>brcm</code></p>
<div class="highlight"><pre><span></span>ls -al /lib/firmware/brcm/*43430* <span class="c1"># limité aux fichiers concernant la PiZero (et la Pi3)</span>
/lib/firmware/brcm/brcmfmac43430-sdio.bin -> ../cypress/cyfmac43430-sdio.bin
/lib/firmware/brcm/brcmfmac43430-sdio.clm_blob -> ../cypress/cyfmac43430-sdio.clm_blob
/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,3-model-b.txt
/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,model-zero-w.bin -> ../cypress/cyfmac43430-sdio.bin
/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,model-zero-w.txt -> brcmfmac43430-sdio.raspberrypi,3-model-b.txt
/lib/firmware/brcm/brcmfmac43430-sdio.txt
<span class="c1"># Modules du noyau</span>
/lib/modules/5.15.13/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko
/lib/modules/5.15.13/kernel/drivers/net/wireless/broadcom/brcm80211/brcmutil/brcmutil.ko
</pre></div>
<p>Un autre point délicat concerne la signature de la base de données <code>regulatory</code> qui doit impérativement être signée comme précisé dans son <code>README</code> :</p>
<div class="highlight"><pre><span></span>If you use a custom kernel built from upstream source, it will only
trust this database <span class="k">if</span> it is signed by the upstream maintainer of
wireless-regdb. To use the upstream database and signature instead of
the Debian version, run:
update-alternatives --set regulatory.db <span class="se">\</span>
/lib/firmware/regulatory.db-upstream
</pre></div>
<p>Sans cette modification le firmware ne se charge pas et pas de réseau ! Cette modification est obligatoire pour <strong>toute</strong> image compilée de raspberry PiZero.</p>
<p><em>Même s'il est possible d'utiliser la Pi0 en terminal ordinaire ses performances sont faibles. Tout ce qui suit fonctionne donc sur écran avec les PiZero mais avec un peu de zénitude...</em></p>
<p>La suite des opérations se déroule à partir de la RaspberryPi "bootée" avec la nouvelle image. </p>
<h2><a name="head3.4"> </a> 3.4 Configuration du réseau</h2>
<p>La construction de base de l'image fournit en théorie une raspberryPi opérationnelle <strong>sur le réseau filaire</strong> sauf pour la PiZero (cf. ci-dessus) ainsi que sur notre réseau wifi éducatif <code>MobileClimatEtMeteo</code> avec comme mot de passe <code>ClimatEtMeteo</code>. Le gestionnaire de réseau interactif installé par défaut est connman (wicd précédemment utilisé est obsolète et ne figure plus dans les paquets de la distribution ordinaire). Si on utilise connman avec son interface graphique en mode <code>clavier/écran/souris</code> après le démarrage de raspberry avec sa nouvelle image il permet de créer une interface pour n'importe quel réseau, se reporter aux tutoriaux correspondants si besoin mais l'interface est très intuitive. Il est possible de changer cet outil en fonction de vos besoins ou compétences (voir plus bas quelques propositions).</p>
<p>On passe aussi en <code>systemd</code>en arrêtant le daemon <code>networking</code> et en veillant à ce que les deux daemons <code>systemd-networkd</code> et <code>systemd-resolved</code> soient lancés au boot. si ce n'est pas le cas effectuer la modification :</p>
<div class="highlight"><pre><span></span>sudo systemctl status networking
sudo systemctl stop networking
sudo systemctl disable networking
sudo systemctl list-unit-files <span class="p">|</span> grep enabled <span class="p">|</span> grep systemd-
</pre></div>
<p>Si besoin</p>
<div class="highlight"><pre><span></span>sudo systemctl <span class="nb">enable</span> systemd-networkd
sudo systemctl <span class="nb">enable</span> systemd-resolved
</pre></div>
<p>Les Raspberries autres que la PiZero prennent automatiquement le <strong>réseau filaire</strong> en DHCP. Si ce n'est pas le cas il y a deux solutions qui peuvent être appliquées avant le démarrage ou après via <code>clavier/écran/souris</code> :</p>
<ul>
<li>soit on affecte une IP fixe et dans ce cas on retrouvera la Raspberry à cette adresse </li>
<li>soit la Raspberry doit obtenir une adresse via le service <code>DHCP</code> du réseau</li>
</ul>
<p>Ces deux solution s'excluent l'une l'autre il faudra choisir.</p>
<h3><a name="head3.4.1"> </a> 3.4.1 Configuration par défaut <code>connman</code></h3>
<p>le logiciel <code>connman</code> fonctionne identiquement pour toutes les raspberries et la solution proposée ci-dessus pour installer un wifi "standard" sur une PiZero peut s'appiquer à toutes les raspberries.</p>
<p>L'utilisation d'un réseau <code>eduroam</code> requiert d'ajouter un fichier <code>myeduroam.config</code> au dossier <code>/var/lib/connman</code> contenant les informations nécesaires à l'accès à eduroam (configurer en fonction de votre réseau) :</p>
<div class="highlight"><pre><span></span><span class="o">[</span>global<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>myeduroam
<span class="o">[</span>service_myeduroam<span class="o">]</span>
<span class="nv">Type</span><span class="o">=</span>wifi
<span class="nv">IPv4</span><span class="o">=</span>dhcp
<span class="nv">IPv6</span><span class="o">=</span>auto
<span class="nv">MAC</span><span class="o">=</span><span class="c1">##:##:##:##:##:##</span>
<span class="nv">Name</span><span class="o">=</span>eduroam
<span class="c1">#Passphrase=$$$$$$$$$$$$$$$$$</span>
<span class="nv">Security</span><span class="o">=</span>ieee8021x
<span class="nv">EAP</span><span class="o">=</span>peap
<span class="c1">#CACertFile=none</span>
<span class="nv">Identity</span><span class="o">=</span>username@myaddress.com
<span class="nv">Phase2</span> <span class="o">=</span> MSCHAPV2
</pre></div>
<p>De même le nom du dossier et le contenu du fichier <code>settings</code> est un peu différent, toujours la <code>Mac</code> de l'interface (hexa à 12 chiffres) et le <code>SSID</code> de l'interface (hexa à 14 chiffres), le terme wifi et les termes "managed_ieee8021x" au lieu de "managed_psk" soit <code>wifi_XXXXXXXXXXXX_YYYYYYYYYYYYYY_managed_ieee8021x</code>.</p>
<div class="highlight"><pre><span></span><span class="o">[</span>wifi_XXXXXXXXXXXX_YYYYYYYYYYYYYY_managed_ieee8021x<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>eduroam
<span class="nv">SSID</span><span class="o">=</span>XXXXXXXXXXXX
<span class="nv">Frequency</span><span class="o">=</span><span class="m">2462</span>
<span class="nv">Favorite</span><span class="o">=</span><span class="nb">true</span>
<span class="nv">AutoConnect</span><span class="o">=</span><span class="nb">true</span>
<span class="nv">Modified</span><span class="o">=</span><span class="m">2021</span>-11-03T13:35:46.238134Z
<span class="nv">Passphrase</span><span class="o">=</span><span class="nv">$$$$$$$$$$$$$$$$$$</span>
IPv4.method<span class="o">=</span>dhcp
IPv4.DHCP.LastAddress<span class="o">=</span><span class="c1">###.###.###.###</span>
IPv6.method<span class="o">=</span>auto
IPv6.privacy<span class="o">=</span>disabled
Config.file<span class="o">=</span>myeduroam
Config.ident<span class="o">=</span>service_myeduroam
</pre></div>
<p>Pour installer un réseau filaire créer un fichier avec le mêmes conventions que pour le wifi mais avec les termes "ethetnet" et "cable" sans <code>SSID</code> de la forme <code>ethernet_XXXXXXXXXXXX_cable</code>. Le fichier `settings prend la forme :</p>
<div class="highlight"><pre><span></span><span class="o">[</span>ethernet_XXXXXXXXXXXX_cable<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>Wired
<span class="nv">AutoConnect</span><span class="o">=</span><span class="nb">true</span>
<span class="nv">Modified</span><span class="o">=</span><span class="m">2021</span>-12-28T15:51:35.232734Z
IPv4.method<span class="o">=</span>dhcp
IPv4.DHCP.LastAddress<span class="o">=</span><span class="c1">###.###.###.###</span>
IPv6.method<span class="o">=</span>auto
IPv6.privacy<span class="o">=</span>disabled
IPv6.DHCP.DUID<span class="o">=</span>0001000yyyyyyyyyXXXXXXXXXXXX
</pre></div>
<p>Si si on ne peut pas disposer d'une connection <code>clavier/écran/souris</code> mais si l'on peut accéder à distance il est possible d'interragir avec le logiciel connman via la commande <code>connmancti</code> voir <code>connmanctl --help</code> pour plus de précisions) sous réserves que le service que le service connman soit activé, vérifier avec <code>sudo systemctl status connman</code>.</p>
<h3><a name="head3.4.2"> </a> 3.4.2 Configuration via <code>systemd-networkd</code> et <code>wpa_spplicant</code></h3>
<p>S'il n'existe pas on va d'abord créer un répertoire qui accueillera les fichiers modifiés de configuration du réseau via systemd-networkd :</p>
<div class="highlight"><pre><span></span>sudo mkdir /etc/systemd/network
</pre></div>
<p>Si le fichier <code>/etc/resolv.conf</code> n'existe pas ou s'il s'agit d'un fichier ordinaire ajouter le lien pour le resolver, <strong>Attention</strong> il est possible que le fichier <code>/run/systemd/resolve/resolv.conf</code> n'existe pas :</p>
<div class="highlight"><pre><span></span>sudo rm /etc/resolv.conf
sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
</pre></div>
<p>Pour éviter d'avoir plusieurs interfaces réseau il est souhaitable de désactiver les interfaces par défaut du système qui peuvent être créées par certaines configurations dans le répertoire <code>/lib/systemd/network</code> :</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /lib/systemd/network
sudo mv <span class="m">10</span>-eth0.network <span class="m">10</span>-eth0.network-orig
sudo mv <span class="m">11</span>-wlan0.network11-wlan0.network-orig
</pre></div>
<p>Il existe probablement une solution plus élégante mais celle-ci fonctionne (merci de toute suggestion).</p>
<p>Vérifier aussi que le répertoire /etc/systemd contient un fichier de configuration <code>resolved.conf</code> et par précaution ajouter le DNS QUad9 et/ou google par défaut (on pourra l'enlever si la Raspberry parvient automatiquement à trouver le DNS du réseau).</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /etc/systemd/
sudo nano resolved.conf
<span class="c1"># This file is part of systemd.</span>
<span class="c1">#</span>
<span class="c1"># systemd is free software; you can redistribute it and/or modify it</span>
<span class="c1"># under the terms of the GNU Lesser General Public License as published by</span>
<span class="c1"># the Free Software Foundation; either version 2.1 of the License, or</span>
<span class="c1"># (at your option) any later version.</span>
<span class="c1">#</span>
<span class="c1"># Entries in this file show the compile time defaults.</span>
<span class="c1"># You can change settings by editing this file.</span>
<span class="c1"># Defaults can be restored by simply deleting this file.</span>
<span class="c1">#</span>
<span class="c1"># See resolved.conf(5) for details</span>
<span class="o">[</span>Resolve<span class="o">]</span>
<span class="c1">#DNS=</span>
<span class="c1">#FallbackDNS=</span>
<span class="c1">#Domains=</span>
<span class="c1">#LLMNR=yes</span>
<span class="c1">#MulticastDNS=yes</span>
<span class="c1">#DNSSEC=allow-downgrade</span>
<span class="c1">#DNSOverTLS=no</span>
<span class="c1">#Cache=yes</span>
<span class="c1">#DNSStubListener=yes</span>
<span class="c1">#ReadEtcHosts=yes</span>
</pre></div>
<p>Pour cela modifier la ligne suivante comme proposé ci-dessous. on utilise le DNS <code>Quad9</code> pour des raisons de protection des données privées.</p>
<div class="highlight"><pre><span></span><span class="nv">DNS</span><span class="o">=</span><span class="m">9</span>.9.9.9
<span class="nv">FallbackDNS</span><span class="o">=</span><span class="m">9</span>.9.9.9
</pre></div>
<h4><a name="head3.4.2.1"> </a> 3.4.2.1 IP fixe</h4>
<p>Ajouter dans le répertoire ci-dessus le fichier <code>50-wired.network</code></p>
<div class="highlight"><pre><span></span>sudo nano /etc/systemd/network/50-wired.network
</pre></div>
<p>Fournir la configuration suivante dans laquelle <code>***.***.***.***</code> représente successivement les adresses du DNS, du réseau qui sera utilisé et de la passerelle. <code>enx*</code> est un contournement <strong>temporaire</strong> permettant de connecter <em>n'importe quelle interface</em> cette valeur devra être changée par la vraie valeur de l'interface dès qu'elle sera connue (voir plus bas) :</p>
<div class="highlight"><pre><span></span><span class="o">[</span>Match<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>enx*
<span class="nv">Host</span><span class="o">=</span>raspwife3
<span class="nv">Virtualization</span><span class="o">=</span>no
<span class="o">[</span>Network<span class="o">]</span>
<span class="nv">DHCP</span><span class="o">=</span>no
<span class="nv">Address</span><span class="o">=</span>***.***.***.***/24
<span class="nv">Gateway</span><span class="o">=</span>***.***.***.***
<span class="nv">DNS</span><span class="o">=</span>***.***.***.***
</pre></div>
<p><strong>Attention</strong> en mettant enplace une telle configuration et en la diffusant il est impératif de réaliser que l'image proposée sera opérationnelle <strong>mais ne pourra pas se connecter au réseau via DHCP car il est désactivé</strong>. Il est donc impératif d'avoir configuré le réseau pour qu'il puisse accueillir la raspberryPi configurée pour l'adresse fixe choisie dans le fichier ci-dessus.</p>
<h4><a name="head3.4.2.2"> </a> 3.4.2.2 IP dynamique fournie par le DHCP</h4>
<p>Pour la Raspberry Pi 3 2 interfaces réseau existent et sont susceptibles de se connecter via dhcp une interface filaire et une interface WIFI. L'interface filaire porte le même nom que dans le cas précédent</p>
<div class="highlight"><pre><span></span>sudo nano /etc/systemd/network/50-wired.network
</pre></div>
<p><code>enx*</code> est un contournement <strong>temporaire</strong> permettant de connecter <em>n'importe quelle interface</em> cette valeur devra être changée par la vraie valeur de l'interface dès qu'elle sera connue (voir plus bas) :</p>
<div class="highlight"><pre><span></span><span class="o">[</span>Match<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>enx*
<span class="nv">Host</span><span class="o">=</span>raspife3
<span class="o">[</span>Network<span class="o">]</span>
<span class="nv">DHCP</span><span class="o">=</span>yes
<span class="o">[</span>DHCP<span class="o">]</span>
<span class="nv">RouteMetric</span><span class="o">=</span><span class="m">10</span>
</pre></div>
<p>L'interface WIFI sera créée dans le fichier <code>55-wireless.network</code></p>
<div class="highlight"><pre><span></span>sudo nano /etc/systemd/network/55-wireless.network
</pre></div>
<p>Fournir la configuration suivante le nom wlan0 est générique.</p>
<div class="highlight"><pre><span></span><span class="o">[</span>Match<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>wl*
<span class="nv">Host</span><span class="o">=</span>raspife3
<span class="o">[</span>Network<span class="o">]</span>
<span class="nv">DHCP</span><span class="o">=</span>yes
<span class="o">[</span>DHCP<span class="o">]</span>
<span class="nv">RouteMetric</span><span class="o">=</span><span class="m">20</span>
</pre></div>
<p>Cette configuration est insuffisante pour que le WIFI soit activé directement au démarrage car il faut fournir les paramètres de connection (nom et mot de pase du WIFI).Pour remédier à ce problème (sans passer par connman), si on dispose à l'avance des paramètres du réseau cible, il est possible de configurer le réseau à l'aide de <code>wpa_cli</code> ou de l'interface graphique de <code>wpasupplicant</code> (voir plus loin).</p>
<ul>
<li>effectuer la configuration depuis un terminal à distance (la connection filaire est automatique) en ligne de commandes avec <code>wpa_cli</code></li>
<li>Utiliser un clavier/écran/souris pour fournir les paramètres à l'interface graphique de <code>wicd</code> une fois la raspberryPi démarrée.</li>
</ul>
<h3><a name="head3.4.3"> </a> 3.4.3 Détection de l'interface WIFI</h3>
<p>Les deux solutions proposées sont
1. <code>connman</code> ou <code>connmanctl</code> qui sont fournis par défaut et sont préconfiguré sans ce qui rend leur manipulation aisée.
2. <code>wpa_cli</code> qui (d'après son nom cli Command Line Interface ;-) ) est moins convivial mais présente l'avantage de pouvoir pré-configurer l'interface en ligne de commandes et avant la connexion. </p>
<p>Cette interface est à manipuler avec précaution en veillant tout conflit avec <code>connman</code>, toute configuration de <code>wpa_supplicant</code> interfère avec <code>connman</code> et peut empêcher toute connexion wifi. Cela peut-être extrêmement utile si on désire "figer" une interface sur un réseau mais peut s'avérer extrêmement problématique si la même interface est utilisée avec plusieurs outils.
Pour éviter cet écueuil désinstaller complètement connman et configurer le fichier <code>/etc/wpa_supplicant/wpa_supplicant-wlan0.conf</code> pour qu'il démarre seulement le réseau choisi (on peut conserver le reste de la configuration par défaut si on le souhaite par exemple pour désactiver l'interface <code>P2P</code></p>
<h4>Uniquement en cas de besoin compilation d'un driver !</h4>
<p>Si l'interface wifi n'est pas détectée (elle n'apparait pas avec la commande <code>ip a</code>) c'est qu'il manque un driver pour le wifi, ce qui peut arriver quand on utilise des dongle WIFI récents ou peu utilisés ; par exemple le <code>ACT1200M</code> qui a besoin du driver <code>rtl88x2bu</code> qui n'existe dans aucun paquet debian. Exécuter la série de commandes suivantes expliquées sur le site <code>https://github.com/cilynx/rtl88x2bu</code> ou toutes commandes équivalentes pour une autre interface réseau. </p>
<p>Pour la compilation il est nécessaire d'avoir le paquet <code>linux-source</code> mais suivant le noyau utilisé il peut être nécessaire de disposer de paquets issus de la distribution <code>testing</code> (ou sid) nous allons d'abord ajouter cette ressource car les sources issues de la compilation avec <code>rpi23-genimage</code> sont incomplètes et ne permettent pas de compiler un nouveau module et un nouveau driver :</p>
<div class="highlight"><pre><span></span>sudo jed /etc/apt/sources.list
<span class="c1"># Le fichier doit avoir cette forme</span>
cat /etc/apt/sources.list
deb http://debian.proxad.net/debian bullseye main contrib non-free
deb http://debian.proxad.net/debian/ bullseye-updates main contrib non-free
deb http://security.debian.org/debian-security bullseye-security main contrib non-free
deb http://debian.proxad.net/debian testing main contrib non-free
deb-src http://debian.proxad.net/debian testing main contrib non-free
deb http://security.debian.org/debian-security testing-security main contrib non-free
cat > distribOrder
Package: *
Pin: release <span class="nv">n</span><span class="o">=</span>bullseye
Pin-Priority: <span class="m">900</span>
Package: *
Pin: release <span class="nv">a</span><span class="o">=</span>testing
Pin-Priority: <span class="m">100</span>
apt search linux-source
sudo apt update
dpkg -l dpkg-dev
<span class="c1"># si besoin</span>
sudo apt install dpkg-dev apt-src
sudo apt-src install linux-source-5.15
<span class="c1"># si des paquets supplémentaires sont nécessaires les installer avec</span>
<span class="c1"># sudo apt install -t testing </span>
sudo mv linux-5.15.15 linux
<span class="nb">cd</span> linux
make oldconfig
sudo make -j4 modules
</pre></div>
<p>Nous disposons maintenant d'une source linux minimale mais complète qui nous permet de compiler le driver du dongle wifi.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> <span class="o">&&</span> mkdir -p Logiciels/RTL88x2BU <span class="o">&&</span> <span class="nb">cd</span> Logiciels/RTL88x2BU
git clone https://github.com/cilynx/rtl88x2bu
<span class="nb">cd</span> rtl88x2bu/
sed -i <span class="s1">'s/I386_PC = y/I386_PC = n/'</span> Makefile
sed -i <span class="s1">'s/ARM_RPI = n/ARM_RPI = y/'</span> Makefile
<span class="nv">VER</span><span class="o">=</span><span class="k">$(</span>sed -n <span class="s1">'s/\PACKAGE_VERSION="\(.*\)"/\1/p'</span> dkms.conf<span class="k">)</span>
sudo rsync -rvhP ./ /usr/src/rtl88x2bu-<span class="si">${</span><span class="nv">VER</span><span class="si">}</span>
sudo dkms add -m rtl88x2bu -v <span class="si">${</span><span class="nv">VER</span><span class="si">}</span>
sudo dkms build -m rtl88x2bu -v <span class="si">${</span><span class="nv">VER</span><span class="si">}</span>
sudo dkms install -m rtl88x2bu -v <span class="si">${</span><span class="nv">VER</span><span class="si">}</span>
sudo dkms install --force -m rtl88x2bu -v <span class="si">${</span><span class="nv">VER</span><span class="si">}</span>
</pre></div>
<h4><a name="head3.4.3.1"> </a> 3.4.3.1 Logiciel <code>connman</code> en bullseye</h4>
<p>Par défaut cette solution semble être la plus facile et la plus automatisée via l'interface graphique (via vnc ou xrdp). Il est recommandé d'utiliser les outils graphiques, Il est toutefois possible d'agir en ligne de commandees et de configurer <code>connman</code> comme décrit ci-dessous.</p>
<p>Configurer le fichier <code>/etc/connman/main.conf</code> en décommentant et modifiant la ligne :</p>
<div class="highlight"><pre><span></span><span class="nv">AllowHostnameUpdates</span> <span class="o">=</span> <span class="nb">false</span>
</pre></div>
<p>Il est souvent plus facile de mettre en place le wifi depuis une interface graphique, on peut facilement utiliser l'outil <code>connman</code> pour mettre en place une connection wifi enutilisant <code>xrdp</code> ou <code>vncserver</code> qui sont installés par défaut il suffira de choisisr l'option autoconnect dans l'interface pour que la raspberry se connecte automatiquement au réseau (cette option très pratique n'est toutefois pas dénuée de risques)</p>
<p>Il est aussi possible de configurer le wifi directement en ajoutant un fichier de configuration dans <code>/var/lib/connman</code></p>
<ol>
<li>exécuter la commande <code>connmanctl services</code> qui fournit le nom de l'interface qui <strong>DOIT</strong> être utilisé pour nommer le dossier qui va contenir le fichier de configuration</li>
<li>créer le dossier avec le nom obtenu</li>
<li>recopier les fichiers <code>settings</code> du modèle existant </li>
<li>modifier les paramètres du fichier <code>settings</code> en fonction du réseau souhaité</li>
</ol>
<p>Le nom de l'interface est construit de la façon suivante :</p>
<p>wifi_[MacAdress sans les séparateurs]_[SSID de l'interface]_managed_psk</p>
<div class="highlight"><pre><span></span><span class="o">[</span>wifi_############_**************************_managed_psk<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>ClimatEtMeteo
<span class="nv">SSID</span><span class="o">=</span>**************************
<span class="nv">Frequency</span><span class="o">=</span><span class="m">2412</span>
<span class="nv">Favorite</span><span class="o">=</span><span class="nb">true</span>
<span class="nv">AutoConnect</span><span class="o">=</span><span class="nb">true</span>
<span class="nv">Modified</span><span class="o">=</span><span class="m">2021</span>-10-19T08:34:11.692503Z
<span class="nv">Passphrase</span><span class="o">=</span>ClimatEtMeteo
IPv4.method<span class="o">=</span>dhcp
IPv4.DHCP.LastAddress<span class="o">=</span><span class="m">192</span>.168.***.***
IPv6.method<span class="o">=</span>auto
IPv6.privacy<span class="o">=</span>disabled
</pre></div>
<h4><a name="head3.4.3.2"> </a> 3.4.3.2 Logiciel <code>wicd</code> par défaut jusqu'à <code>buster</code> (Seulement si <code>connman</code> échoue)</h4>
<p>La façon la plus simple pour configurer l'interface WIFI avec wicd est de démarrer la raspberry connecté au filaire et d'utiliser un clavier-écran-souris. Ouvrir le logiciel wicd dans la barre de menus en bas à droite, élargir la fenêtre et accéder à la configuration des paramètres. Cliquer sur le démarrage par défaut de cette interface. Dès que le filaire sera débranché elle prendra le relais</p>
<h4><a name="head3.4.3.3"> </a> 3.4.3.3 Logiciel <code>wpa_cli</code> en bullseye (Seulement si <code>connman</code> échoue)</h4>
<p>Le logiciel <code>wpasupplicant</code> fournit une interface graphique <code>wpa_gui</code>et une interface en ligne de commandes <code>wpa_cli</code> pour configurer le wifi. Verifier la configuration logicielle avec <code>dpkg -l wpagui wpasupplicant network-manager</code> elle soit se présenter comme ci-dessous éventuellement </p>
<div class="highlight"><pre><span></span><span class="nv">Souhait</span><span class="o">=</span>inconnU/Installé?/suppRimé?/Purgé?/H<span class="o">=</span>à? garder
<span class="p">|</span> É?tat<span class="o">=</span>Non/Installé?/fichier-Config/dé?paqUeté?/é?chec-conFig/H<span class="o">=</span>semi-installé?/W<span class="o">=</span>attend-traitement-dé?clen>
<span class="p">|</span>/ Err?<span class="o">=(</span>aucune<span class="o">)</span>/besoin Ré?installation <span class="o">(</span>É?tat,Err: <span class="nv">majuscule</span><span class="o">=</span>mauvais<span class="o">)</span>
<span class="o">||</span>/ Nom Version Architecture Description
+++-<span class="o">===============</span>-<span class="o">============</span>-<span class="o">============</span>-<span class="o">==============================================</span>
un network-manager <aucune> <aucune> <span class="o">(</span>aucune description n<span class="err">'</span>est disponible<span class="o">)</span>
ii wpagui <span class="m">2</span>:2.9.0-16 armhf graphical user interface <span class="k">for</span> wpa_supplicant
ii wpasupplicant <span class="m">2</span>:2.9.0-16 armhf client support <span class="k">for</span> WPA and WPA2 <span class="o">(</span>IEEE <span class="m">802</span>.11i<span class="o">)</span>
</pre></div>
<p>Éventuellement effectuer les installations et délétions nécessaires :</p>
<div class="highlight"><pre><span></span>sudo apt install wpagui wpasupplicant
sudo apt-purge network-manager
</pre></div>
<p>Par défaut le logiciel <code>rfkill</code> empêche de configurer les configurations du WIFI, cela me rappelle le bref moment pendant lequel un usager ordinaire de linux ne pouvait pas accéder à l'interface sans intervention de l'administrateur... On va ici empêcher simplement <code>rfkill</code> de bloquer par hardware ou software la configuration de l'interface wifi, pour que ce soit applicable à tous les utilisateurs on va modifier le fichier sudoers</p>
<div class="highlight"><pre><span></span>sudo visudo
<span class="c1"># add lines</span>
Cmnd_Alias <span class="nv">RFKILL_CMD</span> <span class="o">=</span> /usr/sbin/rfkill
ALL <span class="nv">ALL</span><span class="o">=</span>NOPASSWD: RFKILL_CMD
</pre></div>
<p>Tous les utilisateurs peuvent rtaper maintenant :</p>
<div class="highlight"><pre><span></span>sudo rfkill unblock all
</pre></div>
<p>Détecter le nom de l'interface avec <code>ipa</code> nous obtenons ici <code>wlan0</code> et éditer le fichier de configuration correspondant à l'interface traitée wpa_supplicant-NOM_INTERFACE.conf ici avec la commande <code>sudo nano /etc/wpa_supplicant/wpa_supplicant-wlan0.conf</code> et ajouter le contenu suivant qui sert de pré-configuration et de modèle pour un wifi WPA2 perso avec phrase de passe.</p>
<div class="highlight"><pre><span></span><span class="c1">## /etc/wpa_supplicant/wpa_supplicant.conf</span>
<span class="nv">ctrl_interface</span><span class="o">=</span><span class="nv">DIR</span><span class="o">=</span>/var/run/wpa_supplicant <span class="nv">GROUP</span><span class="o">=</span>netdev
<span class="nv">update_config</span><span class="o">=</span><span class="m">1</span>
<span class="nv">p2p_disabled</span><span class="o">=</span><span class="m">1</span>
<span class="c1"># network={</span>
<span class="c1"># ssid="__SSID__"</span>
<span class="c1"># psk="__PASS__"</span>
<span class="c1"># }</span>
</pre></div>
<p>la configuration s'effectue : </p>
<ul>
<li>soit en utilisant l'interface graphique <code>wpa_gui</code> dans une configuration écran-clavier-souris, </li>
<li>soit via un terminal serveur (cf plus loin, dans ce cas attention de ne pas couper le réseau qui est en cours d'utilisation...)</li>
<li>soit via la ligne de commandes voir ci-dessous</li>
</ul>
<div class="highlight"><pre><span></span>sudo systemctl start wpa_supplicant@wlan0
sudo wpa_cli
<span class="o">[</span>sudo<span class="o">]</span> Mot de passe de ens-ife :
wpa_cli v2.9
Copyright <span class="o">(</span>c<span class="o">)</span> <span class="m">2004</span>-2019, Jouni Malinen <j@w1.fi> and contributors
This software may be distributed under the terms of the BSD license.
See README <span class="k">for</span> more details.
Selected interface <span class="s1">'wlan0'</span>
Interactive mode
> scan
OK
<<span class="m">3</span>>CTRL-EVENT-SCAN-STARTED
<<span class="m">3</span>>CTRL-EVENT-SCAN-RESULTS
> scan_results
bssid / frequency / signal level / flags / ssid
<span class="m">24</span>:f5:a2:**:**:** <span class="m">2437</span> -50 <span class="o">[</span>WPA2-PSK-CCMP<span class="o">][</span>ESS<span class="o">]</span> MyNetwork
<span class="m">24</span>:95:04:**:**:** <span class="m">2442</span> -89 <span class="o">[</span>WPA-PSK-CCMP+TKIP<span class="o">][</span>WPS<span class="o">][</span>ESS<span class="o">]</span> SFR_F228
<span class="m">98</span>:e7:f4:**:**:** <span class="m">2462</span> -92 <span class="o">[</span>WPA2-PSK-CCMP<span class="o">][</span>WPS<span class="o">][</span>ESS<span class="o">]</span> DIRECT-31-HP ENVY <span class="m">7640</span> series
> add_network
<span class="m">0</span>
> set_network <span class="m">0</span> ssid <span class="s2">"MyNetwork"</span>
OK
> set_network <span class="m">0</span> psk <span class="s2">"secret"</span>
OK
> enable_network <span class="m">0</span>
OK
> quit
</pre></div>
<p>(re)Lancer Pour tester le fonctionnement puis installer au démarrage.</p>
<div class="highlight"><pre><span></span>sudo systemctl restart wpa_supplicant@wlan0
sudo systemctl <span class="nb">enable</span> wpa_supplicant@wlan0
</pre></div>
<p><strong>En cas de problème notamment avec la pi4-64bit bullseye</strong></p>
<p>Veiller à ce que lors de l'install les paquets <code>firmware-brcm80211</code>, <code>firmware-misc-nonfree</code>, <code>rfkill</code> aient été convenablement installés. Ne pas installer <code>connman</code> et vérifier que les services <code>wpa_supplicant</code> et <code>wpa_supplicant@wlan0</code> soient activés au boot (enabled).</p>
<p><strong>Option Option Option Option Option Option </strong></p>
<h3><a name="head3.4.4"> </a> 3.4.4 (Optionnel) Configuration de <code>network-manager</code> (au lieu de <code>wicd</code> ou <code>connman</code> s'ils échouent)</h3>
<p>Tout ce qui suit est totalement optionnel le logiciel <code>wicd</code> est maintenant opérationnel en l'état pour <code>buster</code>et <code>connman</code> pour <code>bullseye</code>. Cette partie du tutoriel a été conservée au cas où les problèmes réapparaitraient ou si pour des questions de goût ou d'usage l'utilisateur souhaite changer de gestionnaire réseau. La combinaison <code>systemd-networkd + wpa_supplicant</code>est plus robuste mais moins conviviale et requiert l'utilisation de lignes de commande.
Supprimer le logiciel <code>wicd</code> désactiver l'interface <code>systemd-networkd</code> (sinon la machine acquiert 2 IP sur la même interface réseau sans <code>bridge</code>, la seconde interface est en état <code>secondary</code>. Installer à la place<code>network-manager</code> et <code>nm-tray</code> pour l'interface graphique.</p>
<div class="highlight"><pre><span></span>sudo apt purge <span class="c1"># (wicd ou connman)</span>
sudo apt install network-manager nm-tray
</pre></div>
<p>Le logiciel <code>networkmanager</code> est installé pour gérer le réseau. ce logiciel propose une interface en ligne de commande extrêmement performante <code>nmcli</code> pourvue de nombreuses options qui permettent de gérer le réseau très finement. Il est fortement conseillé de booter la première fois avec une connexion filaire ce qui permet à la raspberry de récupérer une date correcte et d'assurer un fonctionnement nominal par la suite.
Le bloc ci-dessous présente les options de premier niveau de <code>nmcli</code> il y a jusqu'à 4 niveaux d'options pour certaines commandes, pour connaitre la façon de les utiliser taper la commande suivie de <code>help</code> par exemple :</p>
<div class="highlight"><pre><span></span>nmcli -p radio <span class="nb">help</span>
Syntaxe : nmcli radio <span class="o">{</span> COMMAND <span class="p">|</span> <span class="nb">help</span> <span class="o">}</span>
COMMAND :<span class="o">=</span> <span class="o">{</span> all <span class="p">|</span> wifi <span class="p">|</span> wwan <span class="o">}</span>
all <span class="p">|</span> wifi <span class="p">|</span> wwan <span class="p">|</span> wimax <span class="o">[</span> on <span class="p">|</span> off <span class="o">]</span>
</pre></div>
<div class="highlight"><pre><span></span>nmcli -h
Usage: nmcli <span class="o">[</span>OPTIONS<span class="o">]</span> OBJECT <span class="o">{</span> COMMAND <span class="p">|</span> <span class="nb">help</span> <span class="o">}</span>
OPTIONS
-o<span class="o">[</span>verview<span class="o">]</span> overview mode <span class="o">(</span>hide default values<span class="o">)</span>
-t<span class="o">[</span>erse<span class="o">]</span> terse output
-p<span class="o">[</span>retty<span class="o">]</span> pretty output
-m<span class="o">[</span>ode<span class="o">]</span> tabular<span class="p">|</span>multiline output mode
-c<span class="o">[</span>olors<span class="o">]</span> auto<span class="p">|</span>yes<span class="p">|</span>no whether to use colors in output
-f<span class="o">[</span>ields<span class="o">]</span> <field1,field2,...><span class="p">|</span>all<span class="p">|</span>common specify fields to output
-g<span class="o">[</span>et-values<span class="o">]</span> <field1,field2,...><span class="p">|</span>all<span class="p">|</span>common shortcut <span class="k">for</span> -m tabular -t -f
-e<span class="o">[</span>scape<span class="o">]</span> yes<span class="p">|</span>no escape columns separators in values
-a<span class="o">[</span>sk<span class="o">]</span> ask <span class="k">for</span> missing parameters
-s<span class="o">[</span>how-secrets<span class="o">]</span> allow displaying passwords
-w<span class="o">[</span>ait<span class="o">]</span> <seconds> <span class="nb">set</span> timeout waiting <span class="k">for</span> finishing operations
-v<span class="o">[</span>ersion<span class="o">]</span> show program version
-h<span class="o">[</span>elp<span class="o">]</span> print this <span class="nb">help</span>
OBJECT
g<span class="o">[</span>eneral<span class="o">]</span> NetworkManager<span class="s1">'s general status and operations</span>
<span class="s1"> n[etworking] overall networking control</span>
<span class="s1"> r[adio] NetworkManager radio switches</span>
<span class="s1"> c[onnection] NetworkManager'</span>s connections
d<span class="o">[</span>evice<span class="o">]</span> devices managed by NetworkManager
a<span class="o">[</span>gent<span class="o">]</span> NetworkManager secret agent or polkit agent
m<span class="o">[</span>onitor<span class="o">]</span> monitor NetworkManager changes
</pre></div>
<p>Le paragraphe ci-dessous démontre quelques exemples utiles d'utilisation de <code>nmcli</code>.</p>
<p>La commande ci-dessous permet de lister les interfaces réseau disponibles et d'obtenir leur état :</p>
<div class="highlight"><pre><span></span>nmcli -p device <span class="nv">status</span>
<span class="o">==========================</span>
État des périphériques
<span class="o">==========================</span>
DEVICE TYPE STATE CONNECTION
--------------------------------------------------------------------------------------
enxb827eb6e992b ethernet connecté Connexion filaire <span class="m">1</span>
wlan0 wifi déconnecté --
lo loopback non-géré --
</pre></div>
<p>La commande ci-dessous permet de lister les points d'accès wifi disponibles :</p>
<div class="highlight"><pre><span></span>nmcli -p device wifi <span class="nv">list</span>
<span class="o">===================================</span>
Liste de balayage Wi-Fi <span class="o">(</span>wlan0<span class="o">)</span>
<span class="o">===================================</span>
IN-USE SSID MODE CHAN RATE SIGNAL BARS SECURITY
------------------------------------------------------------------------------------------------------------------
MobileClimatEtMeteo Infra <span class="m">4</span> <span class="m">54</span> Mo/s <span class="m">95</span> ▂▄▆█ WPA1
*************** Infra <span class="m">1</span> <span class="m">405</span> Mo/s <span class="m">94</span> ▂▄▆█ WPA2
FreeWifi_secure Infra <span class="m">4</span> <span class="m">195</span> Mo/s <span class="m">50</span> ▂▄__ WPA2 <span class="m">802</span>.1X
***************** Infra <span class="m">4</span> <span class="m">195</span> Mo/s <span class="m">49</span> ▂▄__ WPA2
FreeWifi Infra <span class="m">4</span> <span class="m">195</span> Mo/s <span class="m">49</span> ▂▄__ --
</pre></div>
<p>La commande ci-dessous permet de lister les connexions actives, en ajoutant le nom de l'interface on obtient la liste et la valeur de tous les paramètres de l'interface :</p>
<div class="highlight"><pre><span></span>nmcli -p connection <span class="nv">show</span>
<span class="o">=======================================</span>
Profils de connexion <span class="nv">NetworkManager</span>
<span class="o">=======================================</span>
NAME UUID TYPE DEVICE
-----------------------------------------------------------------------------------------------------------------------------
Connexion filaire <span class="m">1</span> <span class="m">91773701</span>-33bc-31cc-a016-de04999ec61b ethernet enxb827eb6e992b
</pre></div>
<p>La commande ci-dessous devrait permettre de se connecter à un des points d'accès wifi disponibles mais comme nous allons le voir l'utilisateur ordinaire ne dispose pas des droits nécessaires :</p>
<div class="highlight"><pre><span></span>nmcli device wifi connect MobileClimatEtMeteo password ClimatEtMeteo
Erreur : échec de l<span class="s1">'ajout ou de l'</span>activation de la nouvelle connexion : Not authorized to control networking.
</pre></div>
<p>On vérifie effectivement que les permissions d'un utilisateur ordinaire sont insuffisantes pour manipuler le réseau :</p>
<div class="highlight"><pre><span></span>nmcli general permissions
PERMISSION VALUE
org.freedesktop.NetworkManager.enable-disable-network non
org.freedesktop.NetworkManager.enable-disable-wifi non
org.freedesktop.NetworkManager.enable-disable-wwan non
org.freedesktop.NetworkManager.enable-disable-wimax non
org.freedesktop.NetworkManager.sleep-wake non
org.freedesktop.NetworkManager.network-control auth
org.freedesktop.NetworkManager.wifi.share.protected non
org.freedesktop.NetworkManager.wifi.share.open non
org.freedesktop.NetworkManager.settings.modify.system non
org.freedesktop.NetworkManager.settings.modify.own auth
org.freedesktop.NetworkManager.settings.modify.hostname auth
org.freedesktop.NetworkManager.settings.modify.global-dns auth
org.freedesktop.NetworkManager.reload auth
org.freedesktop.NetworkManager.checkpoint-rollback auth
org.freedesktop.NetworkManager.enable-disable-statistics non
org.freedesktop.NetworkManager.enable-disable-connectivity-check non
</pre></div>
<p>Pour permettre à tous les membres du groupe <code>netdev</code> de modifier le wifi il suffit de créer le fichier d'autorisations adéquat avec la commande <code>sudo nano /etc/polkit-1/localauthority/50-local.d/org.freedesktop.NetworkManager.pkla</code> et d'ajouter dans ce fichier les lignes suivantes :</p>
<div class="highlight"><pre><span></span><span class="o">[</span>nm-applet<span class="o">]</span>
<span class="nv">Identity</span><span class="o">=</span>unix-group:netdev
<span class="nv">Action</span><span class="o">=</span>org.freedesktop.NetworkManager.*
<span class="nv">ResultAny</span><span class="o">=</span>yes
<span class="nv">ResultInactive</span><span class="o">=</span>no
<span class="nv">ResultActive</span><span class="o">=</span>yes
</pre></div>
<p>Vérifier les droits sur ce fichier le groupe netdev doit avoir le droit de lire/écrire</p>
<div class="highlight"><pre><span></span>sudo chmod a+rx /etc/polkit-1/localauthority
sudo chown root.netdev /etc/polkit-1/localauthority/50-local.d/org.freedesktop.NetworkManager.pkla
sudo chmod g+rw /etc/polkit-1/localauthority/50-local.d/org.freedesktop.NetworkManager.pkla
</pre></div>
<p>Les permissions deviennent :</p>
<div class="highlight"><pre><span></span>nmcli general permissions
PERMISSION VALUE
org.freedesktop.NetworkManager.enable-disable-network oui
org.freedesktop.NetworkManager.enable-disable-wifi oui
org.freedesktop.NetworkManager.enable-disable-wwan oui
org.freedesktop.NetworkManager.enable-disable-wimax oui
org.freedesktop.NetworkManager.sleep-wake oui
org.freedesktop.NetworkManager.network-control oui
org.freedesktop.NetworkManager.wifi.share.protected oui
org.freedesktop.NetworkManager.wifi.share.open oui
org.freedesktop.NetworkManager.settings.modify.system non
org.freedesktop.NetworkManager.settings.modify.own oui
org.freedesktop.NetworkManager.settings.modify.hostname oui
org.freedesktop.NetworkManager.settings.modify.global-dns oui
org.freedesktop.NetworkManager.reload oui
org.freedesktop.NetworkManager.checkpoint-rollback oui
org.freedesktop.NetworkManager.enable-disable-statistics oui
org.freedesktop.NetworkManager.enable-disable-connectivity-check oui
</pre></div>
<p>Il est alors possible de gérer les interfaces réseau à sa propre convenance.</p>
<div class="highlight"><pre><span></span>nmcli device wifi connect MobileClimatEtMeteo password ClimatEtMeteo
Périphérique « wlan0 » activé avec « 1cbd5ef5-159e-4a3e-a5cb-844e7147c1ec ».
nmcli -p device <span class="nv">status</span>
<span class="o">==========================</span>
État des périphériques
<span class="o">==========================</span>
DEVICE TYPE STATE CONNECTION
------------------------------------------------------------------------------------
enxb827eb6e992b ethernet connecté Connexion filaire <span class="m">1</span>
wlan0 wifi connecté MobileClimatEtMeteo
lo loopback non-géré --
</pre></div>
<p>Pour allumer ou éteindre le wifi :</p>
<div class="highlight"><pre><span></span>nmcli radio wifi on / off
</pre></div>
<p>les mêmes commandes sont utilisables dans un shell de façon interactive avec clavier et écran. Dans l'interface graphique l'outil <code>nm-tray</code> fournit une interface de gestion du réseau.</p>
<h1><a name="head4"> </a> 4. Ajustements après le premier démarrage de la Raspberry munie de sa nouvelle image</h1>
<p>L'image fournie doit booter normalement et se connecter spontanément au réseau filaire, dans ce cas il est possible de réaliser toutes les installations sans écran ni clavier ni souris. Un réseau WIFI peut aussi être configuré par défaut afin de permettre une connexion wifi, si le réseau wifi n'est pas connu au moment de la création de l'image, il est nécessaire de connecter la <code>raspberryPi</code> à un clavier et à un écran pour configurer manuellement le wifi.</p>
<p>Pour obtenir l'adresse IP de la raspberry, si le réseau n'est pas trop étendu et ne contient pas trop de raspberries, on peut depuis l'ordinateur d'installation utiliser l'une des commande ci-desous :</p>
<ul>
<li>Si l'image utilisée a été configurée avec une IP fixe il va de soi qu c'est elle qui doit être utilisée</li>
<li>Si on dispose d'un accès à la configuration du DHCP il suffit de s'y connecter et de récupérer l'adresse de la Raspberry dans notre exemple son nom est raspife2, raspife3, raspife3P, raspwife3, raspife4 suivant la configuration choisie</li>
<li>Si on ne dipose que de l'accès standard au réseau on peut utiliser la commande <code>sudo nmap -sP -n ***.****.***.0/**</code> la valeur <code>***.****.***.0/**</code> représente le réseau sur lequel on se trouve, les valeurs peuvent être obtenues avec la commande <code>ip addr</code> ; si l'on dispose de l'adresse MAC de la Raspberry <code>**:**:**:**:**:**</code> on peut filtrer la commande ci-dessus avec l'adresse recherchée <code>sudo nmap -sP -n ***.****.***.0/** | grep -e **:**:**:**:**:** -B 2</code></li>
</ul>
<p>Une fois l'adresse obtenue se connecter via ssh ; <code>ssh ens-ife@***.****.***.***</code> (remplacer ens-ife par le nom de l'utilisateur initial choisi dans le fichier de confiuration initiale)</p>
<p>Lors de la première connexion la configuration de l'hôte peut s'avérer inadaptée, modifier le fichier <code>sudo jed /etc/host.conf</code> en commentant la ligne <code>spoof warn</code></p>
<div class="highlight"><pre><span></span><span class="c1">#spoof warn</span>
multi on
</pre></div>
<h2><a name="head4.1"> </a> 4.1. Modification de la taille de l'espace utilisé (au besoin seulement)</h2>
<p>Si cela n'a pas déjà été fait, ou si cela s'avère nécessaire (les images proposées ici font un peu moins de 16Go pour pouvoir être directement recopiées sur une SD d'au moins 16Go une partie de l'espace disque est occupées si on utilise une clef plus grosse), il est possible / souhaitable de redimensionner la partition racine sur la Raspberry Pi fonctionnant avec la nouvelle image. Pour cela <em><strong>une fois la Raspberry Pi opérationnelle et démarrée</strong></em>, se connecter en tant quadministrateur puis utiliser la commande :</p>
<div class="highlight"><pre><span></span>sudo fdisk /dev/mmcblk0
</pre></div>
<ul>
<li>Taper <code>m</code> pour voir la liste des commandes (juste pour information)</li>
<li>
<p>Taper <code>p</code> pour voir la liste des partitions disponibles, normalement il y en deux</p>
<ul>
<li>une FAT : /dev/mmcblk0p1 * 2048 133119 131072 64M c W95 FAT32 (LBA)</li>
<li>une linux : /dev/mmcblk0p2 133120 62517247 62384128 29,8G 83 Linux</li>
</ul>
</li>
<li>
<p>Taper ensuite </p>
<ul>
<li><code>d</code> puis </li>
<li><code>2</code> puis </li>
<li><code>n</code> puis </li>
<li><code>p</code> puis </li>
<li><code>2</code> puis </li>
<li>accepter les valeurs par défaut qui correspondent à la taille effectivement disponible sur la cartes SD et écrire N pour "remove signature", </li>
<li>pour finir taper <code>w</code>. </li>
</ul>
</li>
</ul>
<p>Redimensionner le système de fichiers puis rebooter pour que ce soit pris en compte :</p>
<div class="highlight"><pre><span></span>sudo resize2fs /dev/mmcblk0p2
sudo reboot <span class="o">(</span>facultatif<span class="o">)</span>
</pre></div>
<p>Après ce redémarrage la racine du système occupe maintenant la totalité de l'espace disponible sur la SD.</p>
<h2><a name="head4.2"> </a> 4.2 Mises à jour et installation d'utilitaires</h2>
<p>L'image installée ne contient pas les paquets non libres pour les rajouter éditer le fichier <code>/etc/apt/sources.list</code> et ajouter à la fin de chaque ligne active <code>non-free</code>.</p>
<div class="highlight"><pre><span></span>sudo nano /etc/apt/sources.list
</pre></div>
<p>Il peut s'être écoulé suffisamment de temps entre la création de l'image et sa mise en oeuvre, certains paquets peuvent avoir évolué, certains paquets peuvent être incomplètement configurés et il est recommandé de faire une mise à jour. Pour cela mettre à jour la liste des paquets et mettre à jour ensuite les nouveaux paquets de la liste :</p>
<div class="highlight"><pre><span></span>sudo apt update
sudo apt upgrade
sudo apt dist-upgrade
sudo dpkg-reconfigure locales
sudo dpkg-reconfigure tzdata
</pre></div>
<p>Vérifier que tous les utilitaires et autres programmes ont été installés lors de la construction de l'image, utiliser la commande ci dessous. Pour tous les paquets renvoyant le message <code>dpkg-query: aucun paquet ne correspond à *****</code>, les installer avec la commande standard d'installation de la ligne suivante (tous les paquets sont reportés ici une partie seulement peut-être utilisée:</p>
<div class="highlight"><pre><span></span>dpkg -l dirmngr wpasupplicant php-fpm fcgiwrap libfcgi-dev php7.4-mysql ca-certificates-java icedtea-netx openjdk-11-jdk openjdk-11-jre openjdk-11-jre-headless openjdk-17-jdk openjdk-17-jre openjdk-17-jre-headless
sudo apt install jed dirmngr wpasupplicant php-fpm fcgiwrap libfcgi-dev php7.4-mysql ca-certificates-java icedtea-plugin icedtea-netx openjdk-11-jdk openjdk-11-jre openjdk-11-jre-headless
</pre></div>
<p>Dans une installation <code>buster</code> ou <code>bullseye</code> les paquets openjdk-11 16 et 17 sont disponibles; à partir de la version 16 <code>JNI</code>disparait veiller aux compatibilités.</p>
<h2><a name="head4.3"> </a> 4.3 Ajout d'une interface graphique</h2>
<p>Une interface a été ajoutée par défaut mais des problèmes d'insatisfaction de dépendances emporaires peuvent empêcher la construction correcte de l'interface graphique. Dans ce cas seulement appliquer la procédure ci-dessous.</p>
<p>Afin de disposer d'une interface graphique on ajoute un <code>display manager</code> (lxdm dans ce cas), un <code>window manager</code> (lxqt dans cette proposition). Cette interface graphique est installée par défaut lorsque c'est possible mais des anomalies liées à des dépendances non satisfaites du fait de l'évolution rapide des packages des interfaces graphiques peuvent conduire à des situations cahotiques Si l'interface graphique n'est pas opérationnelle supprimer puis réinstaller les paquets (il est possible de choisir un autre <code>display manager</code> et <code>window manager</code>, toujours choisir des environnements peu gourmands en ressources.</p>
<div class="highlight"><pre><span></span>sudo apt purge lxdm lxqt*
sudo apt install lxdm lxqt
</pre></div>
<h2><a name="head4.4"> </a> 4.4 Ajout d'utilisateurs et gestion des droits</h2>
<p>Lors de la création un seul utilisateur par défaut a été créé <code>ens-ife</code>, dans notre projet cet utilisateur est l'administrateur de secours et nous proposons de créer :</p>
<ul>
<li>un administrateur principal <code>localadm</code>, </li>
<li>un utilisateur qui gèrera l'accès à la station météo <code>weewx</code></li>
<li>un utilisateur invité qui servira de test <code>moon</code> (ce login est utilisé en référence aux machines de développement ayant un utilisateur jupyter et un utilisateur callisto...)</li>
<li>un administrateur de l'nterface de programmation jupyterhub <code>callisto</code></li>
<li>un créateur par défaut d'un serveur de terminaux <code>tsuser</code>. Les groupes et les utilisateurs sont ajoutés avec les commande standard linux debian <code>addgroup</code> et <code>adduser</code></li>
</ul>
<div class="highlight"><pre><span></span><span class="k">for</span> i in i2c gpio jupyterhub<span class="p">;</span> <span class="k">do</span> sudo addgroup <span class="nv">$i</span><span class="p">;</span> <span class="k">done</span>
<span class="k">for</span> i in localadm weewx moon callisto tsuser<span class="p">;</span> <span class="k">do</span> sudo adduser <span class="nv">$i</span><span class="p">;</span> <span class="k">done</span>
</pre></div>
<p>l'utilisateur <code>localadm</code> doit disposer des droits d'administration :</p>
<div class="highlight"><pre><span></span>sudo adduser localadm sudo
</pre></div>
<p>Les utilisateurs <code>ens-ife</code>, <code>localadm</code>, <code>callisto</code>, <code>tsuser</code>et <code>moon</code> doivent pouvoir en outre utiliser les ressources matérielles de la raspberry on les affecte aux groupes nécessaires :</p>
<div class="highlight"><pre><span></span><span class="k">for</span> i in localadm moon ens-ife callisto tsuser<span class="p">;</span> <span class="k">do</span> <span class="k">for</span> j in i2c gpio netdev plugdev audio video<span class="p">;</span> <span class="k">do</span> sudo adduser <span class="nv">$i</span> <span class="nv">$j</span><span class="p">;</span> <span class="k">done</span><span class="p">;</span> <span class="k">done</span>
</pre></div>
<p>Pour améliorer la sécurité il est possible (souhaitable) de supprimer le login par mot de passe de callisto en lui procurant un login exclusif par clef ssh.</p>
<p>Les utilisateurrs <code>localadm</code>, <code>moon</code>, <code>ens-ife</code>, <code>callisto</code> doivent appartenir au groupe <code>jupyterhub</code> :</p>
<div class="highlight"><pre><span></span><span class="k">for</span> i in localadm moon ens-ife callisto<span class="p">;</span> <span class="k">do</span> sudo adduser <span class="nv">$i</span> jupyterhub<span class="p">;</span> <span class="k">done</span>
</pre></div>
<h2><a name="head4.5"> </a> 4.5 Activation du serveur de terminaux à distance</h2>
<p>Depuis le début l'ensemble du travail a pu être réalisé sans connecter clavier/écran/souris à la RaspberryPi. Pour pouvoir continuer dans cette logique tout en profitant d'une interface graphique évoluée nous allons installer un terminal serveur sur la raspi qui pourra être affiché sur n'importe quel ordinateur du <strong>même réseau</strong>.</p>
<h2><a name="head4.5.1"> </a> 4.5.1 Mise en place de <code>tigervnc</code></h2>
<p>Lors de la construction de l'image on a ajouté le logiciel <code>tigervncserver</code> qui permet d'afficher sur un écran distant l'écran de la raspberry via le protocole <code>VNC</code>, ce protocole permet de ne pas avoir à connecter un clavier une souris et un écran à une raspberry Pi pour pouvoir l'utiliser. Il est très utile de disposer du serveur de terminaux dès le boot de la raspberry. Pour cela ce logiciel va être installé comme un service et l'écran sera fourni par un user spécialisé <code>tsuser</code>.</p>
<p>La sécurité est une contrainte importante de tout échange sur un réseau numérique notamment en milieu éducatif. Même si votre raspberry qui est branchée dans une salle de TP derrière le pare-feu de l'établissement paraît ne pas être une menace, elle pourrait bel et bien le devenir ! (Certaines séries américaines ont d'ailleurs utilisé des Raspberries Pi comme symbole d'instruments d'attaque numérique, cela est en général romancé mais repose tout de même sur une part de réalité). Il est recommandé de mettre en place quelques éléments basiques de protection qui pourront aussi servir de support à une sensibilisation sur les risques numériques et le comportement à adopter sur les réseaux. Ces éléments de sécurité sont notamment importants quand on permet l'accès à des interfaces avancées (graphiques) dont la complexité augmente la vulnérabilité. La procédure ci-dessous sera réutilisée pour l'installation de JupyterHub (voir plus loin) L'authentification permet ici de disposer d'un accès avec une interface graphique sur un ordinateur client, c'est une commodité qui doit êre remplacée par une sécurisation personnalisée dès que possible.</p>
<p><code>tsuser</code> est l'utilisateur choisi pour lancer <code>tigervnc</code>, pour assumer la configuration proposée c'est donc l'utilisateur <code>tsuser</code> qui doit créer le certificat de sécurité. Répondre aux questions posées en fonction de vos paramètres, l'exemple fourni correspond au certificat de base créé pour l'usage de l'IFÉ par l'auteur.</p>
<div class="highlight"><pre><span></span>sudo apt install tigervnc-standalone-server tigervnc-viewer
sudo su tsuser
<span class="nb">cd</span>
mkdir -p Utils/Certificates
<span class="nb">cd</span> !$
openssl req -new -newkey rsa:2048 -rand /dev/urandom -nodes -keyout meteotigervnc.key -out meteotigervnc.csr
openssl req -new -x509 -days <span class="m">3652</span> -key meteotigervnc.key -out meteotigervnc.pub
</pre></div>
<p>On dispose maintenant des fichiers de sécurisaton nécessaires <code>meteotigervnc.csr</code> <code>meteotigervnc.key</code> <code>meteotigervnc.pem</code> qui vont être utilisés pour protéger l'accès à jupyterhub. Par défaut un fichier de sécurisation a été installé pour permettre un fonctionnement immédiat mais <strong>chaque nouvel administrateur doit impérativement créer son propre fichier de sécurité</strong>.
Nous allons définir le mot de passe qui sera utilisé par le login <code>tsuser</code> pour lancer le serveur de terminaux au démarrage. Pour cela se connecter en tant que tsuser sur la raspi et exécuter la commande <code>vncpasswd</code>. </p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
vncpasswd
</pre></div>
<p>Le mot de passe doit être ajouté et par défaut dans ce cas c'est le nom de la machine <code>raspife4</code>, <code>raspife3</code>, <code>raspife3P</code> ou <code>raspife2</code> qui est utilisé. (Suivant les versions et les configurations le mot de passe peut-être tronqué à 8 caractères). Vérifier le fonctionnement de vncserver lancé par <code>tsuser</code> afin de garantir que l'image binaire fonctionnera par défaut, puis éteindre vnc afin de configurer le service.</p>
<p>Configurer <code>tigervncserver</code> </p>
<div class="highlight"><pre><span></span>vncserver -localhost no
vncserver -list
vncserver -kill :1
cp /etc/X11/Xtigervnc-session .vnc/xstartup <span class="o">(</span>pas obligatoire<span class="o">)</span>
<span class="nb">exit</span>
</pre></div>
<p>À ce stade la connexion n'est pas sécurisée et il est <strong>impératif</strong> de se connecter via un <code>tunnel ssh</code> qui est initié pr le client (remmina par exemple).</p>
<p>L'autre solution est d'utiliser l'option TLSVnc <code>vncserver -SecurityTypes TLSVnc</code></p>
<p>Le mot de passe doit être ajouté et par défaut dans ce cas c'est le nom de la machine <code>raspife4</code>, <code>raspife3</code>, <code>raspife3P</code> ou <code>raspife2</code> qui est utilisé. (Suivant les versions et les configurations le mot de passe peut-être tronqué à 8 caractères). Si la connexion <code>TLS</code> fonctionne il est possible de la mettre pr défaut dans le fichier <code>/etc/tigervnc/vncserver-config-defaults</code></p>
<div class="highlight"><pre><span></span>sudo jed /etc/tigervnc/vncserver-config-defaults
<span class="c1"># ajouter dans le para graphe correspondant à la sécurité</span>
<span class="nv">$SecurityTypes</span> <span class="o">=</span> <span class="s2">"TLSVnc"</span><span class="p">;</span>
</pre></div>
<p>Vérifier que le fichier soit exécutable puis relancer le serveur.</p>
<p>Vérifier le fonctionnement en utilisant un outil d'affichache de terminaux comme <code>remmina</code>par exemple. </p>
<p>Pour mettre en place un service on ajoute un fichier de lancement dans le répertoire <code>/etc/systemd/system</code> avec la commande <code>sudo nano /etc/systemd/system/vncserver@.service</code> avec le contenu suivant :</p>
<div class="highlight"><pre><span></span><span class="o">[</span>Unit<span class="o">]</span>
<span class="nv">Description</span><span class="o">=</span>TigerVNC remote desktop server
<span class="c1">#After=sshd.service</span>
<span class="nv">After</span><span class="o">=</span>syslog.target network.target
<span class="o">[</span>Service<span class="o">]</span>
<span class="nv">Type</span><span class="o">=</span>simple
<span class="nv">User</span><span class="o">=</span>tsuser
<span class="nv">Group</span><span class="o">=</span>root
<span class="nv">PIDFile</span><span class="o">=</span>/home/%u/.vnc/%H:%i.pid
<span class="nv">ExecStartPre</span><span class="o">=</span>/bin/sh -c <span class="s1">'/usr/bin/tigervncserver -kill :%i > /dev/null 2>&1 || :'</span>
<span class="nv">ExecStart</span><span class="o">=</span>/usr/bin/tigervncserver :%i -geometry 1440x810 -alwaysshared -fg -SecurityTypes TLSVnc
<span class="o">[</span>Install<span class="o">]</span>
<span class="nv">WantedBy</span><span class="o">=</span>multi-user.target
</pre></div>
<p>Pour qu'il soit automatiquement lancé au démarrage il doit être déclaré avec la commande <code>sudo systemctl enable vncserver@1</code>. Vncserver est alors un service manipulable comme tous les autres services de la machine.</p>
<div class="highlight"><pre><span></span>sudo systemctl status vncserver@1
sudo systemctl start vncserver@1
sudo systemctl list-unit-files <span class="p">|</span> grep vnc
sudo systemctl list-units <span class="p">|</span> grep vnc
</pre></div>
<p>Notez que l'on peut lancer en parallèle plusieurs serveurs vnc sur plusieurs <code>displays</code> en augmentant son numéro d'ordre :
<code>vncserver@1</code>, <code>vncserver@2</code>, <code>vncserver@3</code>, etc...
Ne pas oublier d'arrêter ce ou ces service(s) quand on n'en a plus besoin pour éviter de broadcaster en permanence sur le réseau. Pour trouver la Raspberry Pi proposant un terminal serveur si on ne connait pas son adresse, il suffit de chercher une machine faisant du broadcast sur le port 5901, on trouvera bien sûr tous les serveurs faisant du broacast sur ce port...
La façon la plus simple est d'accéder via un tunnel ssh pour respecter les règles de sécurité, une fois sur la machine l'accès au display vnc se fait par mot de passe par défaut. </p>
<p>On se connecte en utilisant un client VNC par exemple xvncviewer ou remmina ou tout autre client de terminal server. Si on ne compte pas exploiter ce service au démarrage il faut le désactiver avec la commande <code>sudo systemctl disable vncserver@1</code> pour éviter de consommer inutilement des ressources.</p>
<p>Le service ainsi installé est aussi une commodité pour que les usagers qui arrivent pour la première fois sur la plateforme et qui ne sont pas habitués à l'usage de lignes de commande puissent travailler confortablement. Il est possible de proposer à tout usager de lancer lui même depuis son propre environnement une instance de vncserver (via la commande en ligne <code>vncserver</code>) qui lui permettra de se retrouver à distance dans son environnement personnalisé et pas dans l'environnement minimaliste de <code>tsuser</code>. Sans que cela n'ait été intensément testé il semble possible de cumuler le service en arrière plan et une instance personnelle de <code>vncserver</code> il y a cependant un risque de détérioration des performances et éventuellement un changement de numéro d'écran d'affichage qui peut être déroutant pour un utilisateur novice. Quoi qu'il en soit et quelle que soit la stratégie choisie noter que vncserver est une commande <strong>attachée à un utilisateur</strong> ce dernier doit impérativement configurer les paramètres de son vncserver avant le premier lancement pour avoir tout l'environnement opérationnel(choisir le mot de passe notamment).</p>
<h2><a name="head4.5.2"> </a> 4.5.2 Mise en place de <code>xrdp</code></h2>
<p>Un second protocole a été ajouté pour afficher l'écran de la raspberry à distance : <code>xrdp</code>. Ce protocole est utilisé par défaut par le système d'exploitation windows et peut aussi être utlisé sous linux. Ce dispositif est fourni par le logiciel <code>xrdp</code> qui permet d'afficher sur un écran distant l'écran de la raspberry comme le protocole <code>VNC</code>. Comme pour la solution précédente, ce protocole permet de ne pas avoir à connecter un clavier une souris et un écran à une raspberry Pi pour pouvoir l'utiliser. Vérifier si <code>xrdp</code> est installé.</p>
<div class="highlight"><pre><span></span>sudo dpkg -l xrdp
<span class="c1">#si non</span>
sudo apt install xrdp
</pre></div>
<p>Ajout de l'utilisateur xrdp dans le groupe ssl-cert.</p>
<div class="highlight"><pre><span></span>sudo adduser xrdp ssl-cert
</pre></div>
<p><code>xrdp</code>est installé et préconfiguré pour fonctionner comme un service géré comme les autres services par <code>systemctl</code>. Les 3 fichiers de configuration du service se trouvent dans <code>/lib/systemd/system</code> :</p>
<div class="highlight"><pre><span></span>xrdp-sesman.service
xrdp session manager
xrdp.service
</pre></div>
<p>Les fichiers de configuration de l'application sont dans <code>/etc/xrdp</code>, on modifie ci dessous le port et la profondeur de l'image. </p>
<div class="highlight"><pre><span></span>sudo cp /etc/xrdp/xrdp.ini /etc/xrdp/xrdp.ini.bak
sudo sed -i <span class="s1">'s/3389/3390/g'</span> /etc/xrdp/xrdp.ini
sudo sed -i <span class="s1">'s/max_bpp=32/#max_bpp=32\nmax_bpp=128/g'</span> /etc/xrdp/xrdp.ini
sudo sed -i <span class="s1">'s/xserverbpp=24/#xserverbpp=24\nxserverbpp=128/g'</span> /etc/xrdp/xrdp.ini
</pre></div>
<p>Démarrage du service :</p>
<div class="highlight"><pre><span></span>systemctl status dbus
<span class="c1"># s'il n'est pas actif </span>
sudo su
systemctl <span class="nb">enable</span> dbus
<span class="nb">exit</span>
sudo systemctl start dbus
<span class="c1"># dbus activé</span>
sudo systemctl start xrdp
</pre></div>
<p>Vérification du fonctionnement avec <code>sudo systemctl status xrdp</code>, vérification que <code>xrdp</code> est activé au démarrage avec <code>sudo systemctl is-enabled xrdp̀</code>.</p>
<p>L'affichage se fait à l'aide d'un client de serveur de terminaux <code>remmina</code> par exemple ou l'outil <code>connexion de bureau à distance</code> sur le <code>port 3390</code> soit : <code>IP.de.la.raspi:3390</code>.</p>
<h2><a name="head4.5.3"> </a> 4.5.3 (Seulement si besoin incontournable) Dégradation de la sécurité ou retour à <code>tightvncserver</code></h2>
<p>Le serveur de terminaux <code>VNC</code> installé est <code>tigervncserver</code> qui impose des règles de sécurité plus strictes que <code>tightvncserver</code> qui était proposé dans les images précédentes. Par défaut pour plus de simplicité la connection repose sur la mise en place du transfert du port d'affichage via un tunnel sécurisé classique que l'on démarre avec une commande ssh (qui peut sous windows être stockée dans un putty et exécutée avant le connecteur vnc). Si le serveur utilise le premier port (5901) la commande pour créer le tunnel sera :</p>
<div class="highlight"><pre><span></span>ssh -L <span class="m">5901</span>:127.0.0.1:5901 -N -f -l userOnTheServer server.ip
</pre></div>
<ul>
<li>userOnTheServer est le nom de l'utilisateur de la raspberryPi qui permet de créer le tunnel</li>
<li>server.ip est l'adresse IP de la raspberryPi serveur VNC</li>
</ul>
<p>Une fois le tunnel ouvert tout utilisateur de la machine locale pourra ouvrir l'écran à distance de la raspberryPi via VNC.</p>
<p>Il n'y a aucun problème avec l'univers linux mais il est possible que certains systèmes d'exploitation ne permettent pas de faire facilement des tunnels et d'utiliser cette fonctionnalité de <code>tigervnc</code> dans sa configuration par défaut, les deux protocoles ci-dessous permettent soit de diminuer la sécurité par défaut soit de revenit à <code>tightvncserver</code>. Ces manipulations <strong>ne sont pas recommandées</strong> et <strong>effectuées aux risques et périls de l'usager</strong>.</p>
<p>Pour permettre un service par authentification non sécurisée réalisée par mot de passe simple (comme le propose tightvnc par défaut) changer la ligne ci-dessous de fichier de service <code>/etc/systemd/system/vncserver@.service</code> </p>
<div class="highlight"><pre><span></span><span class="nv">ExecStart</span><span class="o">=</span>/usr/bin/tigervncserver :%i -geometry 1280x720 -alwaysshared -fg
</pre></div>
<p>en </p>
<div class="highlight"><pre><span></span><span class="nv">ExecStart</span><span class="o">=</span>/usr/bin/tigervncserver :%i -geometry 1280x720 -localhost no -alwaysshared -fg
</pre></div>
<p>Le même changement dans la ligne de commande produit les mêmes effets si tigervnc n'st pas utilisé comme service.</p>
<p>Pour revenir à <code>tightvnc</code></p>
<div class="highlight"><pre><span></span>sudo systemctl stop vncserver@1
sudo systemctl disable vncserver@1
sudo apt remove tiger*
sudo apt install tightvncserver
update-alternatives: utilisation de « /usr/bin/tightvncserver » pour fournir « /usr/bin/vncserver » <span class="o">(</span>vncserver<span class="o">)</span> en mode automatique
update-alternatives: utilisation de « /usr/bin/Xtightvnc » pour fournir « /usr/bin/Xvnc » <span class="o">(</span>Xvnc<span class="o">)</span> en mode automatique
update-alternatives: utilisation de « /usr/bin/tightvncpasswd » pour fournir « /usr/bin/
sudo rm /etc/X11/Xvnc-session
sudo vncserver
</pre></div>
<p>Cette commande régénère le fichier <code>/etc/X11/Xvnc-session</code> dont la nouvelle version est visible avec <code>cat /etc/X11/Xvnc-session</code>.</p>
<div class="highlight"><pre><span></span><span class="ch">#!/bin/sh</span>
<span class="c1">#xrdb $HOME/.Xresources</span>
xsetroot -solid grey
<span class="c1">#x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &</span>
<span class="c1">#x-window-manager &</span>
<span class="c1"># Fix to make GNOME work</span>
<span class="nb">export</span> <span class="nv">XKL_XMODMAP_DISABLE</span><span class="o">=</span><span class="m">1</span>
/etc/X11/Xsession
</pre></div>
<p>Reconstruire les fichiers permettant le fonctionnement nominal du dispositif.</p>
<div class="highlight"><pre><span></span>sudo su tsuser
rm .vnc/*
vncpasswd » <span class="o">(</span>vncpasswd<span class="o">)</span> en mode automatique
vncserver -geometry 1280x720 -depth <span class="m">24</span> :1
New <span class="s1">'X'</span> desktop is raspife3P:1
Creating default startup script /etc/X11/Xvnc-session
Starting applications specified in /etc/X11/Xvnc-session
Log file is /home/tsuser/.vnc/raspife3P:1.log
</pre></div>
<p>Redéfinir et renommer le fichier de service en <code>vncserver.service</code>.</p>
<div class="highlight"><pre><span></span><span class="o">[</span>Unit<span class="o">]</span>
<span class="nv">Description</span><span class="o">=</span>TigerVNC remote desktop server
<span class="c1">#After=sshd.service</span>
<span class="nv">After</span><span class="o">=</span>syslog.target network.target
<span class="o">[</span>Service<span class="o">]</span>
<span class="nv">Type</span><span class="o">=</span>simple
<span class="nv">User</span><span class="o">=</span>tsuser
<span class="nv">Group</span><span class="o">=</span>root
<span class="nv">PIDFile</span><span class="o">=</span>/home/tsuser/.vnc/raspife3P:1.pid
<span class="nv">ExecStartPre</span><span class="o">=</span>/bin/sh -c <span class="s1">'/usr/bin/vncserver -kill :1 > /dev/null 2>&1 || :'</span>
<span class="nv">ExecStart</span><span class="o">=</span>/usr/bin/vncserver -geometry 1280x720 -depth <span class="m">24</span> :1
<span class="nv">ExecStop</span><span class="o">=</span>/usr/bin/vncserver -kill :1
<span class="o">[</span>Install<span class="o">]</span>
<span class="nv">WantedBy</span><span class="o">=</span>multi-user.target
</pre></div>
<h2><a name="head4.6"> </a> 4.6 Modification des accès au <code>GPIO</code> et à la caméra</h2>
<p>Pour le bon fonctionnement du projet il est souhaitable de répartir les usagers dans des groupes et il faudra donc créer ces groupes. Nous aurons besoin d'un groupe pour gérer les accès au bus <code>GPIO</code> de la raspberry, pour le moment nous allons configurer les accès aux ressources.</p>
<p>Pour un fonctionnement sécurisé permettant l'accès de plusieurs utilisteurs au bus <code>GPIO</code>sans privilèges particuliers il est nécessaire d'opérer certainesmodifications donnant à un utilisateur ordinaire membre du groupe <code>gpio</code>le droit d'accéder aux ressources connectées au bus <code>GPIO</code>. On rajoute le fichier <code>50-gpio.rules</code> au répertoire <code>/etc/udev/rules.d</code> avec la commande ci-dessous et on ajoute le contenu suivant (on termine avec Ctrl-D):</p>
<div class="highlight"><pre><span></span>sudo su
cat > /etc/udev/rules.d/50-gpio.rules
</pre></div>
<div class="highlight"><pre><span></span><span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"gpio*"</span>, <span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c 'chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio; \</span>
<span class="s2">chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio; \</span>
<span class="s2">chown -R root:gpio /sys/devices/platform/soc/3f200000.gpio && chmod -R 770 /sys/devices/platform/soc/3f200000.gpio; \</span>
<span class="s2">chown -R root:gpio /sys/devices/platform/soc/soc:virtgpio && chmod -R 770 /sys/devices/platform/soc/soc:virtgpio; \</span>
<span class="s2">chown -R root:gpio /sys/bus/platform/drivers/pinctrl-bcm2835 && chmod -R 770 /sys/bus/platform/drivers/pinctrl-bcm2835 '"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"bcm2835-gpiomem"</span>, <span class="nv">KERNEL</span><span class="o">==</span><span class="s2">"gpiomem"</span>, <span class="nv">GROUP</span><span class="o">=</span><span class="s2">"gpio"</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">"0660"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"gpio"</span>, <span class="nv">KERNEL</span><span class="o">==</span><span class="s2">"gpiochip*"</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">"add"</span>, <span class="se">\</span>
<span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c 'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport ; \</span>
<span class="s2">chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"gpio"</span>, <span class="nv">KERNEL</span><span class="o">==</span><span class="s2">"gpio*"</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">"add"</span>, <span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c \</span>
<span class="s2">'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; \</span>
<span class="s2">chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'"</span>
</pre></div>
<p>Pour l'urtilisation du <code>SPI</code> Le fichier <code>50-gpio.rules</code> prend la forme :</p>
<div class="highlight"><pre><span></span><span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"gpio*"</span>, <span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c 'chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio; \</span>
<span class="s2">chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio; \</span>
<span class="s2">chown -R root:gpio /sys/devices/platform/soc/fe200000.gpio && chmod -R 770 /sys/devices/platform/soc/fe200000.gpio; \</span>
<span class="s2">chown -R root:gpio /sys/devices/platform/soc/soc:virtgpio && chmod -R 770 /sys/devices/platform/soc/soc:virtgpio; \</span>
<span class="s2">chown -R root:gpio /sys/bus/platform/drivers/pinctrl-bcm2835 && chmod -R 770 /sys/bus/platform/drivers/pinctrl-bcm2835 '"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"spidev*"</span>, <span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c 'chown -R root:gpio /sys/class/spidev && chmod -R 770 /sys/class/spidev; \</span>
<span class="s2">chown -R root:gpio /sys/devices/platform/soc/fe204000.spi/spi_master/spi0/spi0.0/spidev && \</span>
<span class="s2">chmod -R 770 /sys/devices/platform/soc/fe204000.spi/spi_master/spi0/spi0.0/spidev; \</span>
<span class="s2">chown -R root:gpio /dev/spidev0.0 && chmod -R 770 /dev/spidev0.0'"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"bcm2835-gpiomem"</span>, <span class="nv">KERNEL</span><span class="o">==</span><span class="s2">"gpiomem"</span>, <span class="nv">GROUP</span><span class="o">=</span><span class="s2">"gpio"</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">"0660"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"gpio"</span>, <span class="nv">KERNEL</span><span class="o">==</span><span class="s2">"gpiochip*"</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">"add"</span>, <span class="se">\</span>
<span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c 'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport ; \</span>
<span class="s2">chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"gpio"</span>, <span class="nv">KERNEL</span><span class="o">==</span><span class="s2">"gpio*"</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">"add"</span>, <span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c \</span>
<span class="s2">'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; \</span>
<span class="s2">chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'"</span>
</pre></div>
<p>on modifie aussi la ligne de commande dans <code>/boot/cmdline.txt</code> en ajoutant en fin de ligne <code>spidev.bufsiz=32768</code> et enfin on ajoute l'activation du bus <code>SPI</code> et le contrôle de la fréquence dans le fichier <code>/boot/config.txt</code> pour contrôler un rubande leds librairie <code>rpi_ws281x</code></p>
<div class="highlight"><pre><span></span><span class="nv">dtparam</span><span class="o">=</span><span class="nv">spi</span><span class="o">=</span>on <span class="c1"># activation du bus SPI</span>
<span class="c1"># to use SPI for ledstrip</span>
<span class="nv">core_freq_min</span><span class="o">=</span><span class="m">500</span> <span class="c1"># pour la raspi4</span>
<span class="c1"># core_freq=250 # pour la pi3</span>
</pre></div>
<p><strong>Attention aux conflits en activant le bus SPI</strong></p>
<p>Tout comme le GPIO l'USB n'est pas accessible aux utilisateurs de base , l'utilsateur <code>weewx</code> est un utilisateur non privilégié qui doit pouvoir accéder à la station via une interface USB on ajoute au même endroit le fichier <code>40-usbweewx.rules</code> avec la commande </p>
<div class="highlight"><pre><span></span>cat > /etc/udev/rules.d/40-usbweewx.rules
</pre></div>
<p>on ajoute le contenu suivant :</p>
<div class="highlight"><pre><span></span><span class="c1"># make any te923 station connected via usb accessible to non-root</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"usb"</span>, ATTR<span class="o">{</span>idVendor<span class="o">}==</span><span class="s2">"1130"</span>, ATTR<span class="o">{</span>idProduct<span class="o">}==</span><span class="s2">"6801"</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">"add"</span>, <span class="nv">GROUP</span><span class="o">=</span><span class="s2">"weewx"</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">"0664"</span>
<span class="c1"># make any Vantage Pro2 station connected via usb accessible to non-root</span>
<span class="c1">#SUBSYSTEM=="usb", ATTR{idVendor}=="10c4", ATTR{idProduct}=="ea60", ACTION=="add", GROUP="weewx", MODE="0664"</span>
</pre></div>
<p>Lorsque la caméra est connectée, son accès est réservé par défaut à l'administrateur il est nécessaire d'ajouter un fichier de configuration supplémentaire <code>60-cam.rules</code> au répertoire <code>/etc/udev/rules.d</code> avec la commnde <code>sudo nano ./etc/udev/rules.d/60-cam.rules</code> et on ajoute le contenu suivant :</p>
<div class="highlight"><pre><span></span>cat > /etc/udev/rules.d/60-cam.rules
</pre></div>
<div class="highlight"><pre><span></span><span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"vchiq"</span>, <span class="nv">GROUP</span><span class="o">=</span><span class="s2">"video"</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">"0660"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"vc-sm"</span>,GROUP<span class="o">=</span><span class="s2">"video"</span>,MODE<span class="o">=</span><span class="s2">"0660"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"bcm2708_vcio"</span>,GROUP<span class="o">=</span><span class="s2">"video"</span>,MODE<span class="o">=</span><span class="s2">"0660"</span>
</pre></div>
<p>Dès que la caméra sera détectée (voir plus loin) tous les membres du groupe <code>video</code> pourront l'utiliser.</p>
<h1><a name="head5"> </a> 5. Utilisation de la Raspberrry en point d'accès web (Hotspot)</h1>
<p>Les images proposées permettent d'utiliser la Raspberry Pi au sein d'un réseau existant, il est aussi possible de la transformer en point d'accès sur un WIFI qu'elle crée et administre avec ou pas des fonctions de passerelle vers internet.
Il est possible grace à l'interface graphique de <code>connman</code> de créer un réseau wifi dont la raspberry est le routeur, suivre la documentation pour activer le <code>tethering</code>.</p>
<p>Construire soi même une interface réseau avec des contraintes particulières est abordé dans un <a href="http://blog.climatetmeteo.fr/GerardVidal/hotspotraspi23.html#head1">autre article de ce blog</a>. Attention mettre en oeuvre cette configuration perturbe les règles de sécurité énoncées ici, veillez à bien configurer votre réseau en fonction de vos besoins et contraintes.</p>
<h1><a name="head6"> </a> 6. Configurations particulières avancées</h1>
<p>La suite des configurations ajoute quelques services utiles.</p>
<h2><a name="head6.1"> </a> 6.1 Image <strong><em>buster ou bullseye</em></strong> "tous terrains Raspberry Pi 3 3B+ou 4" permettant entre autres l'apprentissage de la programmation</h2>
<h3><a name="head6.1.1"> </a> 6.1.1 Compilation d'un cmake récent</h3>
<p>Dans les versions stables de <code>debian</code> la version de <code>cmake</code> peut s'avérer en retard si c'est le cas compiler depuis les sources sinon installer le paquet standard. Attention les compilations peuvent s'avérer extrêmement longues sur les petits modèles de raspis (PI0 P1 notamment).</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/Cmake
<span class="nb">cd</span> Logiciels/Cmake
wget https://github.com/Kitware/CMake/releases/download/v3.21.5/cmake-3.21.5.tar.gz
tar xvfz cmake-3.21.5.tar.gz
<span class="nb">cd</span> cmake-3.21.5
./bootstrap <span class="o">&&</span> make -j4
sudo make install
</pre></div>
<h3><a name="head6.1.2"> </a> 6.1.2 Ajout de fontes</h3>
<p>Vérifier s'il ne manque pas des fontes, si oui les installer.</p>
<div class="highlight"><pre><span></span>sudo dpkg -l fonts-liberation gsfonts libxfont-dev libfontenc-dev ttf-mscorefonts-installer xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable xfonts-utils
sudo apt install fonts-liberation gsfonts libxfont-dev libfontenc-dev ttf-mscorefonts-installer xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable xfonts-utils
</pre></div>
<h3><a name="head6.1.3"> </a> 6.1.3 Activation de la caméra raspberry Pi</h3>
<p>L'activation de la caméra se passe en deux étapes car par défaut la détection de la caméra n'est pas activée, cette situation est probablement due à la volonté de ne pas "gaspiller les ressources limitées de la Raspberry. Dans cette optique il est conseillé de n'activer la caméra qu'uniquement quand on va l'utiliser car contrairement à d'autres fonctionnalités celle ci immobiliose des ressources.</p>
<h4><a name="head6.1.3.1"> </a> 6.1.3.1 Détection de la caméra et accélération graphique</h4>
<p>Pour détecter la camera ou permettre l'accélération graphique pour la <code>Pi4</code> il est nécesaire de modifier la configuration du fichier de boot avec la commande <code>sudo nano /boot/firmware/config.txt</code> la fin du fichier est recopiée ci-dessous. Pour les <code>Pi4</code> du fait de l'activation de l'accélérateur 128Mo de mémoire sont déjà affectés au proc graphique il reste seulement à activer le <code>start_x</code>.</p>
<div class="highlight"><pre><span></span><span class="nv">gpu_mem</span><span class="o">=</span><span class="m">16</span>
initramfs initramfs-4.13.16-v7 followkernel
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">i2c_arm</span><span class="o">=</span>on
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">spi</span><span class="o">=</span>on
</pre></div>
<p>La modifier pour lui donner l'aspect suivant</p>
<div class="highlight"><pre><span></span>initramfs initramfs-4.13.16-v7 followkernel
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">i2c_arm</span><span class="o">=</span>on
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">spi</span><span class="o">=</span>on
<span class="nv">gpu_mem</span><span class="o">=</span><span class="m">16</span> <span class="c1"># Comment this line when activating the camera to provide more memory</span>
<span class="c1"># camera activation</span>
<span class="c1"># To activate camera at least uncomment the two following lines</span>
<span class="c1"># AND comment the line above gpu_mem=16</span>
<span class="c1">#</span>
<span class="c1">#start_x=1 # essential</span>
<span class="c1">#gpu_mem=128 # at least, or maybe more if you wish</span>
<span class="c1">#</span>
</pre></div>
<p>Pour activer la camera il faut commenter la ligne <code>gpu_mem=16</code> et décommenter les deux lignes <code>start_x=1</code> et <code>gpu_mem=128</code> puis impérativement <strong>rebooter</strong>. Une fois le reboot effectué si la caméra est connectée elle apparait aux côtés des autres périphériques sous le nom <code>/dev/vchiq</code></p>
<p>Pour l'accélération graphique de la <code>Pi4</code> la configuration est correcte (caméra non activée) elle doit être de la forme :</p>
<div class="highlight"><pre><span></span><span class="c1"># uncomment to overclock the arm. 700 MHz is the default.</span>
<span class="c1">#arm_freq=800</span>
<span class="nv">force_turbo</span><span class="o">=</span><span class="m">1</span>
<span class="nv">boot_delay</span><span class="o">=</span><span class="m">1</span>
<span class="nv">dtoverlay</span><span class="o">=</span>pi3-disable-bt
<span class="nv">enable_uart</span><span class="o">=</span><span class="m">0</span>
initramfs initramfs-5.10.7-v8 followkernel
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">i2c_arm</span><span class="o">=</span>on
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">spi</span><span class="o">=</span>on
<span class="nv">max_framebuffers</span><span class="o">=</span><span class="m">2</span>
<span class="nv">arm_64bit</span><span class="o">=</span><span class="m">1</span>
<span class="nv">cmdline</span><span class="o">=</span>cmdline.txt
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">audio</span><span class="o">=</span>on
<span class="nv">gpu_mem</span><span class="o">=</span><span class="m">128</span>
<span class="nv">dtoverlay</span><span class="o">=</span>vc4-fkms-v3d, cma-128
</pre></div>
<h4><a name="head6.1.3.2"> </a> 6.1.3.2 Ajout des logiciels de pilotage de la caméra</h4>
<p>La caméra et le module de pilotage ne sont hélas pas des modules standard de la distribution Debian et il est hélas nécessaire de les compiler. La manipulation a effectuer est détaillée ci-dessous :</p>
<p>Créer un répertoire d'accueil des programmes puis se positionner dans ce dossier. Télécharger les outils de compilation croisée puis les sources des librairies qui seront utilisées.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/Cam
<span class="nb">cd</span> !$
git clone https://github.com/raspberrypi/userland.git
</pre></div>
<p>se déplacer dans le dossier userland reçu et taper la commande <code>./buildme</code> qui lance la création des logiciels nécesaires à la mise en oeuvre de la caméra, pour une architercure <code>644 bits</code> ajouter l'option <code>--aarch64</code>.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> userland
./buildme <span class="o">[</span>--aarch64<span class="o">]</span>
</pre></div>
<p>L'exécution devrait se passer sans encombre et tous les outils nécessaires sont stockés dans le dossier <code>/opt/vc</code>. Pour que les programmes trouvent ces librairies il est nécessaire de rajouter un fichier dans le répertoire listant les librairies utilisées avec la commande <code>sudo nano /etc/ld.so.conf.d/userland.conf</code> en ajoutant dans le fichier :</p>
<div class="highlight"><pre><span></span><span class="c1">#Access to Userland libraries</span>
/opt/vc/lib
</pre></div>
<p>Appliquer la transformation avec <code>sudo ldconfig</code></p>
<p>Recopier ensuite le contenu des docciers de <code>/opt/vc</code> hormis <code>lib</code> et <code>src</code> dans <code>/usr/local</code> :</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> build
<span class="k">for</span> i in bin include <span class="o">[</span>sbin<span class="o">]</span> <span class="o">[</span>share<span class="o">]</span><span class="p">;</span> <span class="k">do</span> sudo cp -r /opt/vc/<span class="nv">$i</span>/* /usr/local/<span class="nv">$i</span><span class="p">;</span> <span class="k">done</span>
</pre></div>
<p>Pour utiliser la caméra avec un utilisateur <code>non root</code> et si cela n'a pas été fait dans la phase initiale ne pas oublier d'ajouter dans <code>/etc/udev/rules.d</code> le fichier <code>60-cam.rules</code> avec la commande <code>sudo nano /etc/udev/rules.d/60-cam.rules</code> avec le contenu suivant :</p>
<div class="highlight"><pre><span></span><span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"vchiq"</span>, <span class="nv">GROUP</span><span class="o">=</span><span class="s2">"video"</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">"0660"</span>
</pre></div>
<p>À chaque démarrage le groupe <code>video</code> sera autorisé à acccéder à la resource <code>/dev/vchiq</code> ; cela peut être fait manuellement pour cela en cas de besoin exécuter les deux commandes suivantes :</p>
<div class="highlight"><pre><span></span>sudo chown root.video /dev/vchiq
sudo chmod g+rw !$
<span class="c1"># En cas de problème pour avoir les infos sur /dev/vchiq</span>
sudo udevadm info --name<span class="o">=</span>/dev/vchiq
</pre></div>
<p>Pour prendre une photo utiliser la commande : <code>raspistill -q 100 -o tetst.jpg -w 1280 -h 720 -v</code> (de nombreuses options sont disponibles). Pour streamer une video sur le serveur rtmp tremplin de l'ENS :
<code>raspivid -t 0 -w 640 -h 360 -o - | ffmpeg -re -i - -c:v libx264 -f flv rtmp://visioweb.tremplin.ens-lyon.fr/live/XXXXXX</code> ; XXXXX est le mot de passe servant à ouvrir le flus de lecture. Il est certainement possible d'améliorer le rendu et la fluidité mais la gestion des paramètres reste délicate. Il est possible aussi que les paramètres de boot notamment la mémoire vidéo aient une importance.</p>
<p>Les outils de lafamille <code>raspi</code> sont installés via <code>tools.git</code> en cas de besoin mais non utiles et non déployés dans ce tutoriel, attention le déploiement de ces outils occupe une place importante.</p>
<div class="highlight"><pre><span></span>git clone https://github.com/raspberrypi/tools.git
</pre></div>
<h3><a name="head6.1.4"> </a> 6.1.4 Activation du réseau WIFI et du réseau filaire pour la production</h3>
<p>Comme nous l'avons vu plus haut l'interface réseau filaire est configurée de façon générique pour se connecter à tout réseau disponible. Cette connexion est suffisante pour réaliser toutes les configurations proposées dans ce document mais inadéquate pour une utilisation en production. Cependant la mise en place d'une configuration avancée adaptée à une interface particulière et un réseau particulier "figera" la situation et il faudra reconfigurer l'interface pour se connecter à un autre réseau. On devra réutiliser une des méthodes décrites dans le chapitre consacré au réseau adaptée aux besoins des utilisateurs</p>
<p>Si l'image en cours de création est destinée à être partagée avec d'autres usagers qui la cloneront il est recommandé de <strong>ne pas configurer le réseau filaire ni le WIFI</strong> comme expliqué ci-dessous, ce devra être fait par l'utilisateur final avec ses paramètres personnels; Si l'image en cours de création est destinée à être directement utilisée <strong>la configuration ci-dessous doit être effectuée</strong></p>
<p>Si lors de la configuration une interface secondaire parasite est créée utiliser les commandes suivantes pour s'en débarrasser :</p>
<div class="highlight"><pre><span></span>ip addr flush dev wlan0
sudo shutdown -r
</pre></div>
<h4><a name="head6.1.4.1"> </a> 6.1.4.1 Configurer le réseau filaire</h4>
<p>Pour configurer le réseau filaire il peut être nécessaire de supprimer la désignation générique de l'interface (eth0) et la remplacer par la valeur construite au boot à partir de l'adresse Mac (<strong>Attention</strong> Cette valeur est unique et désigne une seule Raspberry Pi "physique" l'image sera donc inadaptée à toute autre Raspberry Pi !). On obtient le nom de l'interface réseau par la commande <code>ip token</code>.</p>
<p>Si la valeur est <code>eth0</code> c'est que la version antérieure de la configuration a été utilisée lors de la création de l'image et dans ce cas le nom de l'interface est toujours le même aucune manipulation ne doit être effectuée.</p>
<p>Si la valeur diffère de <code>eth0</code> elle doit être substituée à la valeur générique <code>enx*</code> figurant dans le fichier <code>50-wired.network</code>.</p>
<div class="highlight"><pre><span></span><span class="nv">Name</span><span class="o">=</span>enx#########
<span class="nv">Host</span><span class="o">=</span>raspife3
</pre></div>
<h4><a name="head6.1.4.2"> </a> 6.1.4.2 Configurer le WIFI</h4>
<p>La configuration du WIFI est plus délicate car il est nécessaire de fournir des mots de passe ou des paramètres propres à chaque réseau comme cela a été décrit plus haut. Il est bien sûr possible de "remplir à la main" les fichiers de configuration mais toute erreur même minime (espace oublié, majuscule/minuscule, etc...) risque d'entrainer l'arrêt du réseau. D'autre part ce travail impose la manipulation par l'administrateur de données confidentielles en clair ce qui est à proscrire pour un usager ordinaire. Il est donc préférable d'utiliser les outils graphiques standards via la connexion au terminal serveur installé plus haut. (La seule exception à cette règle concerne la création d'une connexion via eduroam qui requiert que l'on ajoute à la main le fichier spécifique pour l'eduroam utilisé dans <code>/var/lib/connman</code>)</p>
<p>On se connecte avec un outil d'affichage de terminal à distance utilisant le protocole VNC ou xrdp, par défaut les services VNC et xrdp sont portés par <code>tsuser</code> et le mot de passe configuré plus haut. Le logiciel installé par défaut est <code>connman</code> (cf plus haut). Cliquer en bas à droite dans la barre de menus sur l'icône réseau, la panneau affiché apparaît configurer le réseau WIFI que l'on souhaite utiliser. Si l'icone réseau n'apparait pas lancer dans le menu des applications <code>connmanUI</code>.</p>
<h2><a name="head6.2"> </a> 6.2 Installation et mise à jour de l'environnement logiciel</h2>
<p>Les forges libres proposent de nombreux logiciels qui peuvent facilement être ajoutés à la Raspberry Pi, même s'il faut les compiler. La manipulation n'est pas compliquée et requiert des connaissances peu avancées à titre d'exemple nous installerons sur notre image les logiciels <code>mraa</code> et <code>upm</code> initiés par Intel et maintenus par eclipse sur <code>github</code>. Le premier donne accès à la maîtrise du bus <code>GPIO</code> le second propose plusieurs centaines de "drivers" pour des leds, capteurs et effecteurs du monde des "makers". C'est l'équivalent de ce que les utilisateurs des arduino appellent des librairies sauf que dans le cas de la Raspberry que nous construisons nous allons réellement construire des librairies au sens informatique du terme dont les composants pourront être appelés depuis les langages <code>C</code>, <code>C++</code>, <code>python</code>, <code>Java</code>, <code>Node-JS</code>. Cela permettra d'écrire des programmes simples permettant d'interagir avec des capteurs météo des leds ou tous autres composants électroniques connectables. (voir nos <a href="https://depot.tremplin.ens-lyon.fr/Tremplin-des-Sciences/CahiersDeProgrammesCodage/files/tip/">cahiers de programmes pour jupyter</a>.</p>
<p>La première étape de l'installation consiste à créer pour chaque logiciel un espace pour stocker les codes puis de les télécharger dans cet espace depuis les forges opensource ou libres. Nous allons créer une hierarchie de dossiers ayant pour racine le dossier <code>Logiciels</code>; on y retrouvera par exemple un dossier <code>IoT</code> (Internet of Things) contenant un dossier <code>mraa</code> et un dossier <code>upm</code>. </p>
<h3><a name="head6.2.1"> </a> 6.2.1 Récupération et installation de Node.js</h3>
<p><strong>ATTENTION-1 en ce moment 2022-01 la compilation croisée de mraa et upm avec nodejs ne fonctionne qu'avec l'application d'un <code>patch</code> </strong> (voir plus bas).</p>
<p><strong>ATTENTION-2 il n'existe pas de version nodeJS pour armel, la compilation croisée standard sur debian échoue ainsi que la compilation sur la PiZero nodeJS est désactivésur la PiZero</strong></p>
<p>Node.js évolue très rapidement avec un souci peu prononcé pour la compatibilité ascendante, il est souhaitable de vérifier s'il n'existe pas une nouvelle version <strong>compatible</strong> depuis l'écriture de ce blog, vérifier la version à jour sur le site <a href="https://nodejs.org">Node.js</a> nous utiliserons ici la version 16.11.0 avec npm 8.0.0). </p>
<p>Il y a deux stratégies possibles pour utiliser <code>nodejs</code> la première est une stratégie par utilisateur qui est la plus souple en utilisant nvm qui permet de disposer de plusieurs versions de node en parallèle et de s'adapter aux compatibilités/incompatibilités entre node et le reste de l'environnement. Pour le projet <em>Tremplin</em> il nous semble plus pertinent d'installer ce logiciel comme une ressource commune afin que tous les usagers soient dans la même situation et en cas de besoin il est simple pour chacun d'ajouter <code>nvm</code> dans son espace personnel.</p>
<h4><a name="head6.2.1.1"> </a> 6.2.1.1 Récupération et installation de <code>nvm</code> (stratégie par utilisateur non déployée par défaut)</h4>
<p>Vérifier la version à jour de <code>nvm</code> sur la <a href="https://github.com/nvm-sh/nvm">forge github</a> puis télécharger installer avec la commande suivante :</p>
<div class="highlight"><pre><span></span>curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh <span class="p">|</span> bash
</pre></div>
<p>Pour lancer <code>nvm</code> la première fois exécuter les 3 commandes ci-dessous si elles n'ont pas été automatiquement exécutées par le script ou si elles eont généré des messages d'erreur :</p>
<div class="highlight"><pre><span></span><span class="nb">export</span> <span class="nv">NVM_DIR</span><span class="o">=</span><span class="s2">"</span><span class="nv">$HOME</span><span class="s2">/.nvm"</span>
<span class="o">[</span> -s <span class="s2">"</span><span class="nv">$NVM_DIR</span><span class="s2">/nvm.sh"</span> <span class="o">]</span> <span class="o">&&</span> <span class="se">\.</span> <span class="s2">"</span><span class="nv">$NVM_DIR</span><span class="s2">/nvm.sh"</span>
<span class="o">[</span> -s <span class="s2">"</span><span class="nv">$NVM_DIR</span><span class="s2">/bash_completion"</span> <span class="o">]</span> <span class="o">&&</span> <span class="se">\.</span> <span class="s2">"</span><span class="nv">$NVM_DIR</span><span class="s2">/bash_completion"</span>
</pre></div>
<p>verifier la situation et charger les versions de <code>nodejs</code> désirées (ici la dernière stable tet la LTS puis on utilise la dernière version).</p>
<div class="highlight"><pre><span></span><span class="nb">source</span> ~/.bashrc
nvm ls
<span class="c1"># N/A</span>
<span class="c1">#iojs -> N/A (default)</span>
<span class="c1">#node -> stable (-> N/A) (default)</span>
<span class="c1">#unstable -> N/A (default)</span>
nvm install <span class="m">16</span>.11.0
<span class="c1">#Downloading and installing node v16.11.0...</span>
<span class="c1">#Downloading https://nodejs.org/dist/v16.11.0/node-v16.11.0-linux-armv7l.tar.xz...</span>
<span class="c1">####################################################################### 100,0%</span>
<span class="c1">#Computing checksum with sha256sum</span>
<span class="c1">#Checksums matched!</span>
<span class="c1">#Now using node v16.11.0 (npm v8.0.0)</span>
<span class="c1">#Creating default alias: default -> 16.11.0 (-> v16.11.0)</span>
nvm install <span class="m">14</span>.18.0
<span class="c1">#Downloading and installing node v14.18.0...</span>
<span class="c1">#Downloading https://nodejs.org/dist/v14.18.0/node-v14.18.0-linux-armv7l.tar.xz...</span>
<span class="c1">####################################################################### 100,0%</span>
<span class="c1">#Computing checksum with sha256sum</span>
<span class="c1">#Checksums matched!</span>
<span class="c1">#Now using node v14.18.0 (npm v6.14.15)</span>
ens-ife@raspife4:~$ nvm use <span class="m">16</span>.11.0
<span class="c1">#Now using node v16.11.0 (npm v8.0.0)</span>
</pre></div>
<p>Pour supprimer nvm et toutes les versions installées enlever les lignes contenant <code>NVM</code> dans <code>.bashrc</code> pui supprimer le dossier <code>.nvm</code> :</p>
<div class="highlight"><pre><span></span>rm -r ~/.nvm
</pre></div>
<h4><a name="head6.2.1.2"> </a> 6.2.1.2 Récupération et installation de <code>nodejs</code></h4>
<p>Créer le dossier pour accueillir le logiciel et le télécharger.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/Node
<span class="nb">cd</span> !$
</pre></div>
<p>Deux méthodes sont possibles soit on utilise les binaires précompilés soit on utilise les source sque l'on recompile pour les raspi 2-3 les versions précompilées fonctionnent correctement ainsi que pour les pi4 32 bits et Pi4-64 bits, pour la Pi0 il faut recompiler.</p>
<p>Vérifier la version et télécharger depuis <a href="https://nodejs.org">le site</a> le binaire ou les sources de la version choisie (ici 16.11.0)</p>
<div class="highlight"><pre><span></span><span class="c1">#Téléchargement des binaires pour PI3 32 bits</span>
wget https://nodejs.org/dist/v17.0.1/node-v17.0.1-linux-armv7l.tar.xz
tar xvfJ node-v17.0.1-linux-armv7l.tar.xz
<span class="nb">cd</span> node-v17.0.1-linux-armv7l
<span class="k">for</span> i in bin include lib share<span class="p">;</span> <span class="k">do</span> sudo cp -r <span class="nv">$i</span>/* /usr/local/<span class="nv">$i</span><span class="p">;</span> <span class="k">done</span>
<span class="c1">#Téléchargement des binaires pour PI4 en 64 bits</span>
<span class="c1"># wget https://nodejs.org/dist/v17.0.1/node-v17.0.1-linux-arm64.tar.xz</span>
<span class="c1"># tar xvfJ node-v17.0.1-linux-arm64.tar.xz</span>
<span class="c1"># cd node-v17.0.1-linux-arm64</span>
<span class="c1"># for i in bin include lib share; do sudo cp -r $i/* /usr/local/$i; done</span>
<span class="c1">#</span>
<span class="c1">#Téléchargement des binaires pour PiZero</span>
<span class="c1">#wget https://unofficial-builds.nodejs.org/download/release/v17.5.0/node-v17.5.0-linux-armv6l.tar.xz</span>
<span class="c1">#tar xf node-v17.5.0-linux-armv6l.tar.xz</span>
<span class="c1">#for i in bin include lib share; do sudo cp -r $i/* /usr/local/$i; done</span>
<span class="c1">#Téléchargement de la source</span>
<span class="c1"># Si PiO ou Pi1 ou PI4-64 les versions récentes peuvent ne pas contenir de version binaire compilée il faut utiliser la source.</span>
<span class="c1"># wget https://nodejs.org/dist/v17.3.0/node-v17.3.0.tar.gz</span>
<span class="c1">#tar xvfJ node-v17.3.0.tar.gz</span>
<span class="c1">#cd node-v17.3.0</span>
<span class="c1">#./configure</span>
<span class="c1">#make</span>
<span class="c1">#sudo make install</span>
<span class="c1"># la compilation se chiffre en ... jours sur la Pi0!</span>
</pre></div>
<p>Création des liens supplémentaires</p>
<div class="highlight"><pre><span></span>sudo ln -s /usr/local/bin/node /usr/local/bin/nodejs
sudo npm install -g --upgrade npm node-gyp configurable-http-proxy
</pre></div>
<h3><a name="head6.2.2"> </a> 6.2.2 Récupération et construction du paquet swig</h3>
<p>L'outil swig est complexe et évolue systématiquement <strong>après</strong> les évolutions des langages qu'il permet de traduire. <code>nodeJS</code> évolue rapidement et fréquemment et swig n'est pas toujours compatible avc la dernière version. De même les versions de C++ se succèdent et proposent de nouvelles fonctionnalités utilisées dans les compilations croisées. La création d'un jeu de compilations croisées est délicate et doit être menée avec précaution. Le tableau ci-dessous présente les combinaisons qui ont été testées opérationnellement. les tests ne sont pas exhaustifs et il peut subsister quelques incompatibilités. Merci de nous les signaler.</p>
<table>
<thead>
<tr>
<th align="center">version de node</th>
<th align="center">version de swig</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center">10.16.3</td>
<td align="center">4.0.1</td>
</tr>
<tr>
<td align="center">10.19.0</td>
<td align="center">4.0.2</td>
</tr>
<tr>
<td align="center">15.0.1</td>
<td align="center">4.1.0</td>
</tr>
<tr>
<td align="center">16.11.0</td>
<td align="center">4.1.0</td>
</tr>
<tr>
<td align="center">17.0.1</td>
<td align="center"></td>
</tr>
</tbody>
</table>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/Swig
<span class="nb">cd</span> !$
git clone -b master --single-branch https://github.com/swig/swig.git
<span class="nb">cd</span> swig
./autogen.sh
./configure
</pre></div>
<p>SI les choses se passent normalement on obtient le message qui indique que nous pourrons utiliser nos librairies croisées avec les 4 langages :</p>
<div class="highlight"><pre><span></span>The SWIG test-suite and examples are configured <span class="k">for</span> the following languages:
java javascript perl5 python
</pre></div>
<p>poursuivre avec :</p>
<div class="highlight"><pre><span></span>make -j4
sudo make install
sudo dpkg -l libjavascriptcoregtk*
sudo apt install libjavascriptcoregtk-4.0-dev
sudo ln -s /usr/include/webkitgtk-4.0/JavaScriptCore /usr/include/JavaScriptCore
</pre></div>
<h3><a name="head6.2.3"> </a> 6.2.3 Récupération et construction du paquet libopenzwave</h3>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/OpenZwave
<span class="nb">cd</span> !$
git clone https://github.com/OpenZWave/open-zwave.git
<span class="nb">cd</span> open-zwave
make -j4
sudo make install
sudo doxygen -u
</pre></div>
<h3><a name="head6.2.4"> </a> 6.2.4 Récupération et construction du paquet modbus</h3>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/Modbus
<span class="nb">cd</span> !$
git clone https://github.com/stephane/libmodbus.git
<span class="nb">cd</span> libmodbus/
./autogen.sh
./configure
make -j4
sudo make install
</pre></div>
<p>En cas de problème utiliser avant <code>./configure</code>.</p>
<div class="highlight"><pre><span></span>libtoolize
aclocal
autoheader
autoconf
automake --add-missing
</pre></div>
<h3><a name="head6.2.5"> </a> 6.2.5 Récupération et construction du paquet tinyb</h3>
<div class="highlight"><pre><span></span>dpkg -l libglib2.0-dev
<span class="c1"># si manquante</span>
sudo apt install libglib2.0-dev
<span class="nb">cd</span> ~/Logiciels
mkdir Tinyb
<span class="nb">cd</span> Tinyb
git clone https://github.com/intel-iot-devkit/tinyb.git
<span class="nb">cd</span> tinyb/
mkdir build
<span class="nb">cd</span> build/
cmake -DCMAKE_INSTALL_PREFIX<span class="o">=</span>/usr ..
make -j4
sudo make install
</pre></div>
<h3><a name="head6.2.6"> </a> 6.2.6 Récupération et Construction de mraa et upm</h3>
<p>Certains modules requièrent beaucoup de RAM pour se compiler avec l'option -j4 du make la raspberryPi3 peut se figer, on passe alors avec l'option -j2 (qui utilise seulement 2 des coeurs du processeur). Il est possible d'ajouter un fichier de swap avec les commandes suivantes qui fournissent 512 Mo de swap, la compilation passe en -j4 mais la raspi3 swape choisissez l'option qui vous convient !</p>
<div class="highlight"><pre><span></span>sudo su
dd <span class="k">if</span><span class="o">=</span>/dev/zero <span class="nv">of</span><span class="o">=</span>/swapfile <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">count</span><span class="o">=</span><span class="m">524288</span>
chown root:root /swapfile
chmod <span class="m">0600</span> /swapfile
mkswap /swapfile
swapon /swapfile
</pre></div>
<p>Pour vérifier l'activité :</p>
<div class="highlight"><pre><span></span>swapon -s
free -m
</pre></div>
<p>Il est maintenant possible de construire les libraries mraa et upm qui permettent de <a href="https://iotdk.intel.com/docs/master/mraa/annotated.html">gérer le bus <code>GPIO</code></a> et un <a href="https://iotdk.intel.com/docs/master/upm/annotated.html">grand nombre de dispositifs électroniques</a></p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/IoT
<span class="nb">cd</span> !$
git clone https://github.com/eclipse/mraa
git clone https://github.com/eclipse/upm
</pre></div>
<p>Au 14/02/2022 le patch de <code>@nxhack</code> pour <code>swig</code> et <code>javascript</code> est nécessaire pour parvenir à compiler mraa. Fixer ensuite l'environnement <code>java</code> et lancer la compilation. Ajouter la compilation des interfaces <code>java</code> et <code>nodejs</code> en modifiant le fichier <code>CMakeLists</code> avec les valeurs ci-dessous.</p>
<p>Il est nécessaire de <strong>prendre en compte l'existence</strong> de <code>/dev/i2c-1</code> sans <code>/dev/i2c-0</code> car le code requiert qu'il existe le bus <code>0</code> (une demande de modification est en cours sur ecclipse), modifier le fichier <code>src/mraa.c</code> . Il est aussi nécessaire de créer le lien symbolique de <code>/dev/i2c-1</code> vers <code>/dev/i2c-0</code> la solution <code>sudo ln -s /dev/i2c-1 /dev/i2c-0</code> est opérationnelle mais <strong>ne fonctionne que pour la session en cours</strong>, pour créer un lien définitif il est nécessaire de créer une règle <code>udev</code>.</p>
<div class="highlight"><pre><span></span>jed CMakeLists.txt
option <span class="o">(</span>BUILDSWIGNODE <span class="s2">"Build swig node modules."</span> ON<span class="o">)</span>
option <span class="o">(</span>BUILDSWIGJAVA <span class="s2">"Build Java API."</span> ON<span class="o">)</span>
option <span class="o">(</span>USEPYTHON3TESTS <span class="s2">"Force tests to run with python3"</span> ON<span class="o">)</span>
</pre></div>
<div class="highlight"><pre><span></span>jed src/mraa.c
<span class="c1">#transformer</span>
<span class="k">if</span> <span class="o">(</span>mraa_file_exist<span class="o">(</span><span class="s2">"/sys/class/i2c-dev/i2c-0"</span><span class="o">))</span>
<span class="c1">#en</span>
<span class="k">if</span> <span class="o">(</span>mraa_file_exist<span class="o">(</span><span class="s2">"/sys/class/i2c-dev/i2c-0"</span><span class="o">)</span> <span class="o">||</span> mraa_file_exist<span class="o">(</span><span class="s2">"/sys/class/i2c-dev/i2c-1"</span><span class="o">))</span>
</pre></div>
<div class="highlight"><pre><span></span>wget https://patch-diff.githubusercontent.com/raw/eclipse/mraa/pull/1064.patch
patch -p1 < <span class="m">1064</span>.patch
mkdir build
<span class="nb">cd</span> build
<span class="nb">export</span> <span class="nv">JAVA_HOME</span><span class="o">=</span>/usr/lib/jvm/java-17-openjdk-armhf
<span class="c1">#export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-arm64 # pi4-64</span>
<span class="c1"># cmake -Wno-dev -DCMAKE_INSTALL_PREFIX=/usr ..</span>
cmake .. -Wno-dev -DCMAKE_INSTALL_PREFIX<span class="o">=</span>/usr -DENABLEEXAMPLES<span class="o">=</span><span class="m">0</span> -DBUILDSWIGNODE<span class="o">=</span>ON -DSWIG_EXECUTABLE<span class="o">=</span>/usr/local/bin/swig -DV8_ROOT_DIR<span class="o">=</span>/usr/local/include/node -DNODE_ROOT_DIR<span class="o">=</span>/usr/local/include/node -DPYTHON2LIBS_FOUND<span class="o">=</span>FALSE -DPYTHON2INTERP_FOUND<span class="o">=</span>FALSE
make -j4
sudo make install
</pre></div>
<p>En cas de besoin il est possible d'effacer ce qui a été installé par les compilations précédentes.</p>
<div class="highlight"><pre><span></span>sudo rm -r /usr/include/mraa* /usr/lib/arm-linux-gnueabihf/pkgconfig/mraa.pc /usr/lib/arm-linux-gnueabihf/libmraa* /usr/lib/python2.7/dist-packages/*mraa* /usr/lib/python3.7/dist-packages/*mraa* /usr/lib/node_modules/mraa /usr/share/mraa/examples /usr/bin/mraa*
ls
sudo rm -r /usr/include/upm /usr/lib/python2.7/dist-packages/upm /usr/lib/python3.7/dist-packages/upm /usr/lib/arm-linux-gnueabihf/pkgconfig/upm* /usr/lib/node_modules/jsupm* /usr/lib/arm-linux-gnueabihf/libupm* /usr/share/upm
</pre></div>
<div class="highlight"><pre><span></span><span class="nb">cd</span> ~/Logiciels/IoT/upm
wget https://github.com/eclipse/upm/pull/703/commits/c7d7718c21828883a4d8eea585b89185a1eaf150.patch
mv c7d7718c21828883a4d8eea585b89185a1eaf150.patch upmNXHack.patch
patch -p1 < upmNXHack.patch
</pre></div>
<p>Ajouter la compilation des interfaces <code>nodeJS</code> <code>java</code> en modifiant le fichier <code>CMakeLists</code> comme indiqué ci-dessous et modifier la version du compilateur 11 -> 17 :</p>
<div class="highlight"><pre><span></span>jed CMakeLists.txt
option <span class="o">(</span>BUILDSWIGNODE <span class="s2">"Build swig node modules."</span> ON<span class="o">)</span>
option <span class="o">(</span>BUILDSWIGJAVA <span class="s2">"Build Java API."</span> ON<span class="o">)</span>
<span class="nb">set</span> <span class="o">(</span>CMAKE_CXX_STANDARD <span class="m">17</span><span class="o">)</span> <span class="c1">#instead of 11</span>
<span class="nb">set</span> <span class="o">(</span>CMAKE_C_STANDARD <span class="m">17</span><span class="o">)</span> <span class="c1">#instead of 11</span>
</pre></div>
<p>Créer le dossier de travail et lancer la compilation.</p>
<div class="highlight"><pre><span></span>mkdir build
<span class="nb">cd</span> build
cmake -Wno-dev -DWERROR<span class="o">=</span>off -DCMAKE_INSTALL_PREFIX<span class="o">=</span>/usr ..
make -j4
sudo make install
</pre></div>
<p>Dans certaines situations(maintenant peut-être révolues) il a été nécessaire de recopier les modules python depuis <code>build/src/*/python?.?/*.py</code> vers <code>/usr/lib/dist-packages/upm</code></p>
<div class="highlight"><pre><span></span><span class="c1"># from build folder</span>
<span class="k">for</span> i in python2.7 python3.9 <span class="p">;</span> <span class="k">do</span> sudo cp src/*/<span class="nv">$i</span>/*.py /usr/lib/<span class="nv">$i</span>/dist-packages/upm/<span class="p">;</span> <span class="k">done</span>
<span class="k">for</span> i in python2.7 python3.9sudo <span class="p">;</span> <span class="k">do</span> sudo cp interfaces/<span class="nv">$i</span>/*.py /usr/lib/<span class="nv">$i</span>/dist-packages/upm/<span class="p">;</span> <span class="k">done</span>
</pre></div>
<p>Les programmes sont directement accessibles depuis les librairies python2, python3, Java, Javascript, C, C++.</p>
<h3><a name="head6.2.7"> </a> 6.2.7 Installation de compléments Python</h3>
<p>Un certain nombre de logiciels python sont installés par défaut pour satisfaire certains usages. Il est recommandé d'installer si besoin (tester avec <code>dpkg</code>)les librairies de développement suivantes qui fournissent les fichiers d'en-tête utilisés pour construire les outils python listés ci-dessous, sans ces librairies les installations avec <code>pip</code> ou pipenv n'aboutissent pas.</p>
<div class="highlight"><pre><span></span>dpkg -l libopenblas-dev libhdf5-dev libnetcdf-dev python3-pandas python3-rpi.gpio python3-netcdf4 python3-numpy python3-six python3-wheel python3-setuptools python3-folium
sudo apt install libopenblas-dev libhdf5-dev libnetcdf-dev python3-pandas python3-rpi.gpio python3-netcdf4 python3-numpy python3-six python3-wheel python3-setuptools python3-folium
sudo pip3 install --upgrade pandas netCDF4 numpy six wheel setuptools spidev folium pillow
<span class="nb">export</span> <span class="nv">CFLAGS</span><span class="o">=</span>-fcommon
sudo pip3 install RPi.GPIO
<span class="c1"># installer aussi dans l'environnement virtuel pour jupyter</span>
sudo su callisto
<span class="nb">cd</span> ~/JupyterLab/
pipenv shell
<span class="nb">export</span> <span class="nv">MAKEFLAGS</span><span class="o">=</span><span class="s2">"-j</span><span class="k">$(</span>nproc<span class="k">)</span><span class="s2">"</span>
pipenv install pandas netCDF4 numpy six wheel setuptools spidev folium pillow matplotlib
<span class="nb">export</span> <span class="nv">CFLAGS</span><span class="o">=</span>-fcommon
pipenv install RPi.GPIO
<span class="nb">export</span> <span class="nv">PIP_NO_CACHE_DIR</span><span class="o">=</span>off
pipenv lock --clear
</pre></div>
<p>Pour la <code>PiZero</code> ajouter la bibliothèque pour ADCCAD SPI</p>
<div class="highlight"><pre><span></span>sudo python3 -m pip install git+https://github.com/abelectronicsuk/ABElectronics_Python_Libraries.git
</pre></div>
<p>Pour avoir les démos du SPI avec la carte <code>ADCDAC Pi zero</code> cloner le dépôt, les programmes sont disponibles dans les cahiers d'exercices de la version météo de cette image.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> ~/Logiciels
mkdir ADCDAC-PiZero
git clone https://github.com/abelectronicsuk/ABElectronics_Python_Libraries.git
</pre></div>
<h2><a name="head6.3"> </a> 6.3 (Optionnel) Installation d'un simulateur graphique de réseau après avoir installé un docker</h2>
<div class="highlight"><pre><span></span>sudo apt purge docker lxc-docker docker-engine docker.io
sudo apt install apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg -o docker.gpg
sudo gpg --import docker.gpg
sudo add-apt-repository <span class="se">\</span>
<span class="s2">"deb [</span><span class="k">$(</span>dpkg --print-architecture<span class="k">)</span><span class="s2">] https://download.docker.com/linux/debian \</span>
<span class="s2"> </span><span class="k">$(</span>lsb_release -cs<span class="k">)</span><span class="s2"> \</span>
<span class="s2"> stable"</span>
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
</pre></div>
<div class="highlight"><pre><span></span>dpkg -l openvswitch-switch wireshark imagemagick tk tcllib util-linux
sudo apt install --reinstall openvswitch-switch wireshark imagemagick tk tcllib util-linux
<span class="nb">cd</span> ~/Logiciels
mkdir Imunes
<span class="nb">cd</span> Imunes
git clone https://github.com/imunes/imunes.git
<span class="nb">cd</span> imunes
sudo make install
</pre></div>
<h2><a name="head6.4"> </a> 6.4 Installation de Jupyterlab et Jupyterhub</h2>
<p><a href="https://jupyter.org/">Jupyter</a> est un interface graphique de développement et de programmation multilangages qui permet de se familiariser simplement avec la programmation. Il permet d'approcher simplement un langage de programmation sa syntaxe, son vocabulaire et sa logique. Il permet de produire et d'exploiter des <a href="https://ipython.org/">cahiers de programmes ipython</a> intégrant code source et commentaire qui s'avèrent être d'excellents outils pédagogiques pour l'apprentissage du code voir les <a href="https://github.com/g-vidal/CahierDeProgrammes">cahiers de programmes du projet Tremplin</a> et par exemple la <a href="https://github.com/g-vidal/CahierDeProgrammes/blob/master/StationMeteo/ministation3Capteurs.ipynb">ministation météo</a>. Jupyterhub est un coutil companion de Jupyterhub qui permet de servir jupyter sur le web à plusieurs usagers en même temps, lors d'un TP ou TD par exemple.</p>
<p>Jupyter et Jupyterhub sont des logiciels python et peuvent donc être installés avec pip ou <code>pipenv</code>, jupyterhub requiert <code>python3</code>. Les commandes concernant <code>python2</code> sont maintenant obsolètes. depuis <code>jupyterlab 3.0</code> on utilise exclusivement <code>python3</code> et <code>jupyter</code> est de moins en moins utilisé. Il est possible de réaliser une installation faisant appel à <code>pipenv</code> cette stratégie crée un environnement virtuel dans lequel la compatibilité et l'interopérabilité entre les paquets <code>python</code> est garantie sans perturber le fonctionnement du <code>python</code> global du système. L'inconvénient est que l'environnement virtuel duplique l'espace occupé par <code>python</code>.
Pour installer en utilisant n processeurs en parallèle utiliser <code>export MAKEFLAGS="-j$(nproc)"</code>.</p>
<div class="highlight"><pre><span></span>sudo apt install rustc
sudo su callisto
<span class="nb">cd</span>
mkdir JupyterLab
<span class="nb">cd</span> JupyterLab
pipenv install jupyterlab
pipenv shell
<span class="nb">export</span> <span class="nv">MAKEFLAGS</span><span class="o">=</span><span class="s2">"-j</span><span class="k">$(</span>nproc<span class="k">)</span><span class="s2">"</span>
pip install --upgrade pip setuptools wheel
pip install jupyterhub
pip install --upgrade matplotlib flexx plotly matplotlib git+https://github.com/jupyter/sudospawner jupyter_contrib_nbextensions
</pre></div>
<p>Il est nécessaire de rapatrier les librairies <code>mraa</code> et <code>upm</code> compilées sur le python du système général.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /lib/python3.9/dist-packages/
ls upm/*.py
<span class="c1"># if no file is found hey must be copied from source</span>
exit<span class="p">;</span><span class="nb">exit</span>
<span class="nb">cd</span> ~/Logiciels/IoT/upm/build
sudo cp src/*/python3.9/*.py /lib/python3.9/dist-packages/upm/
sudo su callisto
<span class="nb">cd</span> ~/JupyterLab
pipenv shell
<span class="nb">cd</span> /lib/python3.9/dist-packages
cp -r *mraa* upm ~/.local/share/virtualenvs/JupyterLab-RHxiRMZV/lib/python3.9/site-packages/
</pre></div>
<p>La commande suivante est devenue inutile avec <code>jupyterlab : sudo jupyter contrib nbextension install --system</code></p>
<h3><a name="head6.4.1"> </a> 6.4.1 Configuration de la sécurité et du lancement par le user callisto</h3>
<p>Comme pour <code>tigervnc</code>la sécurité est une contrainte importante de <code>jupyterhub</code> pour les mêmes raisons. La configuration est ici légèrement différente et l'authentification permet à chaque groupe ou élève (suivant le choix du professeur) de disposer d'un espace protégé des actions du reste du monde.</p>
<p><code>callisto</code> est l'utilisateur choisi pour lancer <code>jupyterhub</code>, pour assumer la configuration proposée c'est donc l'utilisateur callisto qui doit créer le certificat de sécurité.</p>
<div class="highlight"><pre><span></span>sudo su callisto
<span class="nb">cd</span>
mkdir -p Utils/Certificates
<span class="nb">cd</span> !$
openssl req -new -newkey rsa:2048 -rand /dev/urandom -nodes -keyout meteojuphub.key -out meteojuphub.csr
</pre></div>
<p>Répondre aux questions posées en fonction de vos paramètres.</p>
<div class="highlight"><pre><span></span>openssl req -new -x509 -days <span class="m">3652</span> -key meteojuphub.key -out meteojuphub.pem
</pre></div>
<p>On dispose maintenant des fichiers de sécurisaton nécessaires <code>meteojuphub.csr</code> <code>meteojuphub.key</code> <code>meteojuphub.pem</code> qui vont être utilisés pour protéger l'accès à jupyterhub. Par défaut un fichier de sécurisation a été installé pour permettre un fonctionnement immédiat mais <strong>chaque nouvel administrateur doit impérativement créer son propre fichier de sécurité</strong>. les manipulations qui suivent sont génériques et si les mêmes noms de fichier sont utilisés il ne sera pas nécessaire de répliquer les opérations ci-dessous.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir Jupyterhub
<span class="nb">cd</span> !$
jupyterhub --generate-config
</pre></div>
<p>Éditer le fichier <code>jupyterhub_config.py</code> <code>nano jupyterhub_config.py</code> puis décommenter et renseigner les 3 lignes comme indiqué ci-dessous :</p>
<div class="highlight"><pre><span></span>.../...
<span class="c1">## The class to use for spawning single-user servers.</span>
<span class="c1"># </span>
<span class="c1"># Should be a subclass of Spawner.</span>
<span class="c1">#c.JupyterHub.spawner_class = 'jupyterhub.spawner.LocalProcessSpawner'</span>
c.JupyterHub.spawner_class<span class="o">=</span><span class="s1">'sudospawner.SudoSpawner'</span>
<span class="c1">## Path to SSL certificate file for the public facing interface of the proxy</span>
<span class="c1"># </span>
<span class="c1"># When setting this, you should also set ssl_key</span>
<span class="c1">#c.JupyterHub.ssl_cert = ''</span>
c.JupyterHub.ssl_cert <span class="o">=</span> <span class="s1">'/home/callisto/Utils/Certificates/meteojuphub.pem'</span>
<span class="c1">## Path to SSL key file for the public facing interface of the proxy</span>
<span class="c1"># </span>
<span class="c1"># When setting this, you should also set ssl_cert</span>
<span class="c1">#c.JupyterHub.ssl_key = ''</span>
c.JupyterHub.ssl_key <span class="o">=</span> <span class="s1">'/home/callisto/Utils/Certificates/meteojuphub.key'</span>
.../...
<span class="c1">## Set of users that will have admin rights on this JupyterHub.</span>
<span class="c1"># </span>
<span class="c1"># Admin users have extra privileges:</span>
<span class="c1"># - Use the admin panel to see list of users logged in</span>
<span class="c1"># - Add / remove users in some authenticators</span>
<span class="c1"># - Restart / halt the hub</span>
<span class="c1"># - Start / stop users' single-user servers</span>
<span class="c1"># - Can access each individual users' single-user server (if configured)</span>
<span class="c1"># </span>
<span class="c1"># Admin access should be treated the same way root access is.</span>
<span class="c1"># </span>
<span class="c1"># Defaults to an empty set, in which case no user has admin access.</span>
<span class="c1">#c.Authenticator.admin_users = set()</span>
c.Authenticator.admin_users <span class="o">=</span> set<span class="o">([</span><span class="s1">'localadm'</span>,<span class="s1">'callisto'</span>,<span class="s1">'ens-ife'</span><span class="o">])</span>
</pre></div>
<p>Pour que <code>Jupyterhub</code> puisse être lancé par <code>callisto</code> et fonctionne correctement <code>callisto</code> (que nous avons choisi comme user pour lancer <code>Jupyterhub</code> doit disposer de quelques privilèges qui doivent être ajoutés par l'administrateur (et pas par callisto qui n'a pas de privilèges suffisants) au fichier sudoers avec la commande <code>sudo visudo</code> en ajoutant les lignes suivantes :</p>
<div class="highlight"><pre><span></span><span class="c1"># the command(s) the Hub can run on behalf of the jupyterhub group users </span>
<span class="c1"># without needing a password </span>
<span class="c1"># the exact path may differ, depending on how sudospawner was installed </span>
Cmnd_Alias <span class="nv">JUPYTER_CMD</span> <span class="o">=</span> /home/callisto/.local/share/virtualenvs/JupyterLab-RHxiRMZV/bin/sudospawner
<span class="c1"># actually give the Hub user permission to run the above command </span>
<span class="c1"># on behalf of the above users without prompting for a password </span>
%jupyterhub <span class="nv">ALL</span><span class="o">=(</span>callisto<span class="o">)</span> /usr/bin/sudo
callisto <span class="nv">ALL</span><span class="o">=(</span>%jupyterhub<span class="o">)</span> NOPASSWD:JUPYTER_CMD
</pre></div>
<p>L'utilisateur <code>callisto</code> doit aussi appartenir au groupe shadow.</p>
<div class="highlight"><pre><span></span>sudo adduser callisto shadow
</pre></div>
<h3><a name="head6.4.2"> </a> 6.4.2 Ajout de moteurs nodeJS et java dans l'environnement jupyter/jupyterhub</h3>
<p><code>Jupyter</code> et <code>Jupyterhub</code> sont programmés en python mais les <code>notebooks</code> (cahiers d'exercices) qu'ils utilisent peuvent fonctionner avec d'autres langages, à titre d'exemple nous proposons ici l'installation du moteur javascript permettant de programmer en nodeJS.</p>
<p>La version 3 de jupyterlab résoud tous les problèmes d'extensions en permettant d'ajouter les extensions depuis l'interface web. En cas de besoin le contournement qui avait été utilisé précédemment pour permettre d'installer proprement les extensions en ligne de commande avec <code>jupyter lab build</code>, pour les raspberries PI3 et en dessous est proposé, . Le contournement foncctionne avec <code>webpack</code>.</p>
<div class="highlight"><pre><span></span>sudo npm install -g webpack webpack-cli webpack-bundle-analyzer
<span class="nb">cd</span> /usr/local/share/jupyter/lab/staging
sudo su
<span class="nv">NODE_OPTIONS</span><span class="o">=</span><span class="s2">"--max-old-space-size=850"</span> webpack --config webpack.prod.minimize.config.js <span class="c1"># pour la pi3 1Go</span>
<span class="nv">NODE_OPTIONS</span><span class="o">=</span><span class="s2">"--max-old-space-size=3500"</span> webpack --config webpack.prod.minimize.config.js <span class="c1"># pour la pi4 4Go</span>
</pre></div>
<p>Pour que les usagers choisis puissent ajouter leurs extensions il est nécessaire de modifier les permissions des dossiers de <code>.local/share/virtualenvs/JupyterLab-RHxiRMZV/share/jupyter/lab</code>. Dans notre cas tous les usagers ayant ce droit appartiennent au groupe "jupyterhub" la solution choisie a donc été la suivante :</p>
<div class="highlight"><pre><span></span>sudo su callisto
<span class="nb">cd</span> ~/.local/share/virtualenvs/JupyterLab-RHxiRMZV/share/jupyter/lab
ls
<span class="c1"># If those folder do not exist</span>
mkdir extensions settings staging
<span class="k">for</span> i in extensions settings staging<span class="p">;</span> <span class="k">do</span> chmod -R g+w <span class="nv">$i</span><span class="p">;</span> chgrp jupyterhub <span class="nv">$i</span><span class="p">;</span> <span class="k">done</span>
</pre></div>
<p>Installation voila pour extraire un notebook</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> ~/JupyterLab/
pipenv shell
pip install voila
</pre></div>
<p>Installation d'un autre moteur js</p>
<div class="highlight"><pre><span></span>sudo su
npm install -g <span class="o">[</span>--unsafe-perm<span class="o">]</span> ijavascript
sudo su callisto
<span class="nb">cd</span> ~/JupyterLab
pipenv shell
pip install jupyter ipywidgets
ijsinstall
</pre></div>
<p>Le moteur s'isnstalle par défaut dans <code>.local/share/jupyter/kernels/</code> alors qu'il devrait se positionner dans <code>~/.local/share/virtualenvs/JupyterLab-RHxiRMZV/share/jupyter/kernels</code> il faut donc le déplacer à la main.</p>
<div class="highlight"><pre><span></span>ls ~/.local/share/jupyter/kernels
cp -r ~/.local/share/jupyter/kernels/javascript ~/.local/share/virtualenvs/JupyterLab-RHxiRMZV/share/jupyter/kernels
</pre></div>
<p>Installation d'un moteur java.</p>
<div class="highlight"><pre><span></span>pip install kotlin-jupyter-kernel
</pre></div>
<h3><a name="head6.4.3"> </a> 6.4.3 Installation d'un service <code>jupyterhub</code> ou <code>jupyterlabhub</code></h3>
<p>Vérifier que les logiciels nécessaires à la production de sorties textes au format pdf drpuis jupyter ou jupyterlab est possible avec la commancde <code>sudo dpkg -l pandoc python3-pypandoc python3-pandocfilters texlive-xetex texlive-latex-recommended texlive-lang-other</code>, la réponse doit être du type :</p>
<div class="highlight"><pre><span></span><span class="o">||</span>/ Nom Version Architecture Description
+++-<span class="o">=========================</span>-<span class="o">===============</span>-<span class="o">============</span>-<span class="o">=====================================</span>
ii pandoc <span class="m">2</span>.2.1-3+b2 armhf general markup converter
ii python3-pandocfilters <span class="m">1</span>.4.2-1 all python3 bindings <span class="k">for</span> Pandoc<span class="err">'</span>s filters
ii python3-pypandoc <span class="m">1</span>.4+ds0-1.1 all Thin wrapper <span class="k">for</span> pandoc <span class="o">(</span>Python <span class="m">3</span>.x<span class="o">)</span>
ii texlive-lang-other <span class="m">2018</span>.20190227-2 all TeX Live: Other languages
ii texlive-latex-recommended <span class="m">2018</span>.20190227-2 all TeX Live: LaTeX recommended packages
ii texlive-xetex <span class="m">2018</span>.20190227-2 all TeX Live: XeTeX and packages
</pre></div>
<p>Si ce n'est pas le cas installer les paquets manquants avec <code>sudo apt install ...</code> et les paquets python avec <code>pip</code></p>
<div class="highlight"><pre><span></span>sudo apt install texlive-lang-other texlive-latex-recommended texlive-xetex
sudo su callisto
<span class="nb">cd</span> ~/JupyterLab/
pipenv shell
pip install --upgrade pandoc pandocfilters pypandoc
</pre></div>
<h4><a name="head6.4.3.1"> </a> 6.4.3.1 Mise en place de jupyterhub</h4>
<p>Pour mettre en place un service placer le fichier <code>jupyterhub.service</code> dans <code>/etc/systemd/system</code> :</p>
<div class="highlight"><pre><span></span>sudo jed /etc/systemd/system/jupyterhub.service
</pre></div>
<div class="highlight"><pre><span></span><span class="o">[</span>Unit<span class="o">]</span>
<span class="nv">Description</span><span class="o">=</span>Jupyterhub
<span class="nv">After</span><span class="o">=</span>network-online.target
<span class="o">[</span>Service<span class="o">]</span>
<span class="nv">User</span><span class="o">=</span>callisto
<span class="nv">WorkingDirectory</span><span class="o">=</span>/home/callisto/Jupyterhub
<span class="nv">ExecStart</span><span class="o">=</span>pipenv run jupyterhub --config<span class="o">=</span>/home/callisto/Jupyterhub/jupyterhub_config.py
<span class="o">[</span>Install<span class="o">]</span>
<span class="nv">WantedBy</span><span class="o">=</span>multi-user.target
</pre></div>
<p>Faire prendre en compte le nouveau service avec <code>sudo systemctl daemon-reload</code> puis contrôler le service avec les commandes habituelles, pour avoir jupyterhub au démarrage <code>sudo systemctl enable jupyterhub</code></p>
<div class="highlight"><pre><span></span>sudo systemctl status jupyterhub
sudo systemctl start jupyterhub
sudo systemctl stop jupyterhub
</pre></div>
<h4><a name="head6.4.3.2"> </a> 6.4.3.2 Mise en place de jupyterlabhub</h4>
<ul>
<li>pour utiliser exclusivement <code>jupyterlab</code> et non <code>jupyter</code> modifier le fichier de configuration de callisto <code>jupyterhub_config.py</code> en modifiant la valeur du paramètre suivant :</li>
<li></li>
</ul>
<div class="highlight"><pre><span></span>sudo su callisto
<span class="nb">cd</span> ~/Jupyterhub/
jed jupyterhub_config.py
<span class="c1"># change to</span>
c.Spawner.cmd <span class="o">=</span> <span class="o">[</span><span class="s1">'jupyter-labhub'</span><span class="o">]</span>
</pre></div>
<p>Lors de la dernière installation (2021-10-16) cette option éait inopérante. Pour y remédier changement de la commande de démarrage par défaut.</p>
<div class="highlight"><pre><span></span>sudo su callisto
<span class="nb">cd</span> /home/callisto/.local/share/virtualenvs/JupyterLab-RHxiRMZV/bin
mv jupyterhub-singleuser jupyterhub-singleuser-std
cp jupyter-labhub jupyterhub-singleuser
</pre></div>
<p>Le serveur jupyterhub peut-être lancé par <code>callisto</code> depuis le répertoire <code>/home/callisto/Jupyterhub</code> par la commande <code>jupyterhub</code>. Bien veiller à ce que tous les usagers de jupyterhub appartiennent au groupe jupyterhub.</p>
<h3><a name="head6.4.4"> </a> 6.4.4 (Option obsolète) Installation d'une alternative entre jupyterlab et jupyter</h3>
<ul>
<li>Pour avoir jupyterlab et jupyter-labhub ajouter le fichier <code>sudospawner-singleuser</code> contenant le script suivant dans <code>/usr/local/bin</code> et le rendre exécutable.</li>
</ul>
<div class="highlight"><pre><span></span>sudo jed /usr/local/bin/sudospawner-singleuser
</pre></div>
<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash -l</span>
<span class="c1"># Delegate the notebook server launch to the jupyter-labhub script.</span>
<span class="nb">exec</span> <span class="s2">"jupyter-labhub"</span> <span class="nv">$@</span>
</pre></div>
<p>Ne pas oublier de rendre ce fichier <strong>exécutable</strong>.</p>
<div class="highlight"><pre><span></span>sudo chmod a+x /usr/local/bin/sudospawner-singleuser
</pre></div>
<p>La procédure suivante permet de mettre en place deux services l'un pour <code>jupyterlab</code> l'autre pour <code>jupyter</code>. Les deux services seront nommés <code>jupyterhub</code> et <code>jupyterlabhub</code>.</p>
<div class="highlight"><pre><span></span>sudo su
<span class="nb">cd</span> /etc/systemd/system
cat > jupyterhub.service
</pre></div>
<p>Ajouter</p>
<div class="highlight"><pre><span></span><span class="k">[Unit]</span>
<span class="na">Description</span><span class="o">=</span><span class="s">Jupyterhub</span>
<span class="na">After</span><span class="o">=</span><span class="s">network-online.target</span>
<span class="k">[Service]</span>
<span class="na">User</span><span class="o">=</span><span class="s">callisto</span>
<span class="na">ExecStartPre</span><span class="o">=</span><span class="s">+/bin/sh /home/callisto/Jupyterhub/preparehub.sh</span>
<span class="na">ExecStart</span><span class="o">=</span><span class="s">/usr/local/bin/jupyterhub --config=/home/callisto/Jupyterhub/jupyterhub_config.py</span>
<span class="na">WorkingDirectory</span><span class="o">=</span><span class="s">/home/callisto/Jupyterhub</span>
<span class="k">[Install]</span>
<span class="na">WantedBy</span><span class="o">=</span><span class="s">multi-user.target</span>
</pre></div>
<div class="highlight"><pre><span></span>cat > jupyterlabhub.service
</pre></div>
<p>Ajouter</p>
<div class="highlight"><pre><span></span><span class="k">[Unit]</span>
<span class="na">Description</span><span class="o">=</span><span class="s">Jupyterlabhub</span>
<span class="na">After</span><span class="o">=</span><span class="s">network-online.target</span>
<span class="k">[Service]</span>
<span class="na">User</span><span class="o">=</span><span class="s">callisto</span>
<span class="na">ExecStartPre</span><span class="o">=</span><span class="s">+/bin/sh /home/callisto/Jupyterhub/preparelab.sh</span>
<span class="na">ExecStart</span><span class="o">=</span><span class="s">/usr/local/bin/jupyterhub --config=/home/callisto/Jupyterhub/jupyterhub_config.py</span>
<span class="na">WorkingDirectory</span><span class="o">=</span><span class="s">/home/callisto/Jupyterhub</span>
<span class="k">[Install]</span>
<span class="na">WantedBy</span><span class="o">=</span><span class="s">multi-user.target</span>
</pre></div>
<div class="highlight"><pre><span></span><span class="nb">exit</span>
sudo su callisto
<span class="nb">cd</span> ~/Jupyterhub
cat > preparehub.sh
</pre></div>
<p>Ajouter</p>
<div class="highlight"><pre><span></span><span class="ch">#! /bin/sh</span>
<span class="k">if</span> <span class="o">[</span> -f /usr/local/bin/sudospawner-singleuser <span class="o">]</span><span class="p">;</span> <span class="k">then</span> rm /usr/local/bin/sudospawner-singleuser<span class="p">;</span><span class="k">fi</span>
</pre></div>
<div class="highlight"><pre><span></span>cat > preparelab.sh
</pre></div>
<p>Ajouter</p>
<div class="highlight"><pre><span></span><span class="ch">#! /bin/sh</span>
<span class="k">if</span> <span class="o">[</span> -f /usr/local/bin/sudospawner-singleuser <span class="o">]</span><span class="p">;</span> <span class="k">then</span> <span class="nb">echo</span> <span class="s2">"lab ready"</span><span class="p">;</span> <span class="k">else</span> cp /usr/local/bin/sudospawner-singleuserlab /usr/local/bin/sudospawner-singleuser <span class="p">;</span><span class="k">fi</span>
</pre></div>
<p>Rendre les fichiers exécutables puis quitter le user <code>callisto</code> et recopier le fichier <code>sudospawner-singleuser</code> dans <code>sudospawner-singleuserlab</code> :</p>
<div class="highlight"><pre><span></span>chmod a+x *.sh<span class="sb">`</span>
<span class="nb">exit</span>
sudo cp /usr/local/bin/sudospawner-singleuser /usr/local/bin/sudospawner-singleuserlab
</pre></div>
<p>Il y a maintenant deux services de lancement l'un pour jupuyterhub l'autre pour jupyterlabhub fonctionnant de la même façon, Il est souhaitable d'éteindre un service avant de lancer l'autre.</p>
<div class="highlight"><pre><span></span><span class="c1"># Jupyterhub</span>
sudo systemctl status jupyterhub
sudo systemctl start jupyterhub
sudo systemctl stop jupyterhub
<span class="c1">#Jupyterlabhub</span>
sudo systemctl status jupyterlabhub
sudo systemctl start jupyterlabhub
sudo systemctl stop jupyterlabhub
</pre></div>
<p>L'un ou l'autre peut être activé au démarrage avec la commande <code>sudo systemctl enable jupyterhub/jupyterlabhub</code>un des deux au choix.</p>
<h2><a name="head6.5"> </a> 6.5 Installation de Snap!BYOB</h2>
<p>Jupyter est un outil très performant pour un apprentissage progressif du codage mais il ne s'adresse pas à des novices absolus. Le logiciel Snap!BYOB est un outil de programmation graphique par blocs plus puissant que Scratch qui permet une introduction à la programmation. Comme Jupyter il propose ue interface web que la Raspberry fournit sans problème. Pour installer Snap télécharger le code depuis un <a href="http://snap.berkeley.edu/snapsource/snap.html">serveur snap en ligne</a> en cliquant en haut à gauche sur le logo Snap qui fait apparaitre un menu déroulant. reopier le logiciel <code>snap.zip</code> dan un répertoire de la Raspberry pi puis le décompresser dans un dossier de votre choix et le lier à la racine du web <code>/var/www/html</code>.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir Logiciels/Snap
<span class="nb">cd</span> !$
git clone https://github.com/jmoenig/Snap.git
sudo cp -r Snap /opt
sudo ln -s /opt/Snap /var/www/html/snap
</pre></div>
<p>Snap!BYOB est maintenant directement accessible sur le serveur web de la Raspberry Pi <code>http://$$$.$$$.$$$.$$$/snap</code></p>
<h2><a name="head6.6"> </a> 6.6 Installation de Domoticz pour piloter des objets connectés du commerce</h2>
<p>Domoticz est une logiciel de pilotage d'objets connectés du commerce on l'utilisera ici avec le concentrateur <code>RFXCOM RFXtrx433XL</code> pour installer le logiciel <code>domoticz</code> il faut un certain nombre de paquets de développement afin de parvenir à le compiler. La première commande permet de lister les paquets absents, la seconde permet de les ajouter (ne traiter que les paquets manquants).</p>
<div class="highlight"><pre><span></span>sudo dpkg -l python3-openssl libssl-dev libboost-atomic1.74-dev libboost-chrono1.74-dev libboost-system-dev libboost-thread-dev libboost1.74-dev libcurl4-gnutls-dev curl libusb-dev libconfuse-dev doxygen libftdi-dev
sudo apt install python3-openssl libssl1.0-dev libboost-atomic1.74-dev libboost-chrono1.74-dev libboost-system-dev libboost-thread-dev libboost1.74-dev libcurl4-gnutls-dev curl libusb-dev libconfuse-dev doxygen libftdi-dev
</pre></div>
<p>En <code>bullseye</code></p>
<div class="highlight"><pre><span></span>sudo dpkg -l python3-openssl libssl-dev libboost-atomic1.74-dev libboost-chrono1.74-dev libboost-system-dev libboost-thread-dev libboost-dev libcurl4-gnutls-dev curl libusb-dev libconfuse-dev doxygen libftdi-dev
sudo apt install python3-openssl libssl1.0-dev libboost-atomic1.74-dev libboost-chrono1.74-dev libboost-system-dev libboost-thread-dev libboost-dev libcurl4-gnutls-dev curl libusb-dev libconfuse-dev doxygen libftdi-dev
</pre></div>
<p>La version <code>67</code> ou <code>74</code> peut avoir progressé après le rédaction de cet article, faire les modifications en conséquence.</p>
<p>Créer un répertoire pour recevoir le logiciel <code>domoticz</code> et tous les logiciels supplémentaires traitant les différents objets de la domotique.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> ~/Logiciels
mkdir Domoticz
<span class="nb">cd</span> Domoticz/
</pre></div>
<p>Pour disposer des pilotes <code>telldus</code> dans <code>domoticz</code> ajouter le zip le décompresser et le compiler (Il y a des erreurs de compilation et le code source doit être modifié comme précisé c-dessous. </p>
<div class="highlight"><pre><span></span>mkdir Telldus
<span class="nb">cd</span> Telldus/
wget http://download.telldus.com/TellStick/Software/telldus-core/telldus-core-2.1.2.tar.gz
tar xvfz telldus-core-2.1.2.tar.gz
<span class="nb">cd</span> telldus-core-2.1.2
</pre></div>
<p>Compilation puis installation.</p>
<div class="highlight"><pre><span></span>cmake .
mv CMakeDoxyfile.in Doxyfile.in
cmake .
make
sudo make install
</pre></div>
<p>Dans les fichiers de <code>tdtool</code>, <code>tdadmin</code>, <code>link.txt</code> il manque parfois (suivant les versions) le lien avec la librairie <code>pthread</code> ajouter en fin de ligne <code>-lpthread</code> dans les deux fichiers concernés.</p>
<div class="highlight"><pre><span></span>jed tdtool/CMakeFiles/tdtool.dir/link.txt
jed tdadmin/CMakeFiles/tdadmin.dir/link.txt
</pre></div>
<p>Pour disposer d'<code>openzwave</code> penser à ajouter le chemin dans <code>CMakeLists.txt</code> de <code>domoticz</code>.</p>
<p>En x64 il peut s'avérer qu'il n'y ait pas assez de RAM pour compiler domoticz ce qui fige la raspi. </p>
<p>Telldus est issu de logiciels propriétaires, la version partagée semble figée et il subsiste quelques disharmonies avec domoticz empêchant la compilation. les problèmes concernent la non déclaration ou la double déclaration de variables; plusieurs solutions existent celle qui a été expérimentée est de conserver l'inclusion du fichier créé par la compilation séparée de Telldus <code>#include <telldus-core.h></code> qui est installé dans <code>/usr/local/include</code> et de supprimer dans les fichiers de domoticz les doublons. Il est aussi nécessaire d'ajouter <code>#include <telldus-core.h></code> dans certains fichiers <code>.cpp</code> lorsque la déclaration d'une variable est manquante.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> ../..
git clone https://github.com/domoticz/domoticz.git domoticz
<span class="nb">cd</span> domoticz
nano CMakeLists.txt
</pre></div>
<p>Ajouter <code>openzwave</code>compilé ici.</p>
<div class="highlight"><pre><span></span>find_library<span class="o">(</span>OpenZWave NAMES libopenzwave.a HINTS <span class="s2">"/home/ens-ife/Logiciels/OpenZwave/open-zwave"</span>
</pre></div>
<div class="highlight"><pre><span></span>cmake -DCMAKE_BUILD_TYPE<span class="o">=</span>Release CMakeLists.txt
make
sudo make install
</pre></div>
<p>Ne pas compiler avec plus d'un processeur car la mémoire de la RaspBerry (1Go) est insuffisante pour compiler en parallèle sur plusieurs processeurs à mons d'utiliser un gros swap et contrôler que les <code>threads</code> ne soient pas figés, la compilation en <code>-j4</code> passe sur la Pi4 avec 4Go de mémoire..</p>
<p>Pour utiliser <code>Domoticz</code> on crée l'utilisateur <code>domotic</code> et le groupe <code>domotic</code> . Tous les usagers qui pourront lancer le logiciel devront appartenir au groupe domotic et au groupe dialout.</p>
<div class="highlight"><pre><span></span>sudo adduser domotic --no-create-home
<span class="k">for</span> i in domotic dialout<span class="p">;</span><span class="k">do</span> <span class="k">for</span> j in ens-ife localadm www-data domotic<span class="p">;</span><span class="k">do</span> sudo adduser <span class="nv">$j</span> <span class="nv">$i</span><span class="p">;</span><span class="k">done</span><span class="p">;</span><span class="k">done</span>
</pre></div>
<p>Pour que tous les usagers du groupe domotic puissent accéder au <code>RFXCOM</code> on doit ajouter un fichier dans <code>/etc/uvev/rules.d</code> :</p>
<div class="highlight"><pre><span></span>sudo nano /etc/udev/rules.d/45-usbdomoticz.rules
<span class="c1">#ajouter la ligne suivante</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"usb"</span>, ATTR<span class="o">{</span>idVendor<span class="o">}==</span><span class="s2">"0403"</span>, ATTR<span class="o">{</span>idProduct<span class="o">}==</span><span class="s2">"6015"</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">"add"</span>, <span class="nv">GROUP</span><span class="o">=</span><span class="s2">"domotic"</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">"0664"</span>
<span class="c1">#sauvegarder</span>
</pre></div>
<p>Pour créer le service domotique et qu'il puisse démarrer seul ajouter le fichier <code>/etc/systemd/system/domoticz.service</code> :</p>
<div class="highlight"><pre><span></span>sudo nano /etc/systemd/system/domoticz.service
<span class="c1">#ajouter le contenu suivant</span>
<span class="o">[</span>Unit<span class="o">]</span>
<span class="nv">Description</span><span class="o">=</span>domoticz_service
<span class="o">[</span>Service<span class="o">]</span>
<span class="nv">User</span><span class="o">=</span>domotic
<span class="nv">Group</span><span class="o">=</span>domotic
<span class="nv">WorkingDirectory</span><span class="o">=</span>/opt/Domoticz
<span class="nv">ExecStart</span><span class="o">=</span>/opt/Domoticz/domoticz -www <span class="m">8080</span> -sslwww <span class="m">0</span> -wwwbind <span class="m">192</span>.168.10.212
<span class="c1">#ExecStartPre=setcap 'cap_net_bind_service=+ep' /opt/Domoticz/domoticz</span>
<span class="nv">Restart</span><span class="o">=</span>on-failure
<span class="nv">RestartSec</span><span class="o">=</span>1m
<span class="c1">#StandardOutput=null</span>
<span class="o">[</span>Install<span class="o">]</span>
<span class="nv">WantedBy</span><span class="o">=</span>multi-user.target
</pre></div>
<p>Déplacer le contenu durépertoire dans <code>/opt/Domoticz</code> et modifier les droits d'accès :</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
<span class="nb">cd</span> Logiciels/Domoticz/domoticz
sudo mkdir /opt/Domoticz
sudo cp -r ./* /opt/Domoticz/
sudo chown -R domotic.domotic /opt/Domoticz/
sudo chmod -R g+rwX /opt/Domoticz/
</pre></div>
<p>Le service se gère alors comme tous les autres services de la raspberryPi :</p>
<div class="highlight"><pre><span></span>sudo systemctl start domoticz
sudo systemctl status domoticz
sudo systemctl stop domoticz
sudo systemctl <span class="nb">enable</span> domoticz
sudo systemctl disable domoticz
</pre></div>
<h2><a name="head6.7"> </a> 6.7 Ajout de scripts pour démarrer ou supprimer un service au démarrage</h2>
<p>Les services <code>Jupyterhub</code>, <code>vncserver</code>, <code>weewx</code> peuvent tous être mis en route au démarrage mais ils consomment inutilement des ressources si ils ne sont pas utilisés. Les scripts suivants permettent de gérer la mise en route de ces services au démarrage. Par défaut seul le serveur vnc est mis en route. Le contenu de ces scripts est détaillé c dessous.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir Scripts
<span class="nb">cd</span> Scripts
</pre></div>
<h3><a name="head6.7.1"> </a> 6.7.1 Pour <code>jupyterhub</code></h3>
<p>Ajouter le fichier avec <code>nano jupyterhubOnOff</code> ou une commande équivalente</p>
<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1">#script pour activer/désactiver jupyterhub au boot</span>
<span class="c1">#</span>
<span class="nv">prog</span><span class="o">=</span><span class="sb">`</span>basename <span class="nv">$0</span><span class="sb">`</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nv">$1</span> <span class="o">==</span> <span class="s2">""</span> <span class="o">]]</span> <span class="p">;</span> <span class="k">then</span>
<span class="nb">echo</span> <span class="s2">"Type "</span> <span class="nv">$prog</span> <span class="s2">" [on / off]"</span>
<span class="nb">echo</span> <span class="s2">"Start or stop jupyterhub at boot"</span>
<span class="nb">exit</span>
<span class="k">else</span>
<span class="k">case</span> <span class="nv">$1</span> in
on <span class="o">)</span>
sudo systemctl <span class="nb">enable</span> jupyterhub
<span class="p">;;</span>
off <span class="o">)</span>
sudo systemctl disable jupyterhub
<span class="p">;;</span>
* <span class="o">)</span>
<span class="nb">echo</span> <span class="s2">"Choice is on or off"</span>
<span class="nb">exit</span>
<span class="p">;;</span>
<span class="k">esac</span>
<span class="k">fi</span>
</pre></div>
<h3><a name="head6.7.2"> </a> 6.7.2 Pour <code>vncserver</code></h3>
<p>Ajouter le fichier avec <code>nano vncserverOnOff</code> ou une commande équivalente</p>
<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1"># Script pour activer/désactiver vncserver au boot</span>
<span class="c1">#</span>
<span class="nv">prog</span><span class="o">=</span><span class="sb">`</span>basename <span class="nv">$0</span><span class="sb">`</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nv">$2</span> <span class="o">==</span> <span class="s2">""</span> <span class="o">]]</span> <span class="p">;</span> <span class="k">then</span>
<span class="nb">echo</span> <span class="s2">"Type "</span> <span class="nv">$prog</span> <span class="s2">"on / off port to start or stop vncserver at boot on port 5900 + port"</span>
<span class="nb">exit</span>
<span class="k">else</span>
<span class="k">case</span> <span class="nv">$1</span> in
on <span class="o">)</span>
sudo systemctl <span class="nb">enable</span> vncserver@1
<span class="p">;;</span>
off <span class="o">)</span>
sudo systemctl disable vncserver@1
<span class="p">;;</span>
* <span class="o">)</span>
<span class="nb">echo</span> <span class="s2">"Choice is on or off"</span>
<span class="nb">exit</span>
<span class="p">;;</span>
<span class="k">esac</span>
<span class="k">fi</span>
</pre></div>
<h3><a name="head6.7.3"> </a> 6.7.3 Pour <code>weewx</code></h3>
<p>Ajouter le fichier avec <code>nano weewxOnOff</code> ou une commande équivalente</p>
<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1"># script pour activer/désactiver weewx au boot</span>
<span class="c1">#</span>
<span class="nv">prog</span><span class="o">=</span><span class="sb">`</span>basename <span class="nv">$0</span><span class="sb">`</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nv">$1</span> <span class="o">==</span> <span class="s2">""</span> <span class="o">]]</span> <span class="p">;</span> <span class="k">then</span>
<span class="nb">echo</span> <span class="s2">"Type "</span> <span class="nv">$prog</span> <span class="s2">"on or off to start or stop weewx at boot"</span>
<span class="nb">exit</span>
<span class="k">else</span>
<span class="k">case</span> <span class="nv">$1</span> in
on <span class="o">)</span>
sudo systemctl <span class="nb">enable</span> weewx
<span class="p">;;</span>
off <span class="o">)</span>
sudo systemctl disable weewx
<span class="p">;;</span>
* <span class="o">)</span>
<span class="nb">echo</span> <span class="s2">"Choice is on or off"</span>
<span class="nb">exit</span>
<span class="p">;;</span>
<span class="k">esac</span>
<span class="k">fi</span>
</pre></div>
<h3><a name="head6.7.4"> </a> 6.7.3 Pour <code>domoticz</code></h3>
<p>Ajouter le fichier avec <code>nano domoticzOnOff</code> ou une commande équivalente</p>
<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1"># script pour activer/désactiver domoticz au boot</span>
<span class="c1">#</span>
<span class="nv">prog</span><span class="o">=</span><span class="sb">`</span>basename <span class="nv">$0</span><span class="sb">`</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nv">$1</span> <span class="o">==</span> <span class="s2">""</span> <span class="o">]]</span> <span class="p">;</span> <span class="k">then</span>
<span class="nb">echo</span> <span class="s2">"Type "</span> <span class="nv">$prog</span> <span class="s2">"on or off to start or stop domoticz at boot"</span>
<span class="nb">exit</span>
<span class="k">else</span>
<span class="k">case</span> <span class="nv">$1</span> in
on <span class="o">)</span>
sudo systemctl <span class="nb">enable</span> domoticz
<span class="p">;;</span>
off <span class="o">)</span>
sudo systemctl disable domoticz
<span class="p">;;</span>
* <span class="o">)</span>
<span class="nb">echo</span> <span class="s2">"Choice is on or off"</span>
<span class="nb">exit</span>
<span class="p">;;</span>
<span class="k">esac</span>
<span class="k">fi</span>
</pre></div>
<p>Rendre les fichiers exécutables puis les copier les scripts dans le répertoire <code>/usr/local/bin</code> </p>
<div class="highlight"><pre><span></span>chmod a+x ./*
sudo cp ~/Scripts/* /usr/local/bin
</pre></div>
<h2><a name="head6.8"> </a> 6.8 Ajout des cahiers de programmes pour apprendre/enseigner la programmation</h2>
<p>Ajouter les cahiers de programmes du projet Tremplin des Sciences depuis la <code>forge github</code></p>
<div class="highlight"><pre><span></span>sudo su moon
<span class="nb">cd</span>
git clone http://vidal@depot.tremplin.ens-lyon.fr/Tremplin-des-Sciences/CahiersDeProgrammesCodage
git clone http://vidal@depot.tremplin.ens-lyon.fr/Tremplin-des-Sciences/CahiersDeProgrammesClimat
<span class="nb">exit</span>
sudo su localadm
<span class="nb">cd</span>
git clone http://vidal@depot.tremplin.ens-lyon.fr/Tremplin-des-Sciences/CahiersDeProgrammesCodage
git clone http://vidal@depot.tremplin.ens-lyon.fr/Tremplin-des-Sciences/CahiersDeProgrammesClimat
<span class="nb">exit</span>
<span class="nb">cd</span>
git clone http://vidal@depot.tremplin.ens-lyon.fr/Tremplin-des-Sciences/CahiersDeProgrammesCodage
git clone http://vidal@depot.tremplin.ens-lyon.fr/Tremplin-des-Sciences/CahiersDeProgrammesClimat
</pre></div>
<h2><a name="head6.9"> </a> 6.9 Ajout d'un media-center</h2>
<p>La <code>raspberryPi</code> peut aussi être utilisée en media-center pour y parvenir il suffit de disposer d'une bibliothèque de médias accessibles depuis la raspberry et du logiciel <code>kodi</code>. La manipulation du media-center se fait via l'interface intuitive de <code>kodi</code>.</p>
<p>Pour installer :</p>
<div class="highlight"><pre><span></span>sudo apt install kodi kodi-bin kodi-data
</pre></div>
<h2><a name="head6.10"> </a> 6.10 Image sans interface graphique (type serveur) pour le pilotage de la station météorologique et le partage de données</h2>
<p>Cette image n'a pas de serveur X ni la suite de logiciels du poste de travail de programmation ou de traitement des données climat. Elle est créée avec un script largement simplifié.</p>
<h3><a name="head6.10.1"> </a> 6.10.1 Configuration du réseau statique</h3>
<p>Fournir la configuration suivante dans laquelle <strong><em>.</em></strong>.<strong><em>.</em></strong> représente successivement les adresses du DNS, du réseau qui sera utilisé et de la passerelle. enx* est un contournement temporaire permettant de connecter n'importe quelle interface cette valeur devra être changée par la vraie valeur de l'interface dès qu'elle sera connue (voir plus bas) :</p>
<div class="highlight"><pre><span></span><span class="o">[</span>Match<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>enx*
<span class="nv">Host</span><span class="o">=</span>raspife3W
<span class="nv">Virtualization</span><span class="o">=</span>no
<span class="o">[</span>Network<span class="o">]</span>
<span class="nv">RouteMetric</span><span class="o">=</span><span class="m">10</span>
<span class="nv">IPv6PrivacyExtensions</span><span class="o">=</span><span class="nb">true</span>
<span class="nv">DHCP</span><span class="o">=</span>no
<span class="nv">Address</span><span class="o">=</span>***.***.***.***/24
<span class="nv">Gateway</span><span class="o">=</span>***.***.***.***
<span class="nv">DNS</span><span class="o">=</span>***.***.***.***
</pre></div>
<p>Changer le port de connection <code>/etc/ssh/sshd_config</code>.
Rajouter le user <code>weewx</code> et la clef d'accès aux serveurs
Ajouter les permissions <code>udev</code></p>
<h3><a name="head6.10.2"> </a> 6.10.2 Configuration du logiciel de pilotage de stations météorologiques</h3>
<p>Le logiciel <code>weewx</code> récupère les données de la station météorologique qui lui est connectée et fournit des pages web affichant les mesures réalisées.Une version à jour à la date de création de l'image est installée par défaut ou téléchargé depuis le <a href="http://weewx.com/downloads/">site d'origine</a>. télécharger les mises à jour et les installer au besoin. Après avoir créé le répertoire <code>Logiciels</code> s'il n'existe pas encore, on récupère ici à titre conservatoire une copie du paquet <code>weewx</code>.</p>
<p><strong>Attention !</strong> le logiciel <code>weewx</code> ne figure pas dans les dépôts debian par défaut, les mises à jour doivent être faites à la main en téléchargeant le paquet <code>http://weewx.com/downloads/released_versions/python3-weewx_4.2.0-1_all.deb</code> et en l'installant avec la commande <code>dpkg -i python3-weewx_4.2.0-1_all.deb</code>, lors d'une telle mise à jour de weewx le fichier de configuration <code>/etc/weewx/weewx.conf</code> est réécrit en tenant compte de son contenu avant mise à jour. Toutefois, faire une copie de ce fichier <em>AVANT</em> d'entreprendre la mise à jour, puis comparer et modifier si nécessaire le nouveau fichier (le fichier existant étant utilisé comme modèle les paramètres sont théoriquement conservés mais une erreur même minime de syntaxe peut entrainer la perte de paramètres, il est souhaitable de vérifier attentivement).</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/Weewx
<span class="nb">cd</span> !$
wget http://weewx.com/downloads/released_versions/python3-weewx_4.5.1-1_all.deb
</pre></div>
<h3><a name="head6.10.3"> </a> 6.10.3 Ajout des cadrans interactifs</h3>
<p>Il est possible de proposer plusieurs modes d'affichage. Nous avons choisi d'ajouter ici un affichage par cadrans et un affichage par semaine ou mois téléchargeables depuis la forge <code>github</code>. Les deux ambiances graphiques (skins) qui sont utilisées ici pour afficher les données sont <code>highcharts</code> et <code>Steel-Series</code>. Elles sont intégrées sous la forme d'extensions du logiciel <code>weewx</code> en utilisant la procédure <code>wee_extension</code>.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> ~/Logiciels/Weewx
mkdir Skins
<span class="nb">cd</span> Skins
wget -P . https://github.com/gjr80/weewx-highcharts/releases/download/v0.3.0/hfw-0.3.0.tar.gz
wget -P . https://github.com/gjr80/weewx-steelseries/releases/download/v2.7.5/steelseries-2.7.5.tar.gz
wget -P . https://github.com/gjr80/weewx-realtime_gauge-data/releases/download/v0.4.2/rtgd-0.4.2.tar.gz
sudo systemctl stop weewx
sudo wee_extension --install<span class="o">=</span>hfw-0.3.0.tar.gz
sudo wee_extension --install<span class="o">=</span>steelseries-2.7.5.tar.gz
sudo wee_extension --install<span class="o">=</span>rtgd-0.4.2.tar.gz
</pre></div>
<p>Les éléments de configuration sont intégrés aufichier <code>/etc/weewx/weewx.conf</code> parmi les modifications de configuration déjà effectuées. Il est nécessaire de modifier les paramètres intégrés automatiquement en fonctions des choix d'affichage personnalisés de chacun (notamment les unités). les sections nouvellement installées à modifier sont les suivantes :</p>
<div class="highlight"><pre><span></span> <span class="o">[[</span>Highcharts<span class="o">]]</span>
<span class="nv">skin</span> <span class="o">=</span> Highcharts
<span class="o">[[[</span>Units<span class="o">]]]</span>
<span class="o">[[[[</span>StringFormats<span class="o">]]]]</span>
<span class="o">[[[[</span>Groups<span class="o">]]]]</span>
.../...
<span class="o">[[</span>SteelSeries<span class="o">]]</span>
<span class="nv">skin</span> <span class="o">=</span> ss
<span class="nv">HTML_ROOT</span> <span class="o">=</span> /var/www/html/ss
<span class="o">[[[</span>Units<span class="o">]]]</span>
<span class="o">[[[[</span>StringFormats<span class="o">]]]]</span>
<span class="o">[[[[</span>Groups<span class="o">]]]]</span>
</pre></div>
<p>Les affichages améliorés sont maintenant disponibles.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> ~/Logiciels/Weewx
mkdir Utils
<span class="nb">cd</span> !$
git clone https://github.com/mcrossley/SteelSeries-Weather-Gauges.git
<span class="nb">cd</span> SteelSeries-Weather-Gauges/
</pre></div>
<p>Créer ensuite dans la hiérarchie <code>weewx</code> le dossier qui contiendra le graphisme de l'interface et recopier les fichiers téléchargés.</p>
<div class="highlight"><pre><span></span>sudo mkdir /etc/weewx/skins/ss
sudo cp weather_server/WeeWX/skin.conf /etc/weewx/skins/ss
sudo cp weather_server/WeeWX/index.html.tmpl /etc/weewx/skins/ss
sudo cp weather_server/WeeWX/gauge-data.txt.tmpl /etc/weewx/skins/ss
</pre></div>
<p>S'ils n'existent pas encore ajouter les répertoires suivants et leur contenu</p>
<div class="highlight"><pre><span></span>sudo mkdir /etc/weewx/skins/ss/css
sudo cp web_server/css/*.css /etc/weewx/skins/ss/css
sudo mkdir /etc/weewx/skins/ss/scripts
sudo cp web_server/scripts/*.js /etc/weewx/skins/ss/scripts
</pre></div>
<p>Éditer ensuite le fichier <code>/etc/weewx/skins/ss/scripts/gauges.js</code> et le modifier en fonction des paramètres locaux et des choix d'affichage.</p>
<div class="highlight"><pre><span></span>weatherProgram : <span class="m">6</span>,
imgPathURL : <span class="s1">''</span>,
stationTimeout : <span class="m">10</span>, // <span class="nb">set</span> to twice archive interval, in minutes
showUvGauge : true, // <span class="nb">false</span> <span class="k">if</span> there is no UV sensor
showSolarGauge : true, // <span class="nb">false</span> <span class="k">if</span> there is no solar radiation sensor
showRoseGauge : false, // <span class="nb">true</span> <span class="k">if</span> field WindRoseData is populated
</pre></div>
<p>Pour afficher les mesures en temps réel il est nécessaire de synchroniser la Raspberry Pi avec le serveur web des opendata, cela se fait en modifiant les paramètres <code>[[RSYNC]]</code> de <code>weewx.conf</code>; les modifications sont commentées pour éviter que la synchronisation échoue tant que le réseau n'est pas correctement configuré(il s'agit d'une précaution) :</p>
<div class="highlight"><pre><span></span> <span class="o">[[</span>RSYNC<span class="o">]]</span>
<span class="c1">#delete = 1</span>
<span class="c1">#HTML_ROOT = /var/www/html/ss</span>
<span class="c1">#server = stationsdata.climatetmeteo.fr</span>
<span class="c1">#path = folder_name_path_on_server</span>
<span class="c1">#user = opendata</span>
</pre></div>
<h3><a name="head6.10.4"> </a> 6.10.4 Installation et configuration du pare-feu</h3>
<p>La Raspberry va être exposée sur le net il est important d'être attentifs à la sécurité de cette machine. Une première méthode est de mettre en place un pare-feu mais cette opération est délicate et difficile à faire à la main; nous utiliserons donc un logiciel d'asssitance à la création de pare-feu <code>nftables</code>. Ce logiciel permet d'établir des règles de filtrage avec une syntaxe (relativement) intelligible dans un fichier de configuration, il se charge ensuite de construire et activer les règles de filtrage correspondant aux instructions de l'usager. L'installation du paquet se fait avec la procédure habituelle.</p>
<div class="highlight"><pre><span></span>sudo apt install nftables
</pre></div>
<p>Activer <code>nftables</code> au démarrage par défaut:</p>
<div class="highlight"><pre><span></span>sudo systemctl <span class="nb">enable</span> nftables.service
</pre></div>
<p>Le fichier de configuration se trouve ici <code>/etc/nftables.conf</code>. À titre d'exemple la configuration du pare-feu pour le projet tremplin est proposée ci-dessous commentée afin de permettre le fonctionnement par défaut de l'image. Le pare-feu doit être configuré avec les paramètres locaux de l'usager, si la configuration ne correspond pas à l'environnement réseau de la Raspberry cette dernière peut devenir inaccessible ! <strong>Soyez prudents</strong>. En cas de problème il est toujours possible d'accéder au contenu de la microSD depuis une machine GNU/linux et de modifier le fichier de configuration; si vous êtes sous un autre système d'exploitation il est possible de démarrer votre ordinateur en utilisant une clef USB GNU/linux live qui fournit un ordinateur opérationnel sans rien toucher de ce qui est installé par exemple debian live.</p>
<p>Propositions de fichier de configuration nftables.conf.</p>
<div class="highlight"><pre><span></span><span class="ch">#!/usr/sbin/nft -f</span>
flush ruleset
table inet filter <span class="o">{</span>
<span class="nb">set</span> ALLOWED_SSH <span class="o">{</span>
<span class="nb">type</span> ipv4_addr
flags interval
<span class="c1"># Institution : ***.***.***.0/24</span>
<span class="c1"># Individual : ***.***.***.*** </span>
<span class="c1"># Internal : ***.***.***.0/24, ***.***.***.0/23</span>
<span class="c1"># outbound : ***.***.***.*** </span>
<span class="nv">elements</span> <span class="o">=</span> <span class="o">{</span>
***.***.***.0/24, <span class="se">\</span>
***.***.***.***, <span class="se">\</span>
***.***.***.0/24, ***.***.***.0/23, <span class="se">\</span>
***.***.***.***
<span class="o">}</span>
<span class="o">}</span>
chain input <span class="o">{</span>
<span class="nb">type</span> filter hook input priority <span class="m">0</span><span class="p">;</span>
policy drop<span class="p">;</span>
<span class="c1"># established/related connections</span>
ct state established,related accept
<span class="c1"># invalid connections</span>
ct state invalid drop
<span class="c1"># loopback interface</span>
iif lo accept
<span class="c1"># ICMP & IGMP</span>
ip protocol icmp icmp <span class="nb">type</span> <span class="o">{</span> echo-request, echo-reply, destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem <span class="o">}</span> accept
ip protocol igmp accept
<span class="c1"># SSH (port #####)</span>
tcp dport <span class="c1">##### ip saddr @ALLOWED_SSH accept</span>
<span class="c1"># HTTP (ports 80, #####, #####:#####)</span>
tcp dport <span class="o">{</span> http, https <span class="o">}</span> accept
<span class="c1"># HTTPS (ports 443, #####)</span>
tcp dport <span class="o">{</span> https, <span class="c1">##### } accept</span>
<span class="c1"># mysql</span>
tcp dport <span class="c1">##### accept</span>
<span class="c1"># email</span>
tcp dport <span class="o">{</span> <span class="m">25</span>, <span class="m">587</span> <span class="o">}</span> accept
<span class="o">}</span>
chain forward <span class="o">{</span>
<span class="nb">type</span> filter hook forward priority <span class="m">0</span><span class="p">;</span>
policy drop<span class="p">;</span>
<span class="o">}</span>
chain output <span class="o">{</span>
<span class="nb">type</span> filter hook output priority <span class="m">0</span><span class="p">;</span>
policy accept<span class="p">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<h3><a name="head6.10.5"> </a> 6.10.5 Installation et configuration de la base de données relationnelle mariadb</h3>
<p>Par défaut <code>weewx</code> utilise une base <code>sqlite</code>, pour des raisons d'interopérabilité et de facilitation du partage des données nous installons les composants serveur et client de la base <code>mariadb</code>. Nous effectuons un installation par défaut, au moment de la rédaction (27/11/2020) la dernière version disponible est 10.3.25-0+deb10u1.</p>
<div class="highlight"><pre><span></span>sudo apt install mariadb-client mariadb-server mariadb-common
</pre></div>
<p>La base de données est maintenant installée, il est nécessaire de la configurer. On ajoute un mot de passe à l'utilisateur root, on ajoute ensuite un utilisateur admin avec privilèges qui évite d'utiliser root pour la configuration le mot de passe <code>Achanger1$</code> est utilisé pour tous les comptes cette valeur est à changer comme son nom l'indique !</p>
<div class="highlight"><pre><span></span>sudo systemctl stop mariadb
sudo mysqld_safe --skip-grant-tables --skip-networking <span class="p">&</span>
sudo mysql -u root
FLUSH PRIVILEGES<span class="p">;</span>
MariaDB <span class="o">[(</span>none<span class="o">)]</span>> ALTER USER <span class="s1">'root'</span>@<span class="s1">'localhost'</span> IDENTIFIED BY <span class="s1">'AChanger1$'</span><span class="p">;</span>
MariaDB <span class="o">[(</span>none<span class="o">)]</span>> <span class="se">\q</span>
sudo mysql -u root -p
Welcome to the MariaDB monitor. Commands end with <span class="p">;</span> or <span class="se">\g</span>.
Your MariaDB connection id is <span class="m">2</span>
Server version: <span class="m">10</span>.1.26-MariaDB-0+deb9u1 Debian <span class="m">9</span>.1
Copyright <span class="o">(</span>c<span class="o">)</span> <span class="m">2000</span>, <span class="m">2017</span>, Oracle, MariaDB Corporation Ab and others.
Type <span class="s1">'help;'</span> or <span class="s1">'\h'</span> <span class="k">for</span> help. Type <span class="s1">'\c'</span> to clear the current input statement.
MariaDB <span class="o">[(</span>none<span class="o">)]</span>> <span class="k">select</span> password <span class="o">(</span><span class="s1">'AChanger1$'</span><span class="o">)</span><span class="p">;</span>
+-------------------------------------------+
<span class="p">|</span> password <span class="o">(</span><span class="s1">'AChanger1$'</span><span class="o">)</span> <span class="p">|</span>
+-------------------------------------------+
<span class="p">|</span> *695008F6BF1536D1C456BC7B1226080345359BB9 <span class="p">|</span>
+-------------------------------------------+
<span class="m">1</span> row in <span class="nb">set</span> <span class="o">(</span><span class="m">0</span>.01 sec<span class="o">)</span>
MariaDB <span class="o">[(</span>none<span class="o">)]</span>> SET PASSWORD FOR <span class="nv">mysql</span> <span class="o">=</span> PASSWORD<span class="o">(</span><span class="s1">'AChanger1$'</span><span class="o">)</span><span class="p">;</span>
MariaDB <span class="o">[(</span>none<span class="o">)]</span>> use mysql
Reading table information <span class="k">for</span> completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> CREATE USER <span class="s1">'admin'</span>@<span class="s1">'localhost'</span> IDENTIFIED BY PASSWORD <span class="s1">'*695008F6BF1536D1C456BC7B1226080345359BB9'</span><span class="p">;</span>
Query OK, <span class="m">0</span> rows affected <span class="o">(</span><span class="m">0</span>.00 sec<span class="o">)</span>
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> GRANT ALL PRIVILEGES ON *.* TO <span class="s1">'admin'</span>@<span class="s1">'localhost'</span> WITH GRANT OPTION<span class="p">;</span>
Query OK, <span class="m">0</span> rows affected <span class="o">(</span><span class="m">0</span>.00 sec<span class="o">)</span>
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> CREATE USER <span class="s1">'admin'</span>@<span class="s1">'%'</span> IDENTIFIED BY PASSWORD <span class="s1">'*695008F6BF1536D1C456BC7B1226080345359BB9'</span><span class="p">;</span>
Query OK, <span class="m">0</span> rows affected <span class="o">(</span><span class="m">0</span>.01 sec<span class="o">)</span>
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> GRANT ALL PRIVILEGES ON *.* TO <span class="s1">'admin'</span>@<span class="s1">'%'</span> WITH GRANT OPTION<span class="p">;</span>
Query OK, <span class="m">0</span> rows affected <span class="o">(</span><span class="m">0</span>.00 sec<span class="o">)</span>
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> <span class="k">select</span> host, user, default_role, is_role, password from mysql.user<span class="p">;</span>
+-----------+-------+--------------+---------+-------------------------------------------+
<span class="p">|</span> host <span class="p">|</span> user <span class="p">|</span> default_role <span class="p">|</span> is_role <span class="p">|</span> password <span class="p">|</span>
+-----------+-------+--------------+---------+-------------------------------------------+
<span class="p">|</span> localhost <span class="p">|</span> root <span class="p">|</span> <span class="p">|</span> N <span class="p">|</span> *9FDA0930AF881812755F2746906A517D7C892BA6 <span class="p">|</span>
<span class="p">|</span> localhost <span class="p">|</span> admin <span class="p">|</span> <span class="p">|</span> N <span class="p">|</span> *695008F6BF1536D1C456BC7B1226080345359BB9 <span class="p">|</span>
<span class="p">|</span> % <span class="p">|</span> admin <span class="p">|</span> <span class="p">|</span> N <span class="p">|</span> *695008F6BF1536D1C456BC7B1226080345359BB9 <span class="p">|</span>
+-----------+-------+--------------+---------+-------------------------------------------+
<span class="m">3</span> rows in <span class="nb">set</span> <span class="o">(</span><span class="m">0</span>.00 sec<span class="o">)</span>
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> <span class="se">\q</span>
Bye
</pre></div>
<p>Nous souhaitons pouvoir accéder à la base depuis des machines extérieures (pour partager les données dans le cadre du projet par exemple), pour cela il est nécessaire de modifier quelques paramètres du fichier de configuration <code>/etc/mysql/mariadb.conf.d/50-server.cnf</code>.</p>
<div class="highlight"><pre><span></span>sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
</pre></div>
<p>Pour avoir un accès distant ajouter le paramère <code>skip-bind-address</code> et pour changer le port le paramètre <code>port</code>. Sans changement la base écoute sur le port par défaut et seulement sur localhost.</p>
<div class="highlight"><pre><span></span><span class="o">[</span>mysqld<span class="o">]</span>
<span class="nv">port</span> <span class="o">=</span> ****
</pre></div>
<p>Les options ci-dessous sont obsolètes et le remplacement par défaut en cours de test</p>
<div class="highlight"><pre><span></span>.../...
skip-networking<span class="o">=</span><span class="m">0</span>
skip-bind-address
</pre></div>
<p>Relancer le serveur pour vérifier que les paramètres sont priss en compte.</p>
<div class="highlight"><pre><span></span>sudo systemctl restart mysqld
sudo systemctl status mysqld
</pre></div>
<p>Le système doit être chargé et fournir une réponse du type suivant.</p>
<div class="highlight"><pre><span></span>● mariadb.service - MariaDB database server
Loaded: loaded <span class="o">(</span>/lib/systemd/system/mariadb.service<span class="p">;</span> enabled<span class="p">;</span> vendor preset: enabled<span class="o">)</span>
Active: active <span class="o">(</span>running<span class="o">)</span> since Fri <span class="m">2018</span>-01-19 <span class="m">01</span>:27:45 CET<span class="p">;</span> 6s ago
Process: <span class="m">3616</span> <span class="nv">ExecStartPost</span><span class="o">=</span>/bin/sh -c systemctl unset-environment _WSREP_START_POSITION <span class="o">(</span><span class="nv">code</span><span class="o">=</span>exited, <span class="nv">status</span><span class="o">=</span><span class="m">0</span>/SUCCESS<span class="o">)</span>
Process: <span class="m">3613</span> <span class="nv">ExecStartPost</span><span class="o">=</span>/etc/mysql/debian-start <span class="o">(</span><span class="nv">code</span><span class="o">=</span>exited, <span class="nv">status</span><span class="o">=</span><span class="m">0</span>/SUCCESS<span class="o">)</span>
Process: <span class="m">3496</span> <span class="nv">ExecStartPre</span><span class="o">=</span>/bin/sh -c <span class="o">[</span> ! -e /usr/bin/galera_recovery <span class="o">]</span> <span class="o">&&</span> <span class="nv">VAR</span><span class="o">=</span> <span class="o">||</span> <span class="nv">VAR</span><span class="o">=</span><span class="sb">`</span>/usr/bin/galera_recovery<span class="sb">`</span><span class="p">;</span> <span class="o">[</span> <span class="nv">$?</span> -eq <span class="m">0</span> <span class="o">]</span> <span class="o">&&</span>
Process: <span class="m">3491</span> <span class="nv">ExecStartPre</span><span class="o">=</span>/bin/sh -c systemctl unset-environment _WSREP_START_POSITION <span class="o">(</span><span class="nv">code</span><span class="o">=</span>exited, <span class="nv">status</span><span class="o">=</span><span class="m">0</span>/SUCCESS<span class="o">)</span>
Process: <span class="m">3487</span> <span class="nv">ExecStartPre</span><span class="o">=</span>/usr/bin/install -m <span class="m">755</span> -o mysql -g root -d /var/run/mysqld <span class="o">(</span><span class="nv">code</span><span class="o">=</span>exited, <span class="nv">status</span><span class="o">=</span><span class="m">0</span>/SUCCESS<span class="o">)</span>
Main PID: <span class="m">3586</span> <span class="o">(</span>mysqld<span class="o">)</span>
Status: <span class="s2">"Taking your SQL requests now..."</span>
CGroup: /system.slice/mariadb.service
└─3586 /usr/sbin/mysqld
janv. <span class="m">19</span> <span class="m">01</span>:27:42 raspwife3 systemd<span class="o">[</span><span class="m">1</span><span class="o">]</span>: Starting MariaDB database server...
janv. <span class="m">19</span> <span class="m">01</span>:27:43 raspwife3 mysqld<span class="o">[</span><span class="m">3586</span><span class="o">]</span>: <span class="m">2018</span>-01-19 <span class="m">1</span>:27:43 <span class="m">1996341248</span> <span class="o">[</span>Note<span class="o">]</span> /usr/sbin/mysqld <span class="o">(</span>mysqld <span class="m">10</span>.1.26-MariaDB-0+deb9u1<span class="o">)</span> start
janv. <span class="m">19</span> <span class="m">01</span>:27:45 raspwife3 systemd<span class="o">[</span><span class="m">1</span><span class="o">]</span>: Started MariaDB database server.
</pre></div>
<p>La suite des interventions sur la base de données peut alors se faire depuis un outil à ditance comme <code>DBeaver</code>, pour augmenter la sécurité PHPmyadmin n'est pas installé toutes les fonctionnalités étant fournies par le client <code>DBeaver</code></p>
<p>Pour obtenir un bon fonctionnement il est impératif de synchroniser la configuration de <code>weewx</code> et celle de <code>mariadb</code>. Ces éléments de configuration ne sont pas génériques et doivent être réalisés en fonction des besoins de chaque usager. On pourra notamment :</p>
<ul>
<li>créer un nouvel utilisateur pour les données issues du <code>collège1</code> (user_college1)</li>
<li>créer une nouvelle base de données dédiée au<code>collège1</code> (OpenMetEdu_College1)</li>
<li>donner tous les privilèges au nouvel utilisateur sur la nouvelle base</li>
<li>vérifier que weewx est configuré avec ces mêmes paramètres</li>
</ul>
<p>En fonctionnement sur une base locale weewx requiert une base <code>sqlite3</code> opérationnelle, les paquets sont installés par défaut mais il faut configurer la base en lançant weewx avec la configuration <code>weewx_binding</code> avant de lancer le dispositif opérationnel avec la base mariadb locale <code>wx_mariadblocal_binding</code>.</p>
<h3><a name="head6.10.6"> </a> 6.10.6 Mise en place d'un serveur web</h3>
<p>Nous allons utiliser la base de données locale mariadb installée ci dessus et les outils proposés par le site météo Villarzel. Le site web est installé dans le répertoire /opt/WeatherWeb. Le fichier à configurer est /opt/WeatherWeb/mysql_connect.php</p>
<div class="highlight"><pre><span></span>sudo mkdir /opt/WeatherWeb
sudo nano /opt/WeatherWeb/mysqli_connect.php
</pre></div>
<p>Le fichier est de la forme suivante en remplaçant les <strong>*</strong> par les valeurs correspondant à votre situation :</p>
<div class="highlight"><pre><span></span><?php
<span class="nv">$server</span> <span class="o">=</span><span class="s2">"localhost:********"</span><span class="p">;</span>
<span class="nv">$user</span><span class="o">=</span><span class="s2">"**********"</span><span class="p">;</span>
<span class="nv">$pass</span><span class="o">=</span><span class="s2">"***********"</span><span class="p">;</span>
<span class="nv">$db</span><span class="o">=</span><span class="s2">"******************"</span><span class="p">;</span>
mysql_connect<span class="o">(</span><span class="nv">$server</span>,<span class="nv">$user</span>,<span class="nv">$pass</span><span class="o">)</span> or die <span class="o">(</span><span class="s2">"Erreur SQL : "</span>.mysql_error<span class="o">()</span> <span class="o">)</span><span class="p">;</span>
mysql_select_db<span class="o">(</span><span class="nv">$db</span><span class="o">)</span> or die <span class="o">(</span><span class="s2">"Erreur SQL : "</span>.mysql_error<span class="o">()</span> <span class="o">)</span><span class="p">;</span>
?>
</pre></div>
<p>Il est aussi nécessaire de configurer le serveur web nginx installé par défaut en éditant le fichier <code>/etc/nginx/sites-available/meteoRaspWife3</code>.</p>
<div class="highlight"><pre><span></span>sudo nano /etc/nginx/sites-available/meteoRaspWife3
</pre></div>
<p>Le contenu du fichier doit être du type :</p>
<div class="highlight"><pre><span></span>server <span class="o">{</span>
listen <span class="m">80</span> default_server<span class="p">;</span>
listen <span class="o">[</span>::<span class="o">]</span>:80 default_server<span class="p">;</span>
root /opt/WeatherWeb/<span class="p">;</span>
index index.html index.htm index.php<span class="p">;</span>
server_name _<span class="p">;</span>
location / <span class="o">{</span>
try_files <span class="nv">$uri</span> <span class="nv">$uri</span>/ /index.html<span class="p">;</span>
<span class="o">}</span>
location ~ <span class="se">\.</span>php$ <span class="o">{</span>
fastcgi_split_path_info ^<span class="o">(</span>.+<span class="se">\.</span>php<span class="o">)(</span>/.+<span class="o">)</span>$<span class="p">;</span>
<span class="c1"># With php7-fpm:</span>
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock<span class="p">;</span>
fastcgi_index index.php<span class="p">;</span>
include fastcgi_params<span class="p">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>Pour terminer modifier le fichier de configuration par défaut du serveur web nginx.</p>
<div class="highlight"><pre><span></span>sudo rm /etc/nginx/sites-enabled/default
sudo ln -s /etc/nginx/sites-available/meteoRaspWife3 /etc/nginx/sites-enabled/
</pre></div>
<h3><a name="head6.10.7"> </a> 6.10.7 Mise en place d'une connexion WIFI</h3>
<p>Ce système a été conçu sans accès à un serveur <code>DHCP</code> pour des raisons de sécurité. Il est possible qu'il soit nécessaire d'accéder temporairement à un WIFI pour cela il est nécessaire de faire les manipulations suivantes :
* ajouter un fichier de pilotage du réseau <code>wifi</code>
* installer et configurer le driver du chipset <code>wifi</code>
* installer et configurer un outil de gestion du <code>wifi</code></p>
<h4>Ajout du pilotage du <code>wifi</code></h4>
<div class="highlight"><pre><span></span>cat > /etc/systemd/network/51-wireless.network
<span class="o">[</span>Match<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>wlan0
<span class="nv">Host</span><span class="o">=</span>hostname
<span class="o">[</span>Network<span class="o">]</span>
<span class="nv">DHCP</span><span class="o">=</span>yes
<span class="o">[</span>DHCP<span class="o">]</span>
<span class="nv">RouteMetric</span><span class="o">=</span><span class="m">20</span>
</pre></div>
<h4>Installation et configuration du driver</h4>
<div class="highlight"><pre><span></span>sudo apt install firmware-brcm80211 rfkill iw
</pre></div>
<p>À la date de test (18/09/2022) le module du noyau ne fonctionne pas il est nécessaie de changer de module opérationnel en ajoutant le lien suivant :</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /lib/firmware/brcm/
sudo ln -s ../cypress/cyfmac43430-sdio.bin brcmfmac43430-sdio.raspberrypi,3-model-b.bin
</pre></div>
<h4>Installation et configuration dde wpasupplicant</h4>
<div class="highlight"><pre><span></span>sudo apt install wpasupplicant
</pre></div>
<p>Ajouter le réseau <code>wifi</code> dans le fichier de configuration </p>
<p>le fichier <code>/etc/wpa_supplicant/wpa_supplicant-wlan0.conf</code> doit avoir la forme :</p>
<div class="highlight"><pre><span></span><span class="nv">ctrl_interface</span><span class="o">=</span>/run/wpa_supplicant <span class="nv">GROUP</span><span class="o">=</span>netdev
<span class="nv">update_config</span><span class="o">=</span><span class="m">1</span>
<span class="nv">p2p_disabled</span><span class="o">=</span><span class="m">1</span>
<span class="nv">eapol_version</span><span class="o">=</span><span class="m">1</span>
<span class="nv">ap_scan</span><span class="o">=</span><span class="m">1</span>
<span class="nv">fast_reauth</span><span class="o">=</span><span class="m">1</span>
<span class="nv">network</span><span class="o">={</span>
<span class="nv">ssid</span><span class="o">=</span><span class="s2">"DDID name"</span>
<span class="nv">psk</span><span class="o">=</span><span class="s2">"Passphrase"</span>
<span class="o">}</span>
</pre></div>
<h2><a name="head7"> </a> 7. Propagation des images</h2>
<h3><a name="head7.1"> </a> 7.1. Organisation des services au démarrage</h3>
<p>Tous les services et logiciels décrits ci-dessus sont opérationnels mais par défaut une partie seulement sont activés au démarrage. Il est possible de les démarrer à tout moment soit par localadm (qui dispose des droits de <code>root</code> via le <code>sudo</code> soit en ligne de commande soit en utilisant les scripts préparés à cet effet. Ci dessous le statut des services par défaut :</p>
<ul>
<li>jupyter is set <code>sudo systemctl enable jupyterhub</code></li>
<li>xrdp is set <code>sudo systemctl enable xrdp</code></li>
<li>vncserveris set <code>sudo systemctl enable vncserver</code></li>
<li>mariadb is not set <code>sudo systemctl disable mariadb</code></li>
<li>domotix is not set <code>sudo systemctl disable domoticz</code></li>
<li>weewx is not set <code>sudo systemctl disable weewx</code></li>
<li>nginx is set <code>sudo systemctl enable nginx</code></li>
<li>kodi is available</li>
</ul>
<p><code>weewx</code> and <code>mariadb</code> ne sont pas configurés car leur configuration dépend fortement des paramètres locaux liés à l'utilisateur et à l'usage qui en est fait. <code>xrdp</code> et <code>vncserver</code> permettent de se connecter via des serveurs de terminaux respectivement dans le monde windows ou le monde unix/linux. Une connexion vérifiée est configurée dans le fichier <code>/etc/wpa_supplicant/wpa_supplicant-wlan0.conf</code>. <em>Attention</em> dans certains cas le nom de l'interface n'est pas le nom générique <code>wlan0</code> mais un nom translaté en fonction de l'adresse MAC de l'interface de type <code>wlx############</code> il faut dans ce cas renommer le fichier</p>
<h3><a name="head7.2"> </a> 7.2. Clonage et mise à disposition</h3>
<p>Une fois que tous les programmes souhaités sont ajoutés et toutes les options configurées les images peuvent être diffusées sous forme binaire compressée, il suffit alors à tout usager qui souhaite se les approprier de téchager le fichier et le copier sur une micro-SD qui sera immédiatement opérationnelle. Éteindre la Raspberry pi et extraire la micro-SD puis l'insérer dans un ordinateur (dans le cas ci-dessous elle apparaît sur le device <code>/dev/mmcblk0</code>. Copier "bit à bit" le contenu de la micro-SD sur le disque dur de l'ordinateur avec les options de maîtrise des espaces vides et le contrôle de la taille; l'image proposée dans ce blog pouvant contenir dans une micro-SD de 8Go. Le nom de l'image utilise les règles de nommage utilisées au <a href="#head1.3">chap 1.C</a>. Pour faciliter la copie de l'image on propose de créer le fichier bmap correspondant et de la compresser (le logiciel bmaptools traite directement les images compressées ce qui minimise les temps de téléchargement et évite le temps de décompression)</p>
<div class="highlight"><pre><span></span>sudo dd <span class="k">if</span><span class="o">=</span>/dev/mmcblk0 <span class="nv">of</span><span class="o">=</span><span class="m">2018</span>-01-07-rpi3-stretch.img <span class="nv">bs</span><span class="o">=</span>4M <span class="nv">conv</span><span class="o">=</span>sparse <span class="nv">count</span><span class="o">=</span><span class="m">2500</span>
bmaptool create -o <span class="m">2018</span>-01-07-rpi3-stretch.bmap <span class="m">2018</span>-01-07-rpi3-stretch.img
7z a -txz <span class="m">2018</span>-01-07-rpi3-stretch.img.xz <span class="m">2018</span>-01-07-rpi3-stretch.img
</pre></div>
<p>Les usagers devront télécharger les deux fichiers <code>2018-01-07-rpi3-stretch.img.xz</code> et <code>2018-01-07-rpi3-stretch.bmap</code> et utiliser ensuite bmaptool pour la recopier sur une micro-SD vierge :</p>
<div class="highlight"><pre><span></span>sudo bmaptool copy --bmap <span class="m">2018</span>-01-07-rpi3-stretch.bmap <span class="m">2018</span>-01-07-rpi3-stretch.img.xz /dev/mmcblk0
</pre></div>
<p>Une fois la copie terminée la micro-SD est immédiatement opérationnelle.</p>
<hr>
<h3><em>Webographie</em></h3>
<ol>
<li><a href="https://www.raspberrypi.org">Site principal Raspberry Pi</a></li>
<li><a href="https://github.com/drtyhlpr/rpi23-gen-image.git">Scripts de création de l'image</a> </li>
<li><a href="https://www.debian.org/CD/live/">Image Debian Live</a></li>
<li><a href="https://www.debian.org/CD/faq/#write-usb">Comment créer une clef USB bootable Debian</a></li>
<li><a href="https://jeffhoogland.blogspot.com/2012/05/howto-give-network-manager-sufficient.html">nmcli authorization management</a></li>
<li><a href="https://www.thegeekdiary.com/how-to-configure-and-manage-network-connections-using-nmcli/">nmcli examples</a></li>
<li><a href="https://shapeshed.com/linux-wifi/">wpa_cli configuration</a></li>
</ol>Comment créer une image Debian pour Raspberry Pi3 ou Pi4, buster ou bullseye adaptée au pilotage d'une station météo (+ autres capteurs, CO2, pollution, particules,..)2021-05-23T15:06:00+02:002021-05-23T15:21:00+02:00Gérard Vidaltag:blog.tremplin.ens-lyon.fr,2021-05-23:/GerardVidal/RaspberryPiMetBuildImage.html<p>Comment construire une image <code>debian buster</code> ou <code>debian bullseye</code> standard</p><p>pour une Raspberry Pi (3 ou 4). les images sont construites pour êtres
directement utilisables dans un univers Météo/Climat/quaité de l'air pour piloter une station
Météorologique et différents capteurs (qualité de l'air, bruit lumière etc) gérer les données, apprendre ou enseigner le codage ou la gestion des données avec les outils <code>SNAP!BYOB</code> (comme scratch) et <code>jupyter</code> pour aborder <code>python</code> et <code>javascript</code>. Les versions <code>debian stretch</code>sont maintenant obsolètes, il subsiste quelques références pour des raisons de compatibilité et les anciennes versions des articles se trouvent dans le répertoire <code>Archives</code>.</p>
<p><strong><em>Motivations</em></strong></p>
<p>Le but de cet article est de décrire la procédure technique permettant de construire un système d'exploitation Debian "orthodoxe" (totalement analogue à celui qui est installé sur un ordinateur ordinaire) et qui fonctionne sur une Raspberry Pi.
La motivation principale est de partager une distribution standard augmentée de tous les logiciels nécessaires pour piloter le <code>GPIO</code>, gérer une station météorologique, apprendre à coder en python ou C++ à l'aide d'une interface web <code>jupyter</code>ou <code>jupyterlab</code> gérer les données recueillies et les partger.
La seconde motivation est de proposer à des fins pédagogiques une explication de TOUT ce qui est fait pour construire le système d'exploitation en évitant les scripts ou commandes parfois perçues comme "magiques".</p>
<p>Cet article décrit la construction d'images apparentées, chacune dédiée à un mode de fonctionnement particulier :</p>
<ul>
<li>Une image raspberry Pi0 buster pour piloter une station météo et partager des données</li>
<li>Une image raspberry Pi3 buster pour piloter une station météo et partager des données</li>
</ul>
<hr>
<h3><em>Remerciements</em></h3>
<p>Carole Larose, Éric le Jan et Charles-Henri Eyraud.</p>
<hr>
<h3><em>Sommaire</em></h3>
<ol>
<li>
<p><a href="#head1">Stratégie adoptée</a></p>
<p>1.1. <a href="#head1.1">Trois phases de construction</a></p>
<ul>
<li><a href="#head1.1.1">Construction de l'image avec le script automatisé "rpi23genimage" et premiers services</a></li>
<li><a href="#head1.1.2">Ajustements manuels génériques</a></li>
<li><a href="#head1.1.3">Configuration particulière avancée</a></li>
</ul>
<p>1.2. <a href="#head1.2">Six générations de RaspberryPi (rpi0-rpi1-rpi2-rpi3-rpi3B+-rpi4), deux familles d'images (codage-station météo) et deux distributions (buster-bullseye)</a></p>
<p>1.3. <a href="#head1.3">Mode de classement et moyen de retrouver une information</a></p>
</li>
<li>
<p><a href="#head2">Construction de l'image avec le script "rpi23genimage" et premiers services</a></p>
<p>2.1. <a href="#head2.1">Raspberry Pi0 Buster</a></p>
<p>2.2. <a href="#head2.2">Raspberry Pi3 BullsEye</a></p>
</li>
<li>
<p><a href="#head3">Ajustements manuels génériques</a></p>
<p>3.1. <a href="#head3.1">Copie de l'image sur une micro-SD</a></p>
<p>3.2. <a href="#head3.2">ajustement de la taille de l'image</a></p>
<p>3.3 <a href="#head3.3">Installation du réseau (seulement si au boot la raspberry ne le trouve pas)</a></p>
</li>
<li>
<p><a href="#head4">Ajustements après démarrage de la Raspberry munie de sa nouvelle image</a></p>
<p>4.1. <a href="#head4.1">Modification de la taille de l'espace utilisé (au besoin seulement)</a></p>
<p>4.2. <a href="#head4.2">Mises à jour et installation d'utilitaires</a></p>
<p>4.3. <a href="#head4.3">Ajout d'utilisateurs et distribution des droits</a></p>
<p>4.4. <a href="#head4.4">Configuration du réseau</a></p>
<ul>
<li><a href="#head4.4.1">Configuration de systemd-networkd</a></li>
<li><a href="#head4.4.2">IP fixe présélectionnée</a></li>
<li><a href="#head4.4.3">IP dynamique alternative fournie par un DHCP</a> </li>
</ul>
<p>4.5 <a href="#head4.5">Modification des accès au <code>GPIO</code> et à la caméra</a></p>
</li>
<li>
<p><a href="#head5">Utilisation de la Raspberrry en point d'accès web (Hotspot)</a></p>
</li>
<li>
<p><a href="#head6">Configurations particulières avancées</a></p>
<p>6.1. <a href="#head6.1">Ajouts permettant entre autres l'apprentissage de la programmation</a></p>
<ul>
<li><a href="#head6.1.1">Compilation d'un cmake récent</a></li>
<li><a href="#head6.1.2">Ajout de fontes</a></li>
<li><a href="#head6.1.3">Activation de la caméra raspberry Pi</a> <ul>
<li><a href="#head6.1.3.1">Détection de la caméra</a></li>
<li><a href="#head6.1.3.2">Ajout des logiciels de pilotage de la caméra </a></li>
</ul>
</li>
<li><a href="#head6.1.4">Reconfiguration du réseau filaire</a> </li>
</ul>
<p>6.2 <a href="#head6.2">Mise à jour des librairies upm et mraa depuis <code>github</code></a></p>
<ul>
<li><a href="#head6.2.1">Récupération et installation de Node.js</a></li>
<li><a href="#head6.2.2">Récupération et construction du paquet swig</a></li>
<li><a href="#head6.2.3">Récupération et construction du paquet libopenzwave</a></li>
<li><a href="#head6.2.4">Récupération et construction du paquet modbus</a></li>
<li><a href="#head6.2.5">Récupération et construction du paquet tinyb</a></li>
<li><a href="#head6.2.6">Construction de mraa et upm</a></li>
<li><a href="#head6.2.7">Installation de compléments Python</a></li>
</ul>
<p>6.3 <a href="#head6.3">Installation de Jupyter et Jupyterhub</a></p>
<ul>
<li><a href="#head6.3.1">Configuration de la sécurité et du lancement par le user callisto</a></li>
<li><a href="#head6.3.2">Ajout de moteurs nodeJS R et java dans l'environnement jupyter/jupyterhub</a></li>
<li><a href="#head6.3.3">Installation d'un service <code>jupyterlabhub</code></a></li>
</ul>
<p>6.4 <a href="#head6.4">Ajout de scripts pour démarrer ou supprimer un service au démarrage</a></p>
<ul>
<li><a href="#head6.4.1">Pour <code>jupyterhub</code></a></li>
<li><a href="#head6.4.2">Pour <code>weewx</code></a></li>
</ul>
<p>6.5 <a href="#head6.5">Ajout des cahiers de programmes pour apprendre/enseigner la programmation</a></p>
<p>6.6 <a href="#head6.6">Compléments pour le pilotage de la station météorologique des capteurs et le partage de données</a> </p>
<ul>
<li><a href="#head6.6.1">Configuration du logiciel de pilotage de stations météorologiques</a></li>
<li><a href="#head6.6.2">Ajout des cadrans interactifs</a></li>
<li><a href="#head6.6.3">Installation et configuration du pare-feu</a></li>
<li><a href="#head6.6.4">Installation et configuration de la base de données relationnelle mariadb</a></li>
<li><a href="#head6.6.5">Mise en place d'un serveur web</a></li>
</ul>
</li>
<li>
<p><a href="#head7">Configuration personnalisée de la Raspberry Pi par site</a></p>
</li>
<li>
<p><a href="#head8">Propagation des images par clonage</a></p>
<p>8.1. <a href="#head8.1">Changement des noms</a></p>
<p>8.2. <a href="#head8.2">Copie et conversion</a></p>
</li>
</ol>
<hr>
<h3><em>Téléchargements</em></h3>
<ol>
<li><a href="https://github.com/drtyhlpr/rpi23-gen-image">rpi23-gen-image</a></li>
<li><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/files/tip/">g_vidal rpi23-gen-image</a></li>
<li><a href="http://weewx.com/downloads/released_versions/python3-weewx_4.2.0-1_all.deb">logiciel weewx</a></li>
<li><a href="https://media.tremplin.ens-lyon.fr/isoImages/RaspBerry/">Images téléchargeables raspberryPi du projet Tremplin</a></li>
<li>
<ol>
<li><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/files/1bdc606a42030af4751b66f2ab1e00d849ad1350/templates/raspife2-buster_19-09-08">modèle de création d'image raspberry Pi 2 raspife2-buster_19-09-08</a></li>
</ol>
</li>
</ol>
<hr>
<h1><a name="head1"> </a> 1. Stratégie adoptée</h1>
<p>Lors du développement du projet "Météo et Climat tremplin pour l'enseignement des sciences et dès que l'utilisation d'objets connectés (Raspberry Pi Odroïd Intel edison, Intel joule) a été entérinée, des images ont été construites au coup par coup pour soutenir les fonctions attribuées à chacun des objets connectés. Cet article est le second d'une série de 3 présentant la création de l'image dédiée au pilotage de la station météo et des capteurs environnementauw qui peuvent lui être associés</p>
<ul>
<li><a href="https://blog.tremplin.ens-lyon.fr/GerardVidal/RaspberryPiBuildImage.html">Comment créer une image Debian pour Raspberry Pi0 -> Pi4, buster ou bullseye adaptée à vos besoins (exemple Météo-Climat)</a></li>
<li><a href="https://blog.tremplin.ens-lyon.fr/GerardVidal/drafts/RaspberryPiMetBuildImage.html">Comment créer une image Debian pour Raspberry Pi3 -> Pi4, buster ou bullseye adaptée au pilotage d'une station météo et autres capteurs.</a></li>
<li><a href="http://blog.tremplin.ens-lyon.fr/GerardVidal/Use_Pi3W_Stretch.html">Piloter une station météorologique avec une Raspberry Pi3 (image ENS-IFÈ) et participer au réseau OpenMetEdu (optionnel)</a></li>
</ul>
<p>La procédure décrite ci-dessous a été réalisée à partir d'un ordinateur fonctionnant sous système d'exploitation debian (bullseye), si on ne dispose pas d'une telle machine il est possible de réaliser ce travail à partir d'une distribution "live" sur une clef USB qui s'installe sur tout ordinateur sans toucher au système d'exploitation et aux données existantes. Pour conserver l'état du système ainsi créé on peut utiliser une distribution "persistante" voir <a href="http://blog.tremplin.ens-lyon.fr/GerardVidal/UsbKey_Pi3W_Config.html">Créer et utiliser une clef USB GNU/linux bootable persistante pour configurer une raspberry Pi</a>.</p>
<h2><a name="head1.1"> </a> 1.1 Trois phases de construction</h2>
<p>La construction d'une image se passe en trois phases:</p>
<ul>
<li>Tout d'abord construction d'une image minimale en utilisant le script automatisé de <a href="https://github.com/drtyhlpr">drtyhlpr</a> disponible sur le dépôt <a href="http://github.com">github</a> <a href="https://github.com/drtyhlpr/rpi23-gen-image">rpi23-gen-image</a> et sur le <a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/files/tip/">dépôt tremplin des sciences</a>,</li>
<li>ensuite réalisation d'un certain nombre d'ajustemts génériques à l'imagegénérique obtenue dont une partie est réalisable directement sur la micro-SD l'autre devant être exécutée lors du premier démarrage</li>
<li>enfin modifications adaptées à chacune des fonctions attendues pour la raspberry Pi considérée</li>
</ul>
<h3><a name="head1.1.1"> </a> 1.1.1 Construction de l'image avec le script automatisé "rpi23genimage" et premiers services <a href="#head2">chap. 2</a></h3>
<p>Cette opération est totalement automatisée grâce au travail piloté par <code>drtyhlpr</code>sur <code>github</code>, le développement de ces scripts a besoin de développeurs et de testeurs n'hésitez pas à contribuer à ce travail si vous le pouvez. L'image créée est minimale bien que de nombreuses options permettent déjà de la profiler (cf. plus bas), quelques profils particuliers dont celui qui a été utilisé sont disponibles sur le <a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/files/tip/">dépôt tremplin des sciences</a> ou <a href="https://github.com/g-vidal/rpi23-gen-image">github</a>.</p>
<h3><a name="head1.1.2"> </a> 1.1.2 Ajustements manuels génériques <a href="#head3">chap. 3</a></h3>
<p>Dans cette partie du travail sont réalisés tous les ajustements possibles après le premier démarrage de la raspberry avec sa nouvelle image. Cela permet entre autres de prendre en compte le support physique utilisé, l'environnement opérationnel de la future raspberry et quelques fonctionnalités qui ne peuvent être ajoutées lors de la création. L'image fournie contient un ensemble d'usagers et de services préinstallés.</p>
<h3><a name="head1.1.3"> </a> 1.1.3 Configuration particulière avancée <a href="#head4">chap. 4</a></h3>
<p>Les Raspberries Pi3 sont d'admirables petites machines mais leur puissance reste limitée et il est judicieux de les cantonner à un nombre limité de fonctions en supprimant autant que possible tout ce qui est superflu. Par exemple l'image qui pilote la station n'a pas besoin d'écran et toute l'infrastructure d'affichage graphique est supprimée ce qui améliore grandement les performances de pilotage de la station et de manipulation des données.</p>
<h2><a name="head1.2"> </a> 1.2 Quatre générations de RaspberryPi (rpi2-rpi3-rpi3B+-rpi4), deux familles d'images (codage-station météo) et deux distributions (buster-bullseye)</h2>
<p>Au cours du projet nous avons manipulé des raspbrries Pi-2, Pi-3, Pi-3B+ et pi4 ; afin de conserver une compatibilité avec les premiers matériels installés des images pour raspberries Pi 2, 3, 3B+ sont proposées. Dans la mesure où plus aucune raspberry pi 2 ne pilote de station météorologique il n'y a pas d'image de raspberry Pi2 pour le pilotage d'une station météorologique avec <code>weewx</code>. S'il existe un besoin on pourra s'inspirer de la construction de la raspberry Pi W3 en changeant les paramètres liés au modèle et au réseau (On ne peut pas garantir que des problèmes de compilation n'apparaissent pas). </p>
<h2><a name="head1.3"> </a> 1.3 Mode de classement et moyen de retrouver une information</h2>
<p>Le nom des images de raspberries crées est formé en suivant la règle suivante :</p>
<ul>
<li>date AAAA-MM-JJ "-"</li>
<li>modèle rpi2, rpi3, rpi3P (3 BPlus) ou rpi4</li>
<li>fonction W pour la raspberry <code>weewx</code> de pilotage de la station météo et capteurs, rien pour les autres</li>
<li>distribution de debian utilisée <code>buster</code> ou <code>bullseye</code> (des versions <code>stretch</code> existent dans les archives)</li>
<li>pour les rpi4 la version 64 bits contient "-64"</li>
<li>extension : type de fichier img ou bmap (éventuellement compression xz)</li>
</ul>
<p>Ainsi l'mage du 22 octobre 2019 buster pi3 pour la programmation sera nommée : <code>2019-10-22-rpi3-buster.img.xz</code>. L'image pour raspberry4 64 bits faite le 10/02/2020 avec la distribution buster a pour nom : <code>2020-02-10-rpi4-buster-64.img</code></p>
<h1><a name="head2"> </a> 2. Construction de l'image avec le script "rpi23genimage" et premiers services</h1>
<p>Le Travail reporté ci-dessous a été effectivement réalisé à partir d'un ordinateur linux. Windows a finalement intégré la possibilité d'utiliser linux au sein d'applications dédiée (voir l'un des nombreux tutoriaux sur comment installer une distribution linux dans windows10). L'unix de MacOs est suffisamment proche de linux pour que beaucoup de choses soient aussi faisables depuis cette plateforme. Toutefois, une solution "non intrusive" consiste à utiliser une <code>clef bootable Linux live</code> dont la description est <a href="https://blog.tremplin.ens-lyon.fr/GerardVidal/UsbKey_Pi3W_Config.html">ici</a> et d'appliquer les commandes proposées, cela peut s'avérer extrêmemnt utile pour la copie de l'image sur une micro-SD.</p>
<p>Toutes les constructions d'images ci-dessous s'appuient sur le travail de <a href="https://github.com/drtyhlpr">drtyhlpr</a> disponible sur le dépôt <a href="http://github.com">github</a> <a href="https://github.com/drtyhlpr/rpi23-gen-image">rpi23-gen-image</a>. Le dépôt <a href="http://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage">g_vidal rpi23-gen-image</a> est un clône de <code>rpi23-gen-image</code> maintenu à jour autant que possible auquel sont ajoutés quelques fichiers décrits dans les chapitres suivants. Des différences peuvent exister entre les versions commentées ici et les versions disponibles en ligne lorsque des modifications doivent être effectuées pour respecter l'évolution de Debian, la version en ligne sur <code>github</code> est à priori et sauf indication contraire toujours la plus à jour (pour des raisons de sécurité les mots de passe et les indications de chemins sont remplacées par des <code>*****</code>).</p>
<p>Le travail s'effectue dans la hiérarchie de fichiers obtenue par clonage du dépôt <a href="http://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage">g_vidal rpi23-gen-image</a>. </p>
<div class="highlight"><pre><span></span>ls -R
.:
bootstrap.d/ files/ functions.sh LICENSE packages/ README.md rpi23-gen-image.sh* rpi23-gen-image.sh~* templates/
./bootstrap.d:
<span class="m">10</span>-bootstrap.sh <span class="m">12</span>-locale.sh <span class="m">14</span>-fstab.sh <span class="m">20</span>-networking.sh <span class="m">30</span>-security.sh <span class="m">32</span>-sshd.sh <span class="m">42</span>-fbturbo.sh <span class="m">44</span>-nexmon_monitor_patch.sh <span class="m">99</span>-reduce.sh
<span class="m">11</span>-apt.sh <span class="m">13</span>-kernel.sh <span class="m">15</span>-rpi-config.sh <span class="m">21</span>-firewall.sh <span class="m">31</span>-logging.sh <span class="m">41</span>-uboot.sh <span class="m">43</span>-videocore.sh <span class="m">50</span>-firstboot.sh
./files:
apt/ boot/ dpkg/ etc/ firstboot/ initramfs/ iptables/ locales/ modules/ mount/ network/ sysctl.d/ xorg/
./files/apt:
02nocache 03compress 04norecommends 10proxy sources.list
./files/boot:
config.txt uboot.mkimage
./files/dpkg:
01nodoc
./files/etc:
<span class="m">99</span>-com.rules rc.local*
./files/firstboot:
<span class="m">10</span>-begin.sh <span class="m">21</span>-regenerate-initramfs.sh <span class="m">30</span>-generate-ssh-keys.sh <span class="m">41</span>-create-resolv-symlink.sh <span class="m">99</span>-finish.sh
<span class="m">20</span>-expandroot.sh <span class="m">23</span>-restart-dphys-swapfile.sh <span class="m">40</span>-generate-machineid.sh <span class="m">42</span>-config-ifnames.sh
./files/initramfs:
crypt_unlock.sh expand_encrypted_rootfs expand-premount* expand-tools*
./files/iptables:
flush-ip6tables.sh flush-iptables.sh ip6tables.rules ip6tables.service iptables.rules iptables.service nftables6.rules nftables.rules
./files/locales:
locale
./files/modules:
raspi-blacklist.conf rpi2.conf
./files/mount:
crypttab fstab
./files/network:
eth0.network eth.network host.conf hostname hosts interfaces wlan0.network wlan.network
./files/sysctl.d:
<span class="m">81</span>-rpi-vm.conf <span class="m">82</span>-rpi-net-hardening.conf <span class="m">83</span>-rpi-printk.conf <span class="m">84</span>-rpi-ASLR.conf
./files/xorg:
<span class="m">99</span>-fbturbo.conf
./packages:
python3-weewx_4.2.0-1_all.deb
./templates:
raspife4-64-buster_20-02-20 rpi1buster
raspife0W-buster_21-01-08 raspife4-32-buster_20-02-04 rpi1Pbuster
raspife3-buster_20-10-01 raspife4-64-buster_20-11-01 rpi1Pstretch
raspife1P-buster_20-12-28 raspife3-buster_20-11-01 rpi1stretch
raspife3-buster_20-11-21 raspife4-64-bullseye_20-11-14 raspife4-64-buster_20-11-17 rpi2buster
raspife2-buster_20-11-29 rpi2stretch
raspife3-buster-arm64 raspife4-64-bullseye_20-11-17 raspife4-bullseye_20-11-06 rpi3buster
raspife3-bullseye_20-02-02 raspife3P-buster rpi3buster-fullconfig
raspife4-64-bullseye_20-11-21 rpi3Pbuster
raspife3-bullseye_20-11-08 raspife3P-buster_20-11-01 raspife4-64-bullseye_20-11-21~ raspife4-buster_20-11-01
rpi3Pstretch
raspife3-bullseye_20-11-19 raspife3P-buster_21-01-24 raspife4-64-bullseye_21-01-16 README.md
rpi3stretch
rpi0buster rpi3-stretch-arm64-4.14.y
raspife3-bullseye_21-05-16 raspife3W-bullseye_21-05-16 raspife4-64-buster_20-02-10 rpi0stretch
</pre></div>
<p>Pour construire les images on met en place le noyau linux X.YY proposé par le dépôt officiel <a href="https://github.com/raspberrypi/linux">RaspberrryPi/linux</a>. Au moment de la rédaction on utilise le noyau 5.10 pour <code>buster</code> et <code>bullseye</code> (la migration est proche...).</p>
<p>Les 2 parties ci-dessous sont totalement <strong>indépendantes</strong>, le lecteur peut directement se reporter à la construction de l'image souhaitée. Dans tous les cas l'utilisateur privilégié initial (créé par défaut lors de la construction de l'image) s'appelle <code>ens-ife</code> dans les fichiers de configuration. Il est pourvu d'une clef ssh pour éviter l'utilisation de mots de passe (un mot de passe temporaire de secours est toutefois prévu dans la configuration). L'utilisateur privilégié <code>ens-ife</code> est réservé au contructeur de l'image, un autre utilisateur privilégié <code>localadm</code>est créé pour fournir à un tiers installateur de l'image les droits d'administration. Les exemples fournis ont été effectivement utilisés pour construire des images <strong>MAIS</strong> l'outil <code>rpi23-gen-image</code> est vivant et la communauté active, des modifications légères peuvent s'avérer nécessaires entre deux mises à jour du blog. </p>
<h2><a name="head2.1"> </a> 2.1 Raspberry Pi0 Buster</h2>
<p>Cette image a été générée en utilisant le fichier template <code>raspife0W-buster_21-01-08</code>
et le script standard <code>rpi23-gen-image.sh</code>. Ce travail étant réalisé dans le cadre
du projet <strong>Météo Climat Tremplin pour l'enseignement des Sciences</strong><br>
le package <a href="http://weewx.com/downloads/">weewx</a> de gestion de stations météorologiques
est introduit par défaut; il permet d'illustrer l'incorporation de paquets debian
non présents dans les dépôts par défaut.</p>
<p>Les instructions sont lancées depuis la racine du dépôt listé ci-dessus.</p>
<div class="highlight"><pre><span></span>sudo rm -r /data/RpiGenImage/Images/buster/build
sudo <span class="nv">CONFIG_TEMPLATE</span><span class="o">=</span>raspife0W-buster_21-01-08 ./rpi23-gen-image.sh
</pre></div>
<p>Les particularités liées au processeur <code>armel6</code> sont précisées dans le texte lorsque nécessaire.</p>
<h2><a name="head2.2"> </a> 2.2 Raspberry Pi3 BullsEye</h2>
<p>Cette image a été générée en utilisant le fichier template <code>raspife3W-bullseye_21-05-16</code> et le script standard <code>rpi23-gen-image.sh</code>. ce travail étant réalisé dans le cadre du projet <strong>Météo Climat Tremplin pour l'enseignement des Sciences</strong>. L'utilisation de la distribution bullseye permet d'assurer une veille sur l'évolution de la distribution Debian et anticiper les effets des changements de certains paquets sur le projet. Cette est image de la distribution testing n'et habituellement pas recommandée à un utilisateur ordinaire mais fera certainement le bonheur d'un utilisateur avancé à l'affut de dernières mises à jour, cette image présente tous les avantages et inconvénients d'une distribution "debian testing". La date de passage du statut <code>testing</code> au statut <code>stable</code> de la distribution <code>bullseye</code> est très proche et l'utilisation de cette distribution permet d'anticiper ce changement. Le package <a href="http://weewx.com/downloads/">weewx</a> de gestion de stations météorologiques est introduit par défaut; il permet d'illustrer l'incorporation de paquets debian non présents dans les dépôts par défaut. les deux librairies <a href="">mraa</a> et <a href="">upm</a> permettent de gérer une multitude de capteurs avec les langages <code>C</code>, <code>python</code>, <code>java</code>, <code>javascript</code>. Cette énorme flexibilité et la richesse de la liste des capteurs traités en fait probablement la solution la plus polyvalente du marché. Quelques autre paquets supplémentaires ont été ajoutés et certains paquets présents dans la version stretch ont du être retirés du fait d'incompatibilités avec la version deu noyau choisi.</p>
<p>Les instructions sont lancées depuis la racine du dépôt listé ci-dessus.</p>
<div class="highlight"><pre><span></span>sudo rm -r /data/RpiGenImage/Images/bullseye/build
sudo <span class="nv">CONFIG_TEMPLATE</span><span class="o">=</span>raspife3-bullseye_20-11-19 ./rpi23-gen-image.sh
</pre></div>
<p>Le fichier <code>raspife3W-bullseye_21-05-16</code> dérive de <code>raspife3-bullseye_20-11-19</code> mais en diffère sur un certain nombre de points assurant la cohérence entre la procédure-le noyau-le choix effectués. Il se trouve dans le répertoire <code>templates</code> et contient les informations présentées ci-dessous. Se reporter à la documentation de <code>rpi23-gen-image</code> pour avoir des précisions sur les paramètres utilisés. Ces informations sont celles qui ont été extraites du fichier de configuration qui a permis de produire l'image proposée au téléchargement. Les paquets listés dans <code>APT_INCLUDES_LATE=""</code> sont ceux qui sont ajoutés à la construction par défaut pour les besoins du projet. On y trouve les outils de compilation, le langage python et python3, les ressources pour l'affaichage graphique et la manipulation de graphiques et vidéos, firefox et quelques utilitaires ainsi que des paquets ajoutés au coup par coup au cours du développement du projet.</p>
<p><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage/files/1bdc606a42030af4751b66f2ab1e00d849ad1350/templates/raspife3-bullseye_19-11-09">télécharger le fichier raspife3-bullseye_19-11-09</a></p>
<p>La trace de l'exécution apparait à l'écran, la durée dépend de la puissance de la machine utilisée et peut atteindre une heure ou plus. Lorsque tout se passe bien l'exécution s'achève par les messages suivants :</p>
<div class="highlight"><pre><span></span>killing processes using mount point ...
removing temporary mount points ...
/****/bullseye/***********.img <span class="o">(</span><span class="c1">####M) : successfully created</span>
</pre></div>
<p>On dispose alors de deux fichiers :
* <code>rpi3-bullseye***.bmap</code>
* <code>rpi3-bullseye***.img</code></p>
<p>qui peuvent être directement utilisés ou être enrichis comme proposé dans les chapitres suivants. Dans les deux cas il est nécessaire pour poursuivre de copier cette image sur une micro-SD en utilisant la commande <code>bmaptool copy</code> (installer le paquet bmaptools si nécessaire).</p>
<h1><a name="head3"> </a> 3. Ajustements manuels génériques</h1>
<p>La micro-SD qui va être utlisée deviendra le disque dur de la Raspberry Pi, les accès à la partie système doivent donc être privilégiés c'est pourquoi dans ce qui suit il est impératif d'agir en tant qu'utilisateur privilégé pour pouvoir faire les modifications. <strong>ATTENTION</strong> à ne pas modifer les fichiers de la machine hôte utilisée pour travailler.... <strong>Les conséquences seraient dramatiques</strong> !
Le tutoriel qui suit est réalisé en plaçant la microSD vierge dans un connecteur de carte SD, sous linux il est en général affecté à <code>/dev/mmcblkO</code>. Le nom du <code>"device"</code> utilisé pour la micro-SD peut varier en fonction de la configuration de la machine hôte. <strong>ATTENTION</strong> l'utilisation d'adapteurs USB fonctionne mais peut prsenter de légères différences avec les situations décrites ci-dessous, notamment le device sera <code>/dev/sd?</code> (? est une lettre a b c d e f...). <strong>ATTENTION</strong> à bien vérifier la lettre correspondant au bon <code>device</code></p>
<h2><a name="head3.1"> </a> 3.1 Copie de l'image sur une micro-SD</h2>
<p>L'image issue du processus <code>rpi23genimage</code> est opérationnelle et peut donc être chargée dans une Raspberry Pi qui démarrera avec elle sans interface graphique, le but du travail décrit par ce chapître est de lui fournir quelques améliorations. On copie d'abord l'image sur une microSD. La création de l'image a fourni un fichier <code>.bmap</code> qui permet d'utiliser l'outil d'accélération de la copie <code>bmaptools</code> si on dispose d'un ordinateur équipé de ce logiciel. Le paquet <code>bmap-tools</code> existe dans la plupart des <code>distributions linux</code>(en cas de distribution très ancienne la version de bmap-tools peut être incompatible avec celle qui a été utilisée pour fabriquer l'image dans ce cas utiliser la procédure standard avec la commande dd). Quelques exemples de copie de l'image sur la <code>carte SD</code>, l'option <code>--bmap</code> est devenue inutile si l'image porte le même nom que la bmap. L'intérêt de bmaptool est de ne pas obliger à décompresser l'image. le nom de support de destination dépend de l'ordinateur utilisé (/dev/mmcblk0 ou /dev/sdg /dev/sdc...) La commande de copie est <strong>irréversible</strong> elle détruit tout ce qui se trouve à l'adresse de destination <em>toujours vérifier que la destination écrite est bien celle qui est souhaitée pour ne pas perdre de données</em>.</p>
<div class="highlight"><pre><span></span>sudo bmaptool copy --bmap <span class="m">2021</span>-05-17-rpi3W-bullseye.bmap <span class="m">2021</span>-05-17-rpi3W-bullseye.img.xz /dev/sdd
</pre></div>
<p>S'il n'est pas possible d'utiliser bmaptool il est toujours possible de décompresser l'image et de la recopier avec la commande <code>dd</code> qui réalise une "copie brute" (ne pas utiliser de commande de copie de ficher ou un glisser déposer car la copie obtenue ne sera pas opérationnelle).</p>
<div class="highlight"><pre><span></span>7z x <span class="m">2021</span>-05-17-rpi3W-bullseye.img.xz
dd <span class="k">if</span><span class="o">=</span><span class="m">2021</span>-05-17-rpi3W-bullseye.img <span class="nv">of</span><span class="o">=</span>/dev/mmcblk0 <span class="nv">bs</span><span class="o">=</span>4M
</pre></div>
<p>La valeuer de <code>block size (bs)</code> dépend de beaucoup de paramètres hard et soft de l'ordinateur utilisé il peut considérablement modifier le temps de copie, éventuellement le modifier pour améliorer les temps de transfert en fonction des propriétés de l'ordinateur utilisé.</p>
<p>Les images créées n'occupent qu'une partie de l'espace disponible, il faut prévoir de redimensionner la partition pour occuper tout l'espace disponible.</p>
<h2><a name="head3.2"> </a> 3.2 Ajustement de la taille de l'image</h2>
<p>L'image qui vient d'être produite est inscrite sur une partition qui a été ajustée à la taille de cette image augmentée de quelques mégaoctets par sécurité. Afin de pouvoir effectuer les modifications suivantes il est impératif d'agrandir la partition pour accommoder l'espace nécessaire pour stocker les différents fichiers de configuration ainsi que tous les nouveaux programmes nécessaires. Pour y parvenir lorsque l'image a été copiée sur une microSD montée sur <code>/dev/mmcblk0</code> deux solutions sont proposées ici :</p>
<p><strong>Utiliser le commande <code>gparted</code></strong>:</p>
<div class="highlight"><pre><span></span>sudo gparted
</pre></div>
<p>Dans le logiciel gparted :</p>
<ul>
<li>démonter les deux partitions de la SD</li>
<li>redimensionner la seconde partition (ext4)</li>
<li>choisir une dimension compatible avec la SD utilisée ou avec les SD cibles, penser à prendre un peu de marge car toutes les SD ne proposent pas <strong>effectivement</strong> tout l'espace annoncé et par ailleurs ne pas oublier que les constructeurs annoncent les tailles en unités du Système International (puissances de 10) alors que les ordinateurs mesurent les tailles en binaire (pussances de 2) ainsi une SD achetée pour 8 Gio contiendra au mieux 8 x 10 ^ 9 octets = 8 000 000 000 octets et pas les 8Go 8 x 2 ^ 30 = 8 x 1073741824 = 8 589 934 592 que vous souhaiteriez y mettre ! (Dans cet exemple 7.4 Go est voisin de la limite des 8Gio)</li>
</ul>
<p>Même si on pent encore en trouver les microSD de taille <code>8 Go</code> ont quasiment disparu et on peut raisonnablement adopter une taille allant jusqu'à <code>16 Go</code> pour cette image de base sans risque d'empêcher un usager d'utiliser l'image ainsi créée. Suivant les logiciels installés à postériori le système peut dépasser <code>20 Go</code> et suivant les usages mis en oeuvre l'espace requis peut être encore plus important. Toujours choisir une taille de SD adaptée aux besoins envisagés ou choisir une autre solution : par exemple utiliser un disque SSD sur l'USB3 de la raspi4.</p>
<p><strong>Une autre méthode est d'utiliser la commande fdisk en tant que superutilisateur.</strong></p>
<div class="highlight"><pre><span></span>sudo fdisk /dev/mmcblk0
</pre></div>
<ul>
<li>Taper <code>m</code> pour voir la liste des commandes (juste pour information)</li>
<li>
<p>Taper <code>p</code> pour voir la liste des partitions disponibles, normalement il y en deux</p>
<ul>
<li>une FAT : /dev/mmcblk0p1 * 2048 133119 131072 64M c W95 FAT32 (LBA)</li>
<li>une linux : /dev/mmcblk0p2 133120 62517247 62384128 29,8G 83 Linux</li>
</ul>
</li>
<li>
<p>Taper ensuite </p>
<ul>
<li><code>d</code> puis </li>
<li><code>2</code> puis </li>
<li><code>n</code> puis </li>
<li><code>p</code> puis </li>
<li><code>2</code> puis </li>
<li>accepter la valeurs par défaut qui correspondent au premier bloc disponible</li>
<li>accepter la valeurs par défaut qui correspondent au dernier bloc disponible ou alors <code>+10000M</code> afin de produire une image qui puisse fonctionner sur une petite cartes SD</li>
<li><code>N</code> pour "remove signature", </li>
<li>pour finir taper <code>w</code>. </li>
</ul>
</li>
</ul>
<p>puis :</p>
<div class="highlight"><pre><span></span>sudo resize2fs /dev/mmcblk0p2
</pre></div>
<h2><a name="head3.3"> </a> 3.3 Installation du réseau (seulement si au boot la raspberry ne le trouve pas)</h2>
<p>Suivant le mode de construction choisi poiur la raspberryPi (suivant la valeur des paramètres <code>ENABLE_ETH_DHCP</code>, <code>ENABLE_WIFI_DHCP</code> et de tous les paramètres dépendant de ces choix ; beaucoup de solutions sont possibles et respectent les choix de celui qui a construit l'image la solution la plus laxiste permettra à la raspi de se connecter via DHCP en filaire ou en WIFI; la solution la plus restrictive imposera une adresse IP filaire fixe et interdira toute connexion WIFI. Il serait fastidieux reprendre une à une toutes les combinaisons possibles, nous proposons ci-dessous une solution "radicale" permettant de reprendre la configuration à zéro. </p>
<p>Monter la micro-SD et accéder au dossier <code>/lib/systemd/network</code>, renommer tous les fichiers commençant par un nombre inférieur à 73 (s'il en existe).</p>
<div class="highlight"><pre><span></span>sudo mv <span class="m">10</span>-*****.network <span class="m">10</span>-*****.network-ORIG
</pre></div>
<p>Accéder au dossier <code>etc/systemd/</code> puis ajouter un dossier <code>network</code> puis un fichier <code>50-wired.network</code> avec le contenu ci-dessous :</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /media/username/partition/etc/systemd
sudo mkdir network
<span class="nb">cd</span> network
sudo su
cat > <span class="m">50</span>-wired.network
<span class="o">[</span>Match<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>enx*
<span class="nv">Host</span><span class="o">=</span>raspife3W
<span class="nv">Virtualization</span><span class="o">=</span>no
<span class="o">[</span>Network<span class="o">]</span>
<span class="nv">DHCP</span><span class="o">=</span>yes
<span class="o">[</span>DHCP<span class="o">]</span>
<span class="nv">RouteMetric</span><span class="o">=</span><span class="m">10</span>
<span class="nb">exit</span>
</pre></div>
<p>Dès que la raspberry sera connectée à un réseau filaire fournissant le service DHCP elle obtiendra une adresse et pourra se connecter au réseau et devenir ainsi accessible.</p>
<p>La suite des opérations peut se dérouler de deux façons :</p>
<ul>
<li>soit à partir de la RaspberryPi "bootée" avec la nouvelle image ce qui permer immédiatement de vérifier le caractère opérationnel de l'image mais implique une connexion filaire et un accès à distance vis <code>ssh</code></li>
<li>soit en modifiant directement le fichiers de configuration après avoir monté la micro-SD comme un disque dur</li>
</ul>
<p>La première solution est décrite ci-dessous.</p>
<h1><a name="head4"> </a> 4. Ajustements après le premier démarrage de la Raspberry munie de sa nouvelle image</h1>
<p>L'image fournie doit booter normalement et se connecter spontanément au réseau filaire, dans ce cas il est possible de réaliser toutes les installations sans écran ni clavier ni souris. Un réseau WIFI peut aussi être configuré par défaut afin de permettre une connexion wifi, si le réseau wifi n'est pas connu au moment de la création de l'image, il est nécessaire de connecter la <code>raspberryPi</code> à un clavier et à un écran pour configurer manuellement le wifi.</p>
<p>Pour obtenir l'adresse IP de la raspberry, si le réseau n'est pas trop étendu et ne contient pas trop de raspberries, on peut depuis l'ordinateur d'installation utiliser l'une des commande ci-desous :</p>
<ul>
<li>Si l'image utilisée a été configurée avec une IP fixe il va de soi qu c'est elle qui doit être utilisée</li>
<li>Si on dispose d'un accès à la configuration du DHCP il suffit de s'y connecter et de récupérer l'adresse de la Raspberry dans notre exemple son nom est raspife2, raspife3, raspife3P, raspwife3, raspife4 suivant la configuration choisie</li>
<li>Si on ne dipose que de l'accès standard au réseau on peut utiliser la commande <code>sudo nmap -sP -n ***.****.***.0/**</code> la valeur <code>***.****.***.0/**</code> représente le réseau sur lequel on se trouve, les valeurs peuvent être obtenues avec la commande <code>ip addr</code> ; si l'on dispose de l'adresse MAC de la Raspberry <code>**:**:**:**:**:**</code> on peut filtrer la commande ci-dessus avec l'adresse recherchée <code>sudo nmap -sP -n ***.****.***.0/** | grep -e **:**:**:**:**:** -B 2</code></li>
</ul>
<p>Une fois l'adresse obtenue se connecter via ssh ; <code>ssh ens-ife@***.****.***.***</code> (remplacer ens-ife par le nom de l'utilisateur initial choisi dans le fichier de confiuration initiale)</p>
<p>Lors de la première connexion la configuration de l'hôte peut s'avérer inadaptée, modifier le fichier <code>sudo jed /etc/host.conf</code> en commentant la ligne <code>spoof warn</code></p>
<div class="highlight"><pre><span></span><span class="c1">#spoof warn</span>
multi on
</pre></div>
<h2><a name="head4.1"> </a> 4.1. Modification de la taille de l'espace utilisé (au besoin seulement)</h2>
<p>Si cela n'a pas déjà été fait, ou si cela s'avère nécessaire (les images proposées ici font un peu moins de 16Go pour pouvoir être directement recopiées sur une SD d'au moins 16Go une partie de l'espace disque est occupées si on utilise une clef plus grosse), il est possible / souhaitable de redimensionner la partition racine sur la Raspberry Pi fonctionnant avec la nouvelle image. Pour cela <em><strong>une fois la Raspberry Pi opérationnelle et démarrée</strong></em>, se connecter en tant administrateur puis utiliser comme ci-dessus la commande :</p>
<div class="highlight"><pre><span></span>sudo fdisk /dev/mmcblk0
</pre></div>
<ul>
<li>Taper <code>m</code> pour voir la liste des commandes (juste pour information)</li>
<li>
<p>Taper <code>p</code> pour voir la liste des partitions disponibles, normalement il y en deux</p>
<ul>
<li>une FAT : /dev/mmcblk0p1 * 2048 133119 131072 64M c W95 FAT32 (LBA)</li>
<li>une linux : /dev/mmcblk0p2 133120 62517247 62384128 29,8G 83 Linux</li>
</ul>
</li>
<li>
<p>Taper ensuite </p>
<ul>
<li><code>d</code> puis </li>
<li><code>2</code> puis </li>
<li><code>n</code> puis </li>
<li><code>p</code> puis </li>
<li><code>2</code> puis </li>
<li>accepter les successivement les 2 valeurs par défaut qui correspondent à la taille effectivement disponible sur la cartes SD - <code>N</code> pour "remove signature", </li>
<li>pour finir taper <code>w</code>. </li>
</ul>
</li>
</ul>
<p>Redimensionner le système de fichiers puis rebooter pour que ce soit pris en compte :</p>
<div class="highlight"><pre><span></span>sudo resize2fs /dev/mmcblk0p2
sudo reboot
</pre></div>
<p>Après ce redémarrage la racine du système occupe maintenant la totalité de l'espace disponible sur la SD.</p>
<h2><a name="head4.2"> </a> 4.2 Mises à jour et installation d'utilitaires</h2>
<p>Suivant les choix du créateur de l'image les paquets non libres peuvent être présents ou absents, s'ils sont nécessaires et absents éditer le fichier <code>/etc/apt/sources.list</code> et ajouter à la fin de chaque ligne active <code>non-free</code>.</p>
<div class="highlight"><pre><span></span>sudo nano /etc/apt/sources.list
</pre></div>
<p>Il peut s'être écoulé suffisamment de temps entre la création de l'image et sa mise en oeuvre, certains paquets peuvent avoir évolué, certains paquets peuvent être incomplètement configurés et il est recommandé de faire une mise à jour. Pour cela mettre à jour la liste des paquets et mettre à jour ensuite les nouveaux paquets de la liste :</p>
<div class="highlight"><pre><span></span>sudo apt update
sudo apt upgrade
sudo apt dist-upgrade
sudo dpkg-reconfigure locales
sudo dpkg-reconfigure tzdata
</pre></div>
<p>Vérifier que tous les utilitaires et autres programmes ont été installés lors de la construction de l'image, utiliser la commande ci dessous. Pour tous les paquets renvoyant le message <code>dpkg-query: aucun paquet ne correspond à *****</code>, les installer avec la commande standard d'installation de la ligne suivante (tous les paquets sont reportés ici une partie seulement peut-être utilisée:</p>
<div class="highlight"><pre><span></span>dpkg -l dirmngr wpasupplicant php-fpm fcgiwrap libfcgi-dev php7.3-mysql ca-certificates-java icedtea-netx openjdk-1#-jdk openjdk-1#-jre openjdk-1#-jre-headless
sudo apt install jed dirmngr wpasupplicant php-fpm fcgiwrap libfcgi-dev php7.3-mysql ca-certificates-java icedtea-plugin icedtea-netx openjdk-1#-jdk openjdk-1#-jre openjdk-1#-jre-headless
</pre></div>
<p>Dans une installation <code>buster</code> ou <code>bullseye</code> les paquets openjdk-11 16 et 17 sont disponibles; à partir de la version 16 <code>JNI</code>disparait veiller aux compatibilités, # représente 1 6 ou 7 suivant les besoins de l'usager.</p>
<h2><a name="head4.3"> </a> 4.3 Ajout d'utilisateurs et gestion des droits</h2>
<p>Lors de la création un seul utilisateur par défaut a été créé <code>ens-ife</code>, dans notre projet cet utilisateur est l'administrateur de secours et nous proposons de créer :</p>
<ul>
<li>un administrateur principal <code>localadm</code>, </li>
<li>un utilisateur qui gèrera l'accès à la station météo <code>weewx</code></li>
<li>un utilisateur invité qui servira de test <code>moon</code> (ce login est utilisé en référence aux machines de développement ayant un utilisateur jupyter et un utilisateur callisto...)</li>
<li>un administrateur de l'nterface de programmation jupyterhub <code>callisto</code></li>
<li>un groupe pour les utilisateurs dubus <code>i2c</code></li>
<li>un groupe pour les utilisateurs du bus <code>GPIO</code></li>
<li>un groupe pour les utilisateurs du serveur <code>jupyter</code> en réseau</li>
</ul>
<p>Les groupes et les utilisateurs sont ajoutés avec les commande standard linux debian <code>addgroup</code> et <code>adduser</code></p>
<div class="highlight"><pre><span></span><span class="k">for</span> i in i2c gpio jupyterhub<span class="p">;</span> <span class="k">do</span> sudo addgroup <span class="nv">$i</span><span class="p">;</span> <span class="k">done</span>
<span class="k">for</span> i in localadm weewx moon callisto<span class="p">;</span> <span class="k">do</span> sudo adduser <span class="nv">$i</span><span class="p">;</span> <span class="k">done</span>
</pre></div>
<p>l'utilisateur <code>localadm</code> doit disposer des droits d'administration :</p>
<div class="highlight"><pre><span></span>sudo adduser localadm sudo
</pre></div>
<p>Les utilisateurs <code>ens-ife</code>, <code>localadm</code>, <code>callisto</code>et <code>moon</code> doivent pouvoir en outre utiliser les ressources matérielles de la raspberry on les affecte aux groupes nécessaires :</p>
<div class="highlight"><pre><span></span><span class="k">for</span> i in localadm moon ens-ife callisto<span class="p">;</span> <span class="k">do</span> <span class="k">for</span> j in i2c gpio netdev plugdev audio video<span class="p">;</span> <span class="k">do</span> sudo adduser <span class="nv">$i</span> <span class="nv">$j</span><span class="p">;</span> <span class="k">done</span><span class="p">;</span> <span class="k">done</span>
</pre></div>
<p>Pour améliorer la sécurité il est possible (souhaitable) de supprimer le login par mot de passe de callisto en lui procurant un login exclusif par clef ssh.</p>
<p>Les utilisateurrs <code>localadm</code>, <code>moon</code>, <code>ens-ife</code>, <code>callisto</code> doivent appartenir au groupe <code>jupyterhub</code> :</p>
<div class="highlight"><pre><span></span><span class="k">for</span> i in localadm moon ens-ife callisto<span class="p">;</span> <span class="k">do</span> sudo adduser <span class="nv">$i</span> jupyterhub<span class="p">;</span> <span class="k">done</span>
</pre></div>
<h2><a name="head4.4"> </a> 4.4 Configuration du réseau</h2>
<p>Le réseau est configuré en utilisant exclusivement les services <code>systemD</code>. les fichiers par défaut se trouvent dans <code>/lib/systemd//network</code>, les fichiers sont chargés dans l'odre de tri alphanuménumérique. Le système n'esplore pas d'autre fichiers dès que le premier fichier permettant une configuration avec succès est chargé. Nous utilisons un fichier de configuration commençant par 50, il faut donc qu'il n'y ait aucun fichier qui porte un nom d'ordre inférieur dans <code>/lib/systemd//network</code>.</p>
<h3><a name="head4.4.1"> </a> 4.4.1 Configuration de systemd-networkd</h3>
<p>Cette Raspberry est configurée pour prendre automatiquement le <strong>réseau filaire</strong> en prenant une adresse IP fixe car pour de raisons de sécurité elle est conçue pour être installée sur un sous-réseau isolé <strong>sans DHCP</strong> :</p>
<p>S'il n'existe pas on va d'abord créer un répertoire qui accueillera les fichiers modifiés de configuration du réseau :</p>
<div class="highlight"><pre><span></span>sudo mkdir /etc/systemd/network
</pre></div>
<p>Si le fichier <code>/etc/resolv.conf</code> n'existe pas ou s'il s'agit d'un fichier ordinaire ajouter le lien pour le resolver, <strong>Attention</strong> il est possible que le fichier <code>/run/systemd/resolve/resolv.conf</code> n'existe pas, il sera créé automatiquement au redémarrage du réseau dans la configuraton choisie :</p>
<div class="highlight"><pre><span></span>sudo rm /etc/resolv.conf
sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
</pre></div>
<p>Pour éviter d'avoir plusieurs interfaces réseau il est souhaitable de désactiver les interfaces par défaut du système dans le répertoire <code>/lib/systemd/network</code> :</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /lib/systemd/network
sudo mv <span class="m">10</span>-eth0.network <span class="m">10</span>-eth0.network-orig
sudo mv <span class="m">11</span>-wlan0.network <span class="m">11</span>-wlan0.network-orig
</pre></div>
<p>Vérifier aussi que le répertoire /etc/systemd contient un fichier de configuration <code>resolved.conf</code> et par précaution ajouter le DNS <code>Quad9</code> par défaut (on pourra l'enlever si la Raspberry parvient automatiquement à trouver le DNS du réseau).</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /etc/systemd/
sudo nano resolved.conf
<span class="c1"># This file is part of systemd.</span>
<span class="c1">#</span>
<span class="c1"># systemd is free software; you can redistribute it and/or modify it</span>
<span class="c1"># under the terms of the GNU Lesser General Public License as published by</span>
<span class="c1"># the Free Software Foundation; either version 2.1 of the License, or</span>
<span class="c1"># (at your option) any later version.</span>
<span class="c1">#</span>
<span class="c1"># Entries in this file show the compile time defaults.</span>
<span class="c1"># You can change settings by editing this file.</span>
<span class="c1"># Defaults can be restored by simply deleting this file.</span>
<span class="c1">#</span>
<span class="c1"># See resolved.conf(5) for details</span>
<span class="o">[</span>Resolve<span class="o">]</span>
<span class="c1">#DNS=</span>
<span class="c1">#FallbackDNS=</span>
<span class="c1">#Domains=</span>
<span class="c1">#LLMNR=yes</span>
<span class="c1">#MulticastDNS=yes</span>
<span class="c1">#DNSSEC=allow-downgrade</span>
<span class="c1">#DNSOverTLS=no</span>
<span class="c1">#Cache=yes</span>
<span class="c1">#DNSStubListener=yes</span>
<span class="c1">#ReadEtcHosts=yes</span>
</pre></div>
<p>On utilise le DNS <code>Quad9</code> pour des raisons de protection des données privées.</p>
<div class="highlight"><pre><span></span><span class="nv">DNS</span><span class="o">=</span><span class="m">9</span>.9.9.9
<span class="nv">FallbackDNS</span><span class="o">=</span><span class="m">9</span>.9.9.9
</pre></div>
<h4><a name="head4.4.1.1"> </a> 4.4.2 IP fixe présélectionnée</h4>
<p>Ajouter dans le répertoire ci-dessus le fichier <code>50-wired.network</code></p>
<div class="highlight"><pre><span></span>sudo nano /etc/systemd/network/50-wired.network
</pre></div>
<p>Fournir la configuration suivante dans laquelle <code>***.***.***.***</code> représente successivement les adresses du DNS, du réseau qui sera utilisé et de la passerelle. <code>enx*</code> est un contournement <strong>temporaire</strong> permettant de connecter <em>n'importe quelle interface</em> cette valeur devra être changée par la vraie valeur de l'interface dès qu'elle sera connue (voir plus bas) :</p>
<div class="highlight"><pre><span></span><span class="o">[</span>Match<span class="o">]</span>
<span class="nv">Name</span><span class="o">=</span>enx*
<span class="nv">Host</span><span class="o">=</span>raspife3W
<span class="nv">Virtualization</span><span class="o">=</span>no
<span class="o">[</span>Network<span class="o">]</span>
<span class="nv">RouteMetric</span><span class="o">=</span><span class="m">10</span>
<span class="nv">IPv6PrivacyExtensions</span><span class="o">=</span><span class="nb">true</span>
<span class="nv">DHCP</span><span class="o">=</span>no
<span class="nv">Address</span><span class="o">=</span>***.***.***.***/24
<span class="nv">Gateway</span><span class="o">=</span>***.***.***.***
<span class="nv">DNS</span><span class="o">=</span>***.***.***.***
<span class="nv">NTP</span><span class="o">=</span><span class="m">0</span>.pool.ntp.org
<span class="nv">NTP</span><span class="o">=</span><span class="m">2</span>.pool.ntp.org
</pre></div>
<p><strong>Attention</strong> en mettant enplace une telle configuration et en la diffusant il est impératif de réaliser que l'image proposée sera opérationnelle <strong>mais ne pourra pas se connecter au réseau via DHCP car il est désactivé</strong>. Il est donc impératif d'avoir configuré le réseau pour qu'il puisse accueillir la raspberryPi configurée pour l'adresse fixe choisie dans le fichier ci-dessus.</p>
<h4><a name="head4.4.1.2"> </a> 4.4.3 IP dynamique alternative fournie par un DHCP</h4>
<p>Une telle interface de secours peut être utile pour travailler sur un réseau local L'interface filaire porte le même nom que dans le cas précédentavec l'extension rescue pour éviter qu'elle soit activée, il suffit d'enlever ce suffixe pour qu'elle soit chargée.</p>
<div class="highlight"><pre><span></span>sudo nano /etc/systemd/network/51-wired.network-rescue
</pre></div>
<p><code>enx*</code> est un contournement <strong>temporaire</strong> permettant de connecter <em>n'importe quelle interface</em> cette valeur devra être changée par la vraie valeur de l'interface dès qu'elle sera connue (voir plus bas) :</p>
<div class="highlight"><pre><span></span><span class="o">[</span>Match<span class="o">]</span>
<span class="c1">#Name=enx*</span>
<span class="nv">Name</span><span class="o">=</span>
<span class="nv">Host</span><span class="o">=</span>raspife3W
<span class="o">[</span>Network<span class="o">]</span>
<span class="nv">DHCP</span><span class="o">=</span>yes
<span class="o">[</span>DHCP<span class="o">]</span>
<span class="nv">RouteMetric</span><span class="o">=</span><span class="m">10</span>
</pre></div>
<h2><a name="head4.5"> </a> 4.5 Modification des accès au <code>GPIO</code> et à la caméra</h2>
<p>Les accès au bus <code>GPIO</code> de la raspberry sont privilégiés c'est pourquoi nous avons créé un groupe <code>gpio</code> auquel nous allons octroyer des droits supplémentaires pour que les usagers de ce groupe puissent accéder au bus.</p>
<p>Pour un fonctionnement sécurisé permettant l'accès de plusieurs utilisteurs au bus <code>GPIO</code>sans privilèges particuliers il est nécessaire d'opérer des modifications donnant à un utilisateur ordinaire membre du groupe <code>gpio</code>le droit d'accéder aux ressources connectées au bus <code>GPIO</code>. On rajoute le fichier <code>50-gpio.rules</code> au répertoire <code>/etc/udev/rules.d</code> avec la commande ci-dessous et on ajoute le contenu suivant (on termine avec Ctrl-D):</p>
<div class="highlight"><pre><span></span>sudo su
cat > /etc/udev/rules.d/50-gpio.rules
</pre></div>
<div class="highlight"><pre><span></span><span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"gpio*"</span>, <span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c 'chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio; \</span>
<span class="s2">chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio; \</span>
<span class="s2">chown -R root:gpio /sys/devices/platform/soc/3f200000.gpio && chmod -R 770 /sys/devices/platform/soc/3f200000.gpio; \</span>
<span class="s2">chown -R root:gpio /sys/devices/platform/soc/soc:virtgpio && chmod -R 770 /sys/devices/platform/soc/soc:virtgpio; \</span>
<span class="s2">chown -R root:gpio /sys/bus/platform/drivers/pinctrl-bcm2835 && chmod -R 770 /sys/bus/platform/drivers/pinctrl-bcm2835 '"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"bcm2835-gpiomem"</span>, <span class="nv">KERNEL</span><span class="o">==</span><span class="s2">"gpiomem"</span>, <span class="nv">GROUP</span><span class="o">=</span><span class="s2">"gpio"</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">"0660"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"gpio"</span>, <span class="nv">KERNEL</span><span class="o">==</span><span class="s2">"gpiochip*"</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">"add"</span>, <span class="se">\</span>
<span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c 'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport ; \</span>
<span class="s2">chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"gpio"</span>, <span class="nv">KERNEL</span><span class="o">==</span><span class="s2">"gpio*"</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">"add"</span>, <span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c \</span>
<span class="s2">'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; \</span>
<span class="s2">chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'"</span>
</pre></div>
<p>Pour l'urtilisation du <code>SPI</code> Le fichier <code>50-gpio.rules</code> prend la forme :</p>
<div class="highlight"><pre><span></span><span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"gpio*"</span>, <span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c 'chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio; \</span>
<span class="s2">chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio; \</span>
<span class="s2">chown -R root:gpio /sys/devices/platform/soc/fe200000.gpio && chmod -R 770 /sys/devices/platform/soc/fe200000.gpio; \</span>
<span class="s2">chown -R root:gpio /sys/devices/platform/soc/soc:virtgpio && chmod -R 770 /sys/devices/platform/soc/soc:virtgpio; \</span>
<span class="s2">chown -R root:gpio /sys/bus/platform/drivers/pinctrl-bcm2835 && chmod -R 770 /sys/bus/platform/drivers/pinctrl-bcm2835 '"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"spidev*"</span>, <span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c 'chown -R root:gpio /sys/class/spidev && chmod -R 770 /sys/class/spidev; \</span>
<span class="s2">chown -R root:gpio /sys/devices/platform/soc/fe204000.spi/spi_master/spi0/spi0.0/spidev && \</span>
<span class="s2">chmod -R 770 /sys/devices/platform/soc/fe204000.spi/spi_master/spi0/spi0.0/spidev; \</span>
<span class="s2">chown -R root:gpio /dev/spidev0.0 && chmod -R 770 /dev/spidev0.0'"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"bcm2835-gpiomem"</span>, <span class="nv">KERNEL</span><span class="o">==</span><span class="s2">"gpiomem"</span>, <span class="nv">GROUP</span><span class="o">=</span><span class="s2">"gpio"</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">"0660"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"gpio"</span>, <span class="nv">KERNEL</span><span class="o">==</span><span class="s2">"gpiochip*"</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">"add"</span>, <span class="se">\</span>
<span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c 'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport ; \</span>
<span class="s2">chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'"</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"gpio"</span>, <span class="nv">KERNEL</span><span class="o">==</span><span class="s2">"gpio*"</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">"add"</span>, <span class="nv">PROGRAM</span><span class="o">=</span><span class="s2">"/bin/sh -c \</span>
<span class="s2">'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; \</span>
<span class="s2">chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'"</span>
</pre></div>
<p>on modifie aussi la ligne de commande dans <code>/boot/cmdline.txt</code> en ajoutant en fin de ligne <code>spidev.bufsiz=32768</code> et enfin on ajoute l'activation du bus <code>SPI</code> et le contrôle de la fréquence dans le fichier <code>/boot/config.txt</code> pour contrôler un rubande leds librairie <code>rpi_ws281x</code></p>
<div class="highlight"><pre><span></span><span class="nv">dtparam</span><span class="o">=</span><span class="nv">spi</span><span class="o">=</span>on <span class="c1"># activation du bus SPI</span>
<span class="c1"># to use SPI for ledstrip</span>
<span class="nv">core_freq_min</span><span class="o">=</span><span class="m">500</span> <span class="c1"># pour la raspi4</span>
<span class="c1"># core_freq=250 # pour la pi3</span>
</pre></div>
<p><strong>Attention aux conflits en activant le bus SPI</strong></p>
<p>Tout comme le GPIO l'USB n'est pas accessible aux utilisateurs de base , l'utilsateur <code>weewx</code> est un utilisateur non privilégié qui doit pouvoir accéder à la station via une interface USB on ajoute au même endroit le fichier <code>40-usbweewx.rules</code> avec la commande </p>
<div class="highlight"><pre><span></span>cat > /etc/udev/rules.d/40-usbweewx.rules
</pre></div>
<p>on ajoute le contenu suivant :</p>
<div class="highlight"><pre><span></span><span class="c1"># make any te923 station connected via usb accessible to non-root</span>
<span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"usb"</span>, ATTR<span class="o">{</span>idVendor<span class="o">}==</span><span class="s2">"1130"</span>, ATTR<span class="o">{</span>idProduct<span class="o">}==</span><span class="s2">"6801"</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">"add"</span>, <span class="nv">GROUP</span><span class="o">=</span><span class="s2">"weewx"</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">"0664"</span>
<span class="c1"># make any Vantage Pro2 station connected via usb accessible to non-root</span>
<span class="c1">#SUBSYSTEM=="usb", ATTR{idVendor}=="10c4", ATTR{idProduct}=="ea60", ACTION=="add", GROUP="weewx", MODE="0664"</span>
</pre></div>
<p>Lorsque la caméra est connectée, son accès est réservé par défaut à l'administrateur il est nécessaire d'ajouter un fichier de configuration supplémentaire <code>60-cam.rules</code> au répertoire <code>/etc/udev/rules.d</code> avec la commnde <code>sudo nano ./etc/udev/rules.d/60-cam.rules</code> et on ajoute le contenu suivant :</p>
<div class="highlight"><pre><span></span>cat > /etc/udev/rules.d/60-cam.rules
</pre></div>
<div class="highlight"><pre><span></span><span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"vchiq"</span>, <span class="nv">GROUP</span><span class="o">==</span><span class="s2">"video"</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">"0660"</span>
</pre></div>
<p>Dès que la caméra sera détectée (voir plus loin) tous les membres du groupe <code>video</code> pourront l'utiliser.</p>
<h1><a name="head5"> </a> 5. Utilisation de la Raspberrry en point d'accès web (Hotspot)</h1>
<p>Les images proposées permettent d'utiliser la Raspberry Pi au sein d'un réseau existant, il est aussi possible de la transformer en point d'accès sur un WIFI qu'elle crée et administre avec ou pas des fonctions de passerelle vers internet. Ce sujet est abordé dans un <a href="http://blog.climatetmeteo.fr/GerardVidal/hotspotraspi23.html#head1">autre article de ce blog</a>. Attention mettre en oeuvre cette configuration perturbe les règles de sécurité énoncées ici, veillez à bien configurer votre réseau en fonction de vos besoins et contraintes.</p>
<h1><a name="head6"> </a> 6. Configurations particulières avancées</h1>
<p>Certains modules requièrent beaucoup de RAM pour se compiler avec l'option -j4 du make la raspberryPi3 peut se figer, on passe alors avec l'option -j2 (qui utilise seulement 2 des coeurs du processeur). Il est possible d'ajouter un fichier de swap avec les commandes suivantes qui fournissent 512 Mo de swap, la compilation passe en -j4 mais la raspi3 swape choisissez l'option qui vous convient !</p>
<div class="highlight"><pre><span></span>sudo su
dd <span class="k">if</span><span class="o">=</span>/dev/zero <span class="nv">of</span><span class="o">=</span>/swapfile <span class="nv">bs</span><span class="o">=</span><span class="m">1024</span> <span class="nv">count</span><span class="o">=</span><span class="m">524288</span>
chown root:root /swapfile
chmod <span class="m">0600</span> /swapfile
mkswap /swapfile
swapon /swapfile
</pre></div>
<p>Pour vérifier l'activité :</p>
<div class="highlight"><pre><span></span>swapon -s
free -m
</pre></div>
<p>Le logiciel de pilotage des stations météo <code>weewx</code> a été préinstallé, nous verrons plus loin comment affinner sa configuration mais il est inutile de laisser le daemon actif pendant la configuration. </p>
<div class="highlight"><pre><span></span>sudo systemctl stop weewx
sudo systemctl disable weewx
</pre></div>
<h2><a name="head6.1"> </a> 6.1 Ajouts permettant entre autres l'apprentissage de la programmation</h2>
<h3><a name="head6.1.1"> </a> 6.1.1 Compilation d'un cmake récent</h3>
<p>Dans les versions stables de <code>debian</code> la version de <code>cmake</code> peut s'avérer en retard si c'est le cas compiler depuis les sources sinon installer le paquet standard. Attention les compilations peuvent s'avérer extrêmement longues sur les petits modèles de raspis (Pi0 Pi1 notamment). </p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/Cmake
<span class="nb">cd</span> Logiciels/Cmake
wget https://github.com/Kitware/CMake/releases/download/v3.20.3/cmake-3.20.3.tar.gz
tar xvfz cmake-3.20.3.tar.gz
<span class="nb">cd</span> cmake-3.20.3
./bootstrap <span class="o">&&</span> make -j4
sudo make install
</pre></div>
<h3><a name="head6.1.2"> </a> 6.1.2 Ajout de fontes</h3>
<p>Vérifier s'il ne manque pas des fontes, si oui les installer.</p>
<div class="highlight"><pre><span></span>sudo dpkg -l fonts-liberation gsfonts libxfont-dev libfontenc-dev ttf-mscorefonts-installer xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable xfonts-utils
sudo apt install fonts-liberation gsfonts libxfont-dev libfontenc-dev ttf-mscorefonts-installer xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable xfonts-utils
</pre></div>
<h3><a name="head6.1.3"> </a> 6.1.3 Activation de la caméra raspberry Pi</h3>
<p>L'activation de la caméra se passe en deux étapes car par défaut la détection de la caméra n'est pas activée, cette situation est probablement due à la volonté de ne pas "gaspiller les ressources limitées de la Raspberry. Dans cette optique il est conseillé de n'activer la caméra qu'uniquement quand on va l'utiliser car contrairement à d'autres fonctionnalités celle ci immobilise des ressources.</p>
<h4><a name="head6.1.3.1"> </a> 6.1.3.1 Détection de la caméra</h4>
<p>Pour détecter la camera il est nécesaire de modifier la configuration du fichier de boot avec la commande <code>sudo nano /boot/firmware/config.txt</code> la fin du fichier est recopiée ci-dessous. </p>
<div class="highlight"><pre><span></span><span class="nv">gpu_mem</span><span class="o">=</span><span class="m">16</span>
initramfs initramfs-4.13.16-v7 followkernel
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">i2c_arm</span><span class="o">=</span>on
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">spi</span><span class="o">=</span>on
</pre></div>
<p>La modifier pour lui donner l'aspect suivant</p>
<div class="highlight"><pre><span></span>initramfs initramfs-4.13.16-v7 followkernel
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">i2c_arm</span><span class="o">=</span>on
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">spi</span><span class="o">=</span>on
<span class="nv">gpu_mem</span><span class="o">=</span><span class="m">16</span> <span class="c1"># Comment this line when activating the camera to provide more memory</span>
<span class="c1"># camera activation</span>
<span class="c1"># To activate camera at least uncomment the two following lines</span>
<span class="c1"># AND comment the line above gpu_mem=16</span>
<span class="c1">#</span>
<span class="c1">#start_x=1 # essential</span>
<span class="c1">#gpu_mem=128 # at least, or maybe more if you wish</span>
<span class="c1">#</span>
</pre></div>
<p>Pour activer la camera il faut commenter la ligne <code>gpu_mem=16</code> et décommenter les deux lignes <code>start_x=1</code> et <code>gpu_mem=128</code> puis impérativement <strong>rebooter</strong>. Une fois le reboot effectué si la caméra est connectée elle apparait aux côtés des autres périphériques sous le nom <code>/dev/vchiq</code></p>
<h4><a name="head6.1.3.2"> </a> 6.1.3.2 Ajout des logiciels de pilotage de la caméra</h4>
<p>La caméra et le module de pilotage ne sont hélas pas des modules standard de la distribution Debian et il est hélas nécessaire de les compiler. La manipulation a effectuer est détaillée ci-dessous :</p>
<p>Créer un répertoire d'accueil des programmes puis se positionner dans ce dossier. Télécharger les outils de compilation croisée puis les sources des librairies qui seront utilisées.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/Cam
<span class="nb">cd</span> !$
git clone https://github.com/raspberrypi/userland.git
</pre></div>
<p>se déplacer dans le dossier userland reçu et taper la commande <code>./buildme</code> qui lance la création des logiciels nécesaires à la mise en oeuvre de la caméra.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> userland
./buildme
</pre></div>
<p>L'exécution devrait se passer sans encombre et tous les outils nécessaires sont stockés dans le dossier <code>/opt/vc</code>. Pour que les programmes trouvent ces librairies il est nécessaire de rajouter un fichier dans le répertoire listant les librairies utilisées avec la commande <code>sudo nano /etc/ld.so.conf.d/userland.conf</code> en ajoutant dans le fichier :</p>
<div class="highlight"><pre><span></span><span class="c1">#Access to Userland libraries</span>
/opt/vc/lib
</pre></div>
<p>Appliquer la transformation avec <code>sudo ldconfig</code></p>
<p>Recopier ensuite le contenu des docciers de <code>/opt/vc</code> hormis <code>lib</code> et <code>src</code> dans <code>/usr/local</code> :</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> build
<span class="k">for</span> i in bin include <span class="o">[</span>sbin<span class="o">]</span> <span class="o">[</span>share<span class="o">]</span><span class="p">;</span> <span class="k">do</span> sudo cp -r /opt/vc/<span class="nv">$i</span>/* /usr/local/<span class="nv">$i</span><span class="p">;</span> <span class="k">done</span>
</pre></div>
<p>Pour utiliser la caméra avec un utilisateur <code>non root</code> et si cela n'a pas été fait dans la phase initiale ne pas oublier d'ajouter dans <code>/etc/udev/rules.d</code> le fichier <code>60-cam.rules</code> avec la commande <code>sudo nano /etc/udev/rules.d/60-cam.rules</code> avec le contenu suivant :</p>
<div class="highlight"><pre><span></span><span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">"vchiq"</span>, <span class="nv">GROUP</span><span class="o">==</span><span class="s2">"video"</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">"0660"</span>
</pre></div>
<p>À chaque démarrage le groupe <code>video</code> sera autorisé à acccéder à la resource <code>/dev/vchiq</code> ; cela peut être fait manuellement pour cela en cas de besoin exécuter les deux commandes suivantes :</p>
<div class="highlight"><pre><span></span>sudo chown root.video /dev/vchiq
sudo chmod g+rw !$
</pre></div>
<p>Les outils de lafamille <code>raspi</code> sont installés via <code>tools.git</code> en cas de besoin mais non utiles et non déployés dans ce tutoriel, attention le déploiement de ces outils occupe une place importante.</p>
<div class="highlight"><pre><span></span>git clone https://github.com/raspberrypi/tools.git
</pre></div>
<h3><a name="head6.1.4"> </a> 6.1.4 Reconfiguration du réseau filaire</h3>
<p>Comme nous l'avons vu plus haut l'interface réseau filaire est configurée de façon générique pour se connecter à un réseau particulier sur ue adresse précise. Cette connexion est suffisante pour réaliser toutes les configurations proposées dans ce document. La mise en place d'une configuration avancée adaptée à une interface particulière et un réseau particulier "fige" la situation et la Raspberry ne peut pas se connecter à un autre réseau autrement qu'en utilisant la configuration de secours <code>51-wired.conf</code>. </p>
<p>Si l'image en cours de création est destinée à être partagée avec d'autres usagers qui la cloneront il est recommandé de <strong>ne pas configurer le réseau</strong> comme expliqué ci-dessous, ce devra être fait par l'utilisateur final avec ses paramètres personnels. Si l'image en cours de création est destinée à être directement utilisée <strong>la configuration ci-dessous doit être effectuée</strong></p>
<p>Pour configurer le réseau filaire il faut supprimer la désignation générique de l'interface et la remplacer par la valeur construite au boot à partir de l'adresse Mac (cette valeur est unique et désigne une et une seule Raspberry Pi "physique" l'image sera donc inadaptée à toute autre Raspberry Pi !). On obtient le nom de l'interface réseau par la commande <code>ip token</code>.</p>
<p>Si la valeur est <code>eth0</code> c'est que la version antérieure de la configuration a été utilisée et dans ce cas le nom est de l'interface est unique et toujours le même aucune manipulation ne doit être effectuée.</p>
<p>Si la valeur diffère de <code>eth0</code> elle doit être substituée à la valeur générique <code>enx*</code> figurant dans le fichier <code>50-wired.network</code>.</p>
<div class="highlight"><pre><span></span><span class="nv">Name</span><span class="o">=</span>enx#########
<span class="nv">Host</span><span class="o">=</span>raspife3
</pre></div>
<p>On passe aussi en <code>systemd</code>en arrêtant le daemon <code>networking</code> et en veillant à ce que les deux daemons <code>systemd-networkd</code> et <code>systemd-resolved</code> soient lancés au boot. si ce n'est pas le cas effectuer la modificatio :</p>
<div class="highlight"><pre><span></span>sudo systemctl stop networking
sudo systemctl disable networking
sudo systemctl restart systemd-networkd
sudo systemctl restart systemd-resolved
sudo apt purge ifupdown
sudo systemctl list-unit-files <span class="p">|</span> grep enabled <span class="p">|</span> grep systemd-
</pre></div>
<p>Si besoin</p>
<div class="highlight"><pre><span></span>sudo systemctl <span class="nb">enable</span> systemd-networkd
sudo systemctl <span class="nb">enable</span> systemd-resolved
</pre></div>
<p>redémarrer pour vérifier la configuration réseau</p>
<div class="highlight"><pre><span></span>sudo systemctl reboot
</pre></div>
<h2><a name="head6.2"> </a> 6.2 Mise à jour des librairies upm et mraa depuis <code>github</code></h2>
<p>Les forges libres proposent de nombreux logiciels qui peuvent facilement être ajoutés à la Raspberry Pi, même s'il faut les compiler. La manipulation n'est pas compliquée et requiert des connaissances peu avancées à titre d'exemple nous installerons sur notre image les logiciels <code>mraa</code> et <code>upm</code> initiés par <code>intel</code> et repris par <code>eclipse</code> sur <code>github</code>. Le premier donne accès à la maîtrise du bus <code>GPIO</code> (et des pilotages via <code>UART</code>, <code>I2C</code>, <code>SPI</code>);le second propose plusieurs centaines de "drivers" pour des leds, des capteurs et des effecteurs du monde des "makers". C'est l'équivalent de ce que les utilisateurs des arduino appellent des "librairies" sauf que dans le cas de la Raspberry que nous construisons nous allons réellement construire des librairies au sens programmatique du terme dont les composants pourront être appelés depuis les langages <code>C</code>, <code>C++</code>, <code>python</code>, <code>Java</code>, <code>Node-JS</code>. Cela permettra d'écrire des programmes simples permettant d'interagir avec des capteurs météo des leds ou tous autres composants électroniques connectables. (voir nos <a href="https://depot.tremplin.ens-lyon.fr/Tremplin-des-Sciences/CahiersDeProgrammesCodage/files/tip/">cahiers de programmes pour jupyter</a>.</p>
<p>La première étape consiste à créer un espace pour stocker les codes puis de les télécharger dans cet espace depuis les forges opensource ou libres. Nous allons créer une hierarchie de dossiers dans le dodssier <code>Logiciels</code> ayant pour racine <code>IoT</code> (Internet of Things) contenant un dossier <code>mraa</code> et un dossier <code>upm</code>. </p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/IoT
<span class="nb">cd</span> !$
<span class="c1">#git clone https://github.com/eclipse/mraa</span>
<span class="c1">#git clone https://github.com/eclipse/upm</span>
git clone -b cleanup_V8_MAJOR_VERSION --single-branch https://github.com/nxhack/mraa.git
git clone -b cleanup_V8_MAJOR_VERSION --single-branch https://github.com/nxhack/upm.git
</pre></div>
<p>Avant de pouvoir créer ces deux librairies de programmes il est nécessaire de construire des éléments sur lesquels <code>mraa</code> et <code>upm</code> dépendent.</p>
<h3><a name="head6.2.1"> </a> 6.2.1 Récupération et installation de Node.js</h3>
<p><strong>ATTENTION en ce moment 2021-06 la compilation croisée de mraa et upm avec nodejs et swig ne fonctionne.</strong></p>
<p>Ce logicielévolue très rapidement et il est souhaitable de vérifier s'il n'existe pas une nouvelle version depuis l'écriture de ce blog, vérifier la version à jour sur le site <a href="https://nodejs.org">Node.js</a> nous utiliserons ici la version 16.2.0 avec npm7.15.0). créer le dossier pour accueillir le logiciel et le télécharger.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/Node
<span class="nb">cd</span> !$
wget https://nodejs.org/dist/v16.2.0/node-v16.2.0-linux-armv7l.tar.xz
tar xvfJ node-v16.2.0-linux-armv7l.tar.xz
<span class="nb">cd</span> node-v16.2.0-linux-armv7l
<span class="k">for</span> i in bin include lib share<span class="p">;</span> <span class="k">do</span> sudo cp -r <span class="nv">$i</span>/* /usr/local/<span class="nv">$i</span><span class="p">;</span> <span class="k">done</span>
sudo ln -s /usr/local/bin/node /usr/local/bin/nodejs
sudo npm install -g --upgrade npm node-gyp configurable-http-proxy
</pre></div>
<p>Pour gérer plusieurs versions de node installer <code>nvm</code></p>
<div class="highlight"><pre><span></span>wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh <span class="p">|</span> bash
</pre></div>
<h3><a name="head6.2.2"> </a> 6.2.2 Récupération et construction du paquet swig</h3>
<p>L'outil swig est complexe et évolue systématiquement <strong>après</strong> les évolutions des langages qu'il permet de traduire. <code>nodeJS</code> évolue rapidement et fréquemment et swig n'est pas toujours compatible avc la dernière version. Le tableau ci-dessous présente les combinaisons qui ont été testées opérationnellement. les tests ne sont pas exhaustifs et il peut subsister quelques incompatibilités. Merci de nous les signaler.</p>
<table>
<thead>
<tr>
<th align="center">version de node</th>
<th align="center">version de swig</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center">10.16.3</td>
<td align="center">4.0.1</td>
</tr>
<tr>
<td align="center">10.19.0</td>
<td align="center">4.0.2</td>
</tr>
<tr>
<td align="center">15.0.1</td>
<td align="center">4.1.0</td>
</tr>
<tr>
<td align="center">16.2.0</td>
<td align="center">4.1.0</td>
</tr>
<tr>
<td align="center">Pour gérer plusieurs versions de node installer <code>nvm</code></td>
<td align="center"></td>
</tr>
</tbody>
</table>
<p>Il est possible que le paquet automake n'ait pas installé et il est souhaitable (01-06-2021) d'ajouter le patch suivant lors de la construction de swig.</p>
<div class="highlight"><pre><span></span>sudo apt install automake
<span class="nb">cd</span>
mkdir -p Logiciels/Swig
<span class="nb">cd</span> !$
git clone -b master --single-branch https://github.com/swig/swig.git
<span class="c1"># git clone -b cleanup_V8_MAJOR_VERSION --single-branch https://github.com/nxhack/swig.git</span>
<span class="nb">cd</span> swig
./autogen.sh
./configure --enable-cpp11-testing
</pre></div>
<p>SI les choses se passent normalement on obtient le message :</p>
<div class="highlight"><pre><span></span>The SWIG test-suite and examples are configured <span class="k">for</span> the following languages:
java javascript perl5 python
</pre></div>
<p>poursuivre avec :</p>
<div class="highlight"><pre><span></span>make -j4
sudo make install
dpkg -l libjavascriptcoregtk*
sudo apt install libjavascriptcoregtk-4.0-dev
sudo ln -s /usr/include/webkitgtk-4.0/JavaScriptCore /usr/include/JavaScriptCore
</pre></div>
<h4><a name="head6.2.3"> </a> 6.2.3 Récupération et construction du paquet libopenzwave</h4>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/OpenZwave
<span class="nb">cd</span> !$
git clone https://github.com/OpenZWave/open-zwave.git
<span class="nb">cd</span> open-zwave
make -j4
sudo make install
</pre></div>
<h4><a name="head6.2.4"> </a> 6.2.4 Récupération et construction du paquet modbus</h4>
<div class="highlight"><pre><span></span>sudo apt install libtool
<span class="nb">cd</span>
mkdir -p Logiciels/Modbus
<span class="nb">cd</span> !$
git clone https://github.com/stephane/libmodbus.git
<span class="nb">cd</span> libmodbus/
./autogen.sh
./configure
make -j4
sudo make install
</pre></div>
<p>En cas de problème utiliser avant <code>./configure</code>.</p>
<div class="highlight"><pre><span></span>libtoolize
aclocal
autoheader
autoconf
automake --add-missing
</pre></div>
<h4><a name="head6.2.5"> </a> 6.2.5 Récupération et construction du paquet tinyb</h4>
<div class="highlight"><pre><span></span>dpkg -l libglib2
<span class="c1"># si manquante</span>
sudo apt install libglib2.0-dev
<span class="nb">cd</span> ~/Logiciels
mkdir Tinyb
<span class="nb">cd</span> Tinyb
git clone https://github.com/intel-iot-devkit/tinyb.git
<span class="nb">cd</span> tinyb/
mkdir build
<span class="nb">cd</span> build/
cmake -DCMAKE_INSTALL_PREFIX<span class="o">=</span>/usr ..
make -j4
sudo make install
</pre></div>
<h4><a name="head6.2.6"> </a> 6.2.6 Construction de mraa et upm</h4>
<p>Il est maintenant possible de construire les libraries mraa et upm qui permettent de <a href="https://iotdk.intel.com/docs/master/mraa/annotated.html">gérer le bus <code>GPIO</code></a> et un <a href="https://iotdk.intel.com/docs/master/upm/annotated.html">grand nombre de dispositifs électroniques</a></p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> ~/Logiciels/IoT/mraa
</pre></div>
<p>Ajuster les politiques de <code>cmake</code>puis vérifier qu'on ne compile pas l'interface <code>nodejs</code> (il y a des bugs avec <code>swig</code>) et ajouter la compilation de l'interface <code>java</code>. Modifier le fichier <code>CMakeLists</code> comme indiqué ci-dessous :</p>
<div class="highlight"><pre><span></span><span class="k">if</span> <span class="o">(</span>CMAKE_VERSION VERSION_LESS <span class="s2">"3.1"</span><span class="o">)</span>
<span class="k">if</span> <span class="o">(</span>CMAKE_C_COMPILER_ID STREQUAL <span class="s2">"GNU"</span><span class="o">)</span>
<span class="nb">set</span> <span class="o">(</span>CMAKE_C_FLAGS <span class="s2">"-std=gnu99 </span><span class="si">${</span><span class="nv">CMAKE_C_FLAGS</span><span class="si">}</span><span class="s2">"</span><span class="o">)</span>
endif <span class="o">()</span>
<span class="k">else</span> <span class="o">()</span>
<span class="nb">set</span> <span class="o">(</span>CMAKE_C_STANDARD <span class="m">99</span><span class="o">)</span>
cmake_policy<span class="o">(</span>SET CMP0078 OLD<span class="o">)</span>
cmake_policy<span class="o">(</span>SET CMP0086 NEW<span class="o">)</span>
endif <span class="o">()</span>
.../...
option <span class="o">(</span>BUILDSWIGNODE <span class="s2">"Build swig node modules."</span> ON<span class="o">)</span>
option <span class="o">(</span>BUILDSWIGJAVA <span class="s2">"Build Java API."</span> ON<span class="o">)</span>
</pre></div>
<p>Au 07/06:2021 le patch de <code>@nxhack</code> pour <code>swig</code> et <code>javascript</code> n'a pas encore été intégréà la branche principale il faut l'ajouter avant de compiler</p>
<div class="highlight"><pre><span></span>wget https://patch-diff.githubusercontent.com/raw/eclipse/mraa/pull/1064.patch
patch -p1 < <span class="m">1064</span>.patch
mkdir build
<span class="nb">cd</span> build
<span class="nb">export</span> <span class="nv">JAVA_HOME</span><span class="o">=</span>/usr/lib/jvm/java-17-openjdk-armhf/
<span class="c1"># cmake -Wno-dev -DCMAKE_INSTALL_PREFIX=/usr ..</span>
cmake .. -Wno-dev -DCMAKE_INSTALL_PREFIX<span class="o">=</span>/usr -DENABLEEXAMPLES<span class="o">=</span><span class="m">0</span> -DBUILDSWIGNODE<span class="o">=</span>ON -DSWIG_EXECUTABLE<span class="o">=</span>/usr/local/bin/swig -DV8_ROOT_DIR<span class="o">=</span>/usr/local/include/node -DNODE_ROOT_DIR<span class="o">=</span>/usr/local/include/node -DPYTHON2LIBS_FOUND<span class="o">=</span>FALSE -DPYTHON2INTERP_FOUND<span class="o">=</span>FALSE
</pre></div>
<p>Pour une compilation avec buster au 2020-11-11 il est nécessaire d'appliquer les patches suivants, le premier permet de contourner les problèmes de version V8, le second celui des problèmes de version :</p>
<div class="highlight"><pre><span></span><span class="gd">--- include/version.h 2020-11-10 19:47:03.734243366 +0100</span>
<span class="gi">+++ include/version.h 2020-11-11 10:43:19.870180059 +0100</span>
<span class="gu">@@ -11,8 +11,8 @@</span>
extern "C" {
#endif
<span class="gd">-const char* gVERSION;</span>
<span class="gd">-const char* gVERSION_SHORT;</span>
<span class="gi">+extern const char* gVERSION;</span>
<span class="gi">+extern const char* gVERSION_SHORT;</span>
#ifdef __cplusplus
}
</pre></div>
<p>Poursuivre la compilation :</p>
<div class="highlight"><pre><span></span>make -j4
sudo make install
</pre></div>
<p>En cas de besoin il est possible d'effacer ce qui a été installé par les compilations précédentes.</p>
<div class="highlight"><pre><span></span>sudo rm -r /usr/include/mraa* /usr/lib/arm-linux-gnueabihf/pkgconfig/mraa.pc /usr/lib/arm-linux-gnueabihf/libmraa* /usr/lib/python2.7/dist-packages/*mraa* /usr/lib/python3.7/dist-packages/*mraa* /usr/lib/node_modules/mraa /usr/share/mraa/examples /usr/bin/mraa*
sudo rm -r /usr/include/upm /usr/lib/python2.7/dist-packages/upm /usr/lib/python3.7/dist-packages/upm /usr/lib/arm-linux-gnueabihf/pkgconfig/upm* /usr/lib/node_modules/jsupm* /usr/lib/arm-linux-gnueabihf/libupm* /usr/share/upm
</pre></div>
<div class="highlight"><pre><span></span><span class="nb">cd</span> ~/Logiciels/IoT/upm
</pre></div>
<p>Supprimer la compilation de l'interface <code>nodeJS</code> ajouter la compilation de l'interface <code>java</code>.
Modifier le fichier <code>CMakeLists</code> comme indiqué ci-dessous :</p>
<div class="highlight"><pre><span></span>option <span class="o">(</span>BUILDSWIGNODE <span class="s2">"Build swig node modules."</span> ON<span class="o">)</span>
option <span class="o">(</span>BUILDSWIGJAVA <span class="s2">"Build Java API."</span> ON<span class="o">)</span>
option <span class="o">(</span>WERROR <span class="s2">"Make all warnings into errors."</span> OFF<span class="o">)</span>
</pre></div>
<p>Continuer la compilation.</p>
<div class="highlight"><pre><span></span>wget https://patch-diff.githubusercontent.com/raw/eclipse/upm/pull/703.patch
patch -p1 < <span class="m">703</span>.patch
mkdir build
<span class="nb">cd</span> build
<span class="c1">#cmake -Wno-dev -DWERROR=off -DCMAKE_INSTALL_PREFIX=/usr ..</span>
cmake .. -Wno-dev -DCMAKE_INSTALL_PREFIX<span class="o">=</span>/usr -DENABLEEXAMPLES<span class="o">=</span><span class="m">0</span> -DBUILDSWIGNODE<span class="o">=</span>ON -DSWIG_EXECUTABLE<span class="o">=</span>/usr/local/bin/swig -DV8_ROOT_DIR<span class="o">=</span>/usr/local/include/node -DNODE_ROOT_DIR<span class="o">=</span>/usr/local/include/node -DPYTHON2LIBS_FOUND<span class="o">=</span>FALSE -DPYTHON2INTERP_FOUND<span class="o">=</span>FALSE -DWERROR<span class="o">=</span>OFF -DCMAKE_CXX_STANDARD<span class="o">=</span><span class="m">17</span>
make -j4
sudo make install
</pre></div>
<p>Dans certaines situations(maintenant peut-être révolues) il a été nécessaire de recopier les modules python depuis <code>build/src/*/python?.?/*.py</code> vers <code>/usr/lib/dist-packages/upm</code></p>
<div class="highlight"><pre><span></span><span class="c1"># from build folder</span>
<span class="k">for</span> i in python2.7 python3.7 <span class="p">;</span> <span class="k">do</span> sudo cp src/*/<span class="nv">$i</span>/*.py /usr/lib/<span class="nv">$i</span>/dist-packages/upm/<span class="p">;</span> <span class="k">done</span>
<span class="k">for</span> i in python2.7 python3.7 <span class="p">;</span> <span class="k">do</span> sudo cp interfaces/<span class="nv">$i</span>/*.py /usr/lib/<span class="nv">$i</span>/dist-packages/upm/<span class="p">;</span> <span class="k">done</span>
</pre></div>
<p>Les programmes sont directement accessibles depuis les librairies python2, python3, Java, Javascript, C, C++.</p>
<h3><a name="head6.2.7"> </a> 6.2.7 Installation de compléments Python</h3>
<p>Un certain nombre de logiciels python sont installés par défaut pour satisfaire certains usages. Il est recommandé d'installer si besoin (tester avec <code>dpkg</code>)les librairies de développement suivantes qui fournissent les fichiers d'en-tête utilisés pour construire les outils python listés ci-dessous, sans ces librairies les installations avec <code>pipenv</code> ou <code>pip</code> n'aboutissent pas. <code>pipenv</code> est un outil qui permet de fabriquer un environnement virtuel dans lequel il est possible d'installer une série de packages python qui seront confinés dans cet espace. Les paquets ci-dessous peuvent avoir une utilité dans de nombreux programmes ils sont donc installés pour tout le système.</p>
<div class="highlight"><pre><span></span>dpkg -l libopenblas-dev libhdf5-dev libnetcdf-dev python3-pandas python3-rpi.gpio python3-netcdf4 python3-numpy python3-six python3-wheel python3-setuptools pandoc
sudo apt install libopenblas-dev libhdf5-dev libnetcdf-dev python3-pandas python3-rpi.gpio python3-netcdf4 python3-numpy python3-six python3-wheel python3-setuptools
sudo pip3 install --upgrade h5py pandas rpi.gpio netCDF4 numpy six wheel setuptools spidev folium pillow
</pre></div>
<h2><a name="head6.3"> </a> 6.3 Installation de Jupyterlab et Jupyterhub</h2>
<p><a href="https://jupyter.org/">Jupyter</a> est un interface graphique de développement et de programmation multilangages qui permet de se familiariser simplement avec la programmation. Il permet d'approcher simplement un langage de programmation sa syntaxe, son vocabulaire et sa logique. Il permet de produire et d'exploiter des <a href="https://ipython.org/">cahiers de programmes ipython</a> intégrant code source et commentaire qui s'avèrent être d'excellents outils pédagogiques pour l'apprentissage du code voir les <a href="https://github.com/g-vidal/CahierDeProgrammes">cahiers de programmes du projet Tremplin</a> et par exemple la <a href="https://github.com/g-vidal/CahierDeProgrammes/blob/master/StationMeteo/ministation3Capteurs.ipynb">ministation météo</a>. Jupyterhub est un outil companion de Jupyter qui permet de servir jupyter sur le web à plusieurs usagers en même temps, lors d'un TP ou TD par exemple.</p>
<p>Jupyter et Jupyterhub sont des logiciels python et peuvent donc être installés avec pip ou <code>pipenv</code>, jupyterhub requiert <code>python3</code>. Les commandes concernant <code>python2</code> sont maintenant obsolètes. Depuis <code>jupyterlab 3.0</code> on utilise exclusivement <code>python3</code> et <code>jupyter</code> est de moins en moins utilisé. Il est possible de réaliser une installation faisant appel à <code>pipenv</code> cette stratégie crée un environnement virtuel dans lequel la compatibilité et l'interopérabilité entre les paquets <code>python</code> est garantie sans perturber le fonctionnement du <code>python</code> global du système. L'inconvénient est que l'environnement virtuel duplique l'espace occupé par <code>python</code>.</p>
<h3><a name="head6.3.1"> </a> 6.3.1 Configuration de la sécurité et du lancement par le user callisto</h3>
<p>La sécurité est une contrainte importante de <code>jupyterhub</code> pour les mêmes raisons. La configuration est ici légèrement différente et l'authentification permet à chaque groupe ou élève (suivant le choix du professeur) de disposer d'un espace protégé des actions du reste du monde. <code>callisto</code> est l'utilisateur choisi pour lancer <code>jupyterhub</code>, pour assumer la configuration proposée c'est donc l'utilisateur callisto qui doit créer le certificat de sécurité.</p>
<div class="highlight"><pre><span></span>sudo su callisto
<span class="nb">cd</span>
mkdir -p Utils/Certificates
<span class="nb">cd</span> !$
openssl req -new -newkey rsa:2048 -rand /dev/urandom -nodes -keyout meteojuphub.key -out meteojuphub.csr
</pre></div>
<p>Répondre aux questions posées en fonction de vos paramètres.</p>
<div class="highlight"><pre><span></span>openssl req -new -x509 -days <span class="m">3652</span> -key meteojuphub.key -out meteojuphub.pem
</pre></div>
<p>On dispose maintenant des fichiers de sécurisaton nécessaires <code>meteojuphub.csr</code> <code>meteojuphub.key</code> <code>meteojuphub.pem</code> qui vont être utilisés pour protéger l'accès à jupyterhub. Par défaut un fichier de sécurisation a été installé pour permettre un fonctionnement immédiat mais <strong>chaque nouvel administrateur doit impérativement créer son propre fichier de sécurité</strong>. les manipulations qui suivent sont génériques et si les mêmes noms de fichier sont utilisés il ne sera pas nécessaire de répliquer les opérations ci-dessous.</p>
<p>Pour que les usagers choisis puissent ajouter leurs extensions il est nécessaire de modifier les permissions des dossiers de <code>/usr/local/share/jupyter</code>. Dans notre cas tous les usagers ayant ce droit appartiennent au groupe "jupyterhub" la solution choisie a donc été la suivante :</p>
<div class="highlight"><pre><span></span>sudo su
<span class="c1"># Si les dossiers suivants n'existent pas les créer</span>
<span class="c1"># /usr/local/share/jupyter</span>
mkdir /usr/local/share/jupyter
mkdir /usr/local/etc/jupyter
<span class="nb">cd</span> /usr/local/etc
chmod -R g+w jupyter <span class="o">&&</span> chgrp jupyterhub jupyter
<span class="c1"># Si les dossiers suivants n'existent pas les créer</span>
<span class="c1"># lab/extensions lab/settings lab/staging</span>
mkdir -p lab/extensions lab/settings lab/staging
chmod -R g+w jupyter <span class="o">&&</span> chgrp jupyterhub jupyter
</pre></div>
<p>On crée d'abord un environnement virtuel pour accueillir <code>jupyter</code> et <code>jupyterlab</code>.</p>
<div class="highlight"><pre><span></span>sudo apt install rustc
<span class="nb">cd</span>
mkdir JupyterVirtenv
<span class="nb">cd</span> JupyterVirtenv
pipenv install
pipenv install setuptools wheel jupyter jupyterlab jupyterhub
pipenv install matplotlib flexx plotly git+https://github.com/jupyter/sudospawner jupyter_contrib_nbextensions
pipenv run jupyter contrib nbextension install
<span class="nb">cd</span>
mkdir Jupyterhub
<span class="nb">cd</span> !$
pipenv run jupyterhub --generate-config
</pre></div>
<p>Éditer le fichier <code>jupyterhub_config.py</code> <code>nano jupyterhub_config.py</code> puis décommenter et renseigner les 3 lignes comme indiqué ci-dessous :</p>
<div class="highlight"><pre><span></span>.../...
<span class="c1">## The class to use for spawning single-user servers.</span>
<span class="c1"># </span>
<span class="c1"># Should be a subclass of Spawner.</span>
<span class="c1">#c.JupyterHub.spawner_class = 'jupyterhub.spawner.LocalProcessSpawner'</span>
c.JupyterHub.spawner_class<span class="o">=</span><span class="s1">'sudospawner.SudoSpawner'</span>
<span class="c1">## Path to SSL certificate file for the public facing interface of the proxy</span>
<span class="c1"># </span>
<span class="c1"># When setting this, you should also set ssl_key</span>
<span class="c1">#c.JupyterHub.ssl_cert = ''</span>
c.JupyterHub.ssl_cert <span class="o">=</span> <span class="s1">'/home/callisto/Utils/Certificates/meteojuphub.pem'</span>
<span class="c1">## Path to SSL key file for the public facing interface of the proxy</span>
<span class="c1"># </span>
<span class="c1"># When setting this, you should also set ssl_cert</span>
<span class="c1">#c.JupyterHub.ssl_key = ''</span>
c.JupyterHub.ssl_key <span class="o">=</span> <span class="s1">'/home/callisto/Utils/Certificates/meteojuphub.key'</span>
.../...
<span class="c1">## Set of users that will have admin rights on this JupyterHub.</span>
<span class="c1"># </span>
<span class="c1"># Admin users have extra privileges:</span>
<span class="c1"># - Use the admin panel to see list of users logged in</span>
<span class="c1"># - Add / remove users in some authenticators</span>
<span class="c1"># - Restart / halt the hub</span>
<span class="c1"># - Start / stop users' single-user servers</span>
<span class="c1"># - Can access each individual users' single-user server (if configured)</span>
<span class="c1"># </span>
<span class="c1"># Admin access should be treated the same way root access is.</span>
<span class="c1"># </span>
<span class="c1"># Defaults to an empty set, in which case no user has admin access.</span>
<span class="c1">#c.Authenticator.admin_users = set()</span>
c.Authenticator.admin_users <span class="o">=</span> set<span class="o">([</span><span class="s1">'localadm'</span>,<span class="s1">'callisto'</span>,<span class="s1">'ens-ife'</span><span class="o">])</span>
</pre></div>
<ul>
<li>pour utiliser exclusivement <code>jupyterlab</code> et non <code>jupyter</code> modifier le fichier de configuration de callisto <code>jupyterhub_config.py</code> en modifiant la valeur du paramètre suivant :</li>
</ul>
<div class="highlight"><pre><span></span>c.Spawner.cmd <span class="o">=</span> <span class="o">[</span><span class="s1">'jupyter-labhub'</span><span class="o">]</span>
c.Spawner.default_url <span class="o">=</span> <span class="s1">'/lab'</span>
</pre></div>
<p>Pour que <code>Jupyterhub</code> puisse être lancé par <code>callisto</code> et fonctionne correctement <code>callisto</code> (que nous avons choisi comme user pour lancer <code>Jupyterhub</code> doit disposer de quelques privilèges qui doivent être ajoutés par l'administrateur (et pas par callisto qui n'a pas de privilèges suffisants) au fichier sudoers avec la commande <code>sudo visudo</code> en ajoutant les lignes suivantes :</p>
<div class="highlight"><pre><span></span><span class="c1"># the command(s) the Hub can run on behalf of the jupyterhub group users</span>
<span class="c1"># without needing a password</span>
<span class="c1"># the exact path may differ, depending on how sudospawner was installed</span>
Cmnd_Alias <span class="nv">JUPYTER_CMD</span> <span class="o">=</span> /home/callisto/.local/share/virtualenvs/JupyterVirtenv-FmubDmff/bin/sudospawner
<span class="c1"># actually give the Hub user permission to run the above command</span>
<span class="c1"># on behalf of the above users without prompting for a password</span>
callisto <span class="nv">ALL</span><span class="o">=(</span>%jupyterhub<span class="o">)</span> NOPASSWD:JUPYTER_CMD
</pre></div>
<p>L'utilisateur <code>callisto</code> doit aussi appartenir au groupe shadow.</p>
<div class="highlight"><pre><span></span>sudo adduser callisto shadow
</pre></div>
<p>Tous les utilisateurs qui vont utiliser jupyter à distance doivent appartenir au groupe <code>jupyterhub</code>.</p>
<h3><a name="head6.3.2"> </a> 6.3.2 Ajout de moteurs nodeJS R et java dans l'environnement jupyter/jupyterhub</h3>
<p><code>Jupyter</code> et <code>Jupyterhub</code> sont programmés en python mais les <code>notebooks</code> (cahiers d'exercices) qu'ils utilisent peuvent fonctionner avec d'autres langages, à titre d'exemple nous proposons ici l'installation du moteur javascript permettant de programmer en nodeJS et "R".
Installation de R et du noyau javascript.</p>
<div class="highlight"><pre><span></span>sudo apt install r-base r-base-core
sudo npm install -g --unsafe-perm ijavascript
<span class="c1">#(?)sudo ijsinstall --install=global</span>
<span class="c1">#(?)cp -r /usr/local/share/jupyter/kernels/javascript .</span>
sudo Rscript -e <span class="s1">'install.packages(c("repr", "IRdisplay", "IRkernel"), type = "source", repos="https://cran.rstudio.com");'</span>
</pre></div>
<p>Installation des noyaux supplémentaires dans et extraction d'un notebookun notebook.</p>
<div class="highlight"><pre><span></span>sudo su callisto
<span class="nb">cd</span> ~/JupyterVirtenv
ijsinstall --install<span class="o">=</span><span class="nb">local</span>
Rscript -e <span class="s1">'IRkernel::installspec()'</span>
cp -r ~/.local/share/jupyter/kernels/* ~/.local/share/virtualenvs/JupyterVirtenv-FmubDmff/share/jupyter/kernels
pipenv install voila kotlin-jupyter-kernel
</pre></div>
<p>La version 3 de jupyterlab résoud tous les problèmes d'extensions en permettant d'ajouter les extensions depuis l'interface web. En cas de besoin le contournement qui avait été utilisé précédemment pour permettre d'installer proprement les extensions en ligne de commande avec <code>jupyter lab build</code>, pour les raspberries PI3 et en dessous est proposé, . Le contournement foncctionne avec <code>webpack</code>.</p>
<div class="highlight"><pre><span></span>sudo npm install -g webpack webpack-cli webpack-bundle-analyzer
<span class="nb">cd</span> /usr/local/share/jupyter/lab/staging
sudo su
<span class="nv">NODE_OPTIONS</span><span class="o">=</span><span class="s2">"--max-old-space-size=850"</span> webpack --config webpack.prod.minimize.config.js <span class="c1"># pour la pi3 1Go</span>
<span class="nv">NODE_OPTIONS</span><span class="o">=</span><span class="s2">"--max-old-space-size=3500"</span> webpack --config webpack.prod.minimize.config.js <span class="c1"># pour la pi4 4Go</span>
</pre></div>
<div class="highlight"><pre><span></span>pipenv run jupyter-labextension install @jupyterlab/toc
pipenv run jupyter-labextension install @jupyterlab/git
pipenv run jupyter labextension install @jupyterlab/hub-extension
</pre></div>
<p>Vérifier que les logiciels nécessaires à la production de sorties textes au format pdf drpuis jupyter ou jupyterlab est possible avec la commancde </p>
<div class="highlight"><pre><span></span>pipenv shell
pipenv install pandoc pandocfilters
sudo dpkg -l texlive-xetex texlive-latex-recommended texlive-lang-other<span class="sb">`</span>
</pre></div>
<p>la réponse doit être du type :</p>
<div class="highlight"><pre><span></span><span class="o">||</span>/ Nom Version Architecture Description
+++-<span class="o">=========================</span>-<span class="o">===============</span>-<span class="o">============</span>-<span class="o">=====================================</span>
ii texlive-lang-other <span class="m">2018</span>.20190227-2 all TeX Live: Other languages
ii texlive-latex-recommended <span class="m">2018</span>.20190227-2 all TeX Live: LaTeX recommended packages
ii texlive-xetex <span class="m">2018</span>.20190227-2 all TeX Live: XeTeX and packages
</pre></div>
<p>Si ce n'est pas le cas installer les paquets manquants avec <code>sudo apt install ...</code></p>
<h3><a name="head6.3.3"> </a> 6.3.3 Installation d'un service <code>jupyterlabhub</code></h3>
<p>Pour mettre en place un service placer le fichier <code>jupyterlabhub.service</code> dans <code>/etc/systemd/system</code> :</p>
<div class="highlight"><pre><span></span>sudo jed /etc/systemd/system/jupyterlabhub.service
</pre></div>
<div class="highlight"><pre><span></span><span class="o">[</span>Unit<span class="o">]</span>
<span class="nv">Description</span><span class="o">=</span>Jupyterlabhub
<span class="nv">After</span><span class="o">=</span>network-online.target
<span class="o">[</span>Service<span class="o">]</span>
<span class="nv">User</span><span class="o">=</span>callisto
<span class="nv">WorkingDirectory</span><span class="o">=</span>/home/callisto/JupyterVirtenv
<span class="nv">ExecStart</span><span class="o">=</span> pipenv run jupyterhub --config<span class="o">=</span>/home/callisto/Jupyterhub/jupyterhub_config.py
<span class="o">[</span>Install<span class="o">]</span>
<span class="nv">WantedBy</span><span class="o">=</span>multi-user.target
</pre></div>
<p>Faire prendre en compte le nouveau service avec <code>sudo systemctl daemon-reload</code> puis contrôler le service avec les commandes habituelles, pour avoir jupyterhub au démarrage <code>sudo systemctl enable jupyterhub</code></p>
<div class="highlight"><pre><span></span>sudo systemctl status jupyterhub
sudo systemctl start jupyterhub
sudo systemctl stop jupyterhub
</pre></div>
<h2><a name="head6.4"> </a> 6.4 Ajout de scripts pour démarrer ou supprimer un service au démarrage</h2>
<p>Les services <code>Jupyterhub</code>, <code>vncserver</code>, <code>weewx</code> peuvent tous être mis en route au démarrage mais ils consomment inutilement des ressources si ils ne sont pas utilisés. Les scripts suivants permettent de gérer la mise en route de ces services au démarrage. Par défaut seul le serveur vnc est mis en route. Le contenu de ces scripts est détaillé c dessous.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir Scripts
<span class="nb">cd</span> Scripts
</pre></div>
<h3><a name="head6.4.1"> </a> 6.4.1 Pour <code>jupyterhub</code></h3>
<p>Ajouter le fichier avec <code>cat > jupyterhubOnOff</code> ou une commande équivalente</p>
<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1">#script pour activer/désactiver jupyterhub au boot</span>
<span class="c1">#</span>
<span class="nv">prog</span><span class="o">=</span><span class="sb">`</span>basename <span class="nv">$0</span><span class="sb">`</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nv">$2</span> <span class="o">==</span> <span class="s2">""</span> <span class="o">]]</span> <span class="p">;</span> <span class="k">then</span>
<span class="nb">echo</span> <span class="s2">"Type "</span> <span class="nv">$prog</span> <span class="s2">" [on / off] [lab / nbk]"</span>
<span class="nb">echo</span> <span class="s2">"Start or stop jupyterlabhub at boot"</span>
<span class="nb">exit</span>
<span class="k">else</span>
<span class="k">case</span> <span class="nv">$1</span> in
on <span class="o">)</span>
sudo systemctl <span class="nb">enable</span> jupyterhub
<span class="p">;;</span>
off <span class="o">)</span>
sudo systemctl disable jupyterlabhub
<span class="p">;;</span>
* <span class="o">)</span>
<span class="nb">echo</span> <span class="s2">"Choice is on or off"</span>
<span class="nb">exit</span>
<span class="p">;;</span>
<span class="k">esac</span>
<span class="k">fi</span>
</pre></div>
<h3><a name="head6.4.2"> </a> 6.4.2 Pour <code>weewx</code></h3>
<p>Ajouter le fichier avec <code>cat > weewxOnOff</code> ou une commande équivalente</p>
<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1"># script pour activer/désactiver weewx au boot</span>
<span class="c1">#</span>
<span class="nv">prog</span><span class="o">=</span><span class="sb">`</span>basename <span class="nv">$0</span><span class="sb">`</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nv">$1</span> <span class="o">==</span> <span class="s2">""</span> <span class="o">]]</span> <span class="p">;</span> <span class="k">then</span>
<span class="nb">echo</span> <span class="s2">"Type "</span> <span class="nv">$prog</span> <span class="s2">"on or off to start or stop weewx at boot"</span>
<span class="nb">exit</span>
<span class="k">else</span>
<span class="k">case</span> <span class="nv">$1</span> in
on <span class="o">)</span>
sudo systemctl <span class="nb">enable</span> weewx
<span class="p">;;</span>
off <span class="o">)</span>
sudo systemctl disable weewx
<span class="p">;;</span>
* <span class="o">)</span>
<span class="nb">echo</span> <span class="s2">"Choice is on or off"</span>
<span class="nb">exit</span>
<span class="p">;;</span>
<span class="k">esac</span>
<span class="k">fi</span>
</pre></div>
<p>Rendre les fichiers exécutables puis les copier les scripts dans le répertoire <code>/usr/local/bin</code> </p>
<div class="highlight"><pre><span></span>chmod a+x ./*
sudo cp ~/Scripts/* /usr/local/bin
</pre></div>
<h2><a name="head6.5"> </a> 6.5 Ajout des cahiers de programmes pour apprendre/enseigner la programmation</h2>
<p>Ajouter les cahiers de programmes du projet Tremplin des Sciences depuis la <code>forge git</code> du projet Tremplin.</p>
<div class="highlight"><pre><span></span>sudo su moon
<span class="nb">cd</span>
git clone http://vidal@depot.tremplin.ens-lyon.fr/Tremplin-des-Sciences/CahiersDeProgrammesCodage
<span class="nb">exit</span>
sudo su localadm
<span class="nb">cd</span>
git clone http://vidal@depot.tremplin.ens-lyon.fr/Tremplin-des-Sciences/CahiersDeProgrammesCodage
<span class="nb">exit</span>
<span class="nb">cd</span>
git clone http://vidal@depot.tremplin.ens-lyon.fr/Tremplin-des-Sciences/CahiersDeProgrammesCodage
</pre></div>
<h2><a name="head6.6"> </a> 6.6 Compléments pour le pilotage de la station météorologique des capteurs et le partage de données</h2>
<h3><a name="head6.6.1"> </a> 6.6.1 Configuration du logiciel de pilotage de stations météorologiques</h3>
<p>Le logiciel <code>weewx</code> récupère les données de la station météorologique qui lui est connectée et fournit des pages web affichant les mesures réalisées.Une version à jour à la date de création de l'image est installée par défaut ou téléchargé depuis le <a href="http://weewx.com/downloads/">site d'origine</a>. télécharger les mises à jour et les installer au besoin. Après avoir créé le répertoire <code>Logiciels</code> s'il n'existe pas encore, on récupère ici à titre conservatoire une copie du paquet <code>weewx</code>.</p>
<p><strong>Attention !</strong> le logiciel <code>weewx</code> ne figure pas dans les dépôts debian par défaut, les mises à jour doivent être faites à la main en téléchargeant le paquet <code>http://weewx.com/downloads/released_versions/python3-weewx_4.2.0-1_all.deb</code> et en l'installant avec la commande <code>dpkg -i python3-weewx_4.2.0-1_all.deb</code>, lors d'une telle mise à jour de weewx le fichier de configuration <code>/etc/weewx/weewx.conf</code> est réécrit en tenant compte de son contenu avant mise à jour. Toutefois, faire une copie de ce fichier <em>AVANT</em> d'entreprendre la mise à jour, puis comparer et modifier si nécessaire le nouveau fichier (le fichier existant étant utilisé comme modèle les paramètres sont théoriquement conservés mais une erreur même minime de syntaxe peut entrainer la perte de paramètres, il est souhaitable de vérifier attentivement).</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span>
mkdir -p Logiciels/Weewx
<span class="nb">cd</span> !$
wget http://weewx.com/downloads/released_versions/python3-weewx_4.2.0-1_all.deb
</pre></div>
<div class="highlight"><pre><span></span>sudo su weewx
<span class="nb">cd</span>
mkdir .ssh
<span class="nb">cd</span> .ssh
cat > id_rsa
<span class="c1"># copy here the ssh key</span>
chmod og-r id_rsa
cat > known_hosts
<span class="c1"># copy here the hosts known by other raspis</span>
</pre></div>
<h3><a name="head6.6.2"> </a> 6.6.2 Ajout des cadrans interactifs</h3>
<p>Il est possible de proposer plusieurs modes d'affichage. Nous avons choisi d'ajouter ici un affichage par cadrans et un affichage par semaine ou mois téléchargeables depuis la forge <code>github</code>. Les deux ambiances graphiques (skins) qui sont utilisées ici pour afficher les données sont <code>highcharts</code> et <code>Steel-Series</code>. Elles sont intégrées sous la forme d'extensions du logiciel <code>weewx</code> en utilisant la procédure <code>wee_extension</code>.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> ~/Logiciels/Weewx
mkdir Skins
<span class="nb">cd</span> Skins
wget -P . https://github.com/gjr80/weewx-highcharts/releases/download/v0.3.2/hfw-0.3.2.tar.gz
wget -P . https://github.com/gjr80/weewx-steelseries/releases/download/v2.7.6/steelseries-2.7.6.tar.gz
wget -P . https://github.com/gjr80/weewx-realtime_gauge-data/releases/download/v0.4.2/rtgd-0.4.2.tar.gz
sudo systemctl stop weewx
sudo wee_extension --install<span class="o">=</span>hfw-0.3.2.tar.gz
sudo wee_extension --install<span class="o">=</span>steelseries-2.7.6.tar.gz
sudo wee_extension --install<span class="o">=</span>rtgd-0.4.2.tar.gz
<span class="nb">cd</span> /var/www/html/
sudo chown -R weewx.weewx weewx
<span class="nb">cd</span> weewx
sudo mkdir ss
sudo chown -R weewx.weewx ss
sudo mkdir seasons
sudo chown -R weewx.weewx seasons
</pre></div>
<p>Les éléments de configuration sont intégrés aufichier <code>/etc/weewx/weewx.conf</code> parmi les modifications de configuration déjà effectuées. Il est nécessaire de modifier les paramètres intégrés automatiquement en fonctions des choix d'affichage personnalisés de chacun (notamment les unités). les sections nouvellement installées à modifier sont les suivantes :</p>
<div class="highlight"><pre><span></span>
</pre></div>
<div class="highlight"><pre><span></span> <span class="o">[[</span>Highcharts<span class="o">]]</span>
<span class="nv">skin</span> <span class="o">=</span> Highcharts
<span class="o">[[[</span>Units<span class="o">]]]</span>
<span class="o">[[[[</span>StringFormats<span class="o">]]]]</span>
<span class="o">[[[[</span>Groups<span class="o">]]]]</span>
.../...
<span class="o">[[</span>SteelSeries<span class="o">]]</span>
<span class="nv">skin</span> <span class="o">=</span> ss
<span class="nv">HTML_ROOT</span> <span class="o">=</span> /var/www/html/ss
<span class="o">[[[</span>Units<span class="o">]]]</span>
<span class="o">[[[[</span>StringFormats<span class="o">]]]]</span>
<span class="o">[[[[</span>Groups<span class="o">]]]]</span>
</pre></div>
<p>Les affichages améliorés sont maintenant disponibles.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> ~/Logiciels/Weewx
mkdir Utils
<span class="nb">cd</span> !$
git clone https://github.com/mcrossley/SteelSeries-Weather-Gauges.git
<span class="nb">cd</span> SteelSeries-Weather-Gauges/
</pre></div>
<p>Créer ensuite dans la hiérarchie <code>weewx</code> le dossier qui contiendra le graphisme de l'interface et recopier les fichiers téléchargés.</p>
<div class="highlight"><pre><span></span>sudo mkdir /etc/weewx/skins/ss
sudo cp weather_server/WeeWX/skin.conf /etc/weewx/skins/ss
sudo cp weather_server/WeeWX/index.html.tmpl /etc/weewx/skins/ss
sudo cp weather_server/WeeWX/gauge-data.txt.tmpl /etc/weewx/skins/ss
</pre></div>
<p>S'ils n'existent pas encore ajouter les répertoires suivants et leur contenu</p>
<div class="highlight"><pre><span></span>sudo mkdir /etc/weewx/skins/ss/css
sudo cp web_server/css/*.css /etc/weewx/skins/ss/css
sudo mkdir /etc/weewx/skins/ss/scripts
sudo cp web_server/scripts/*.js /etc/weewx/skins/ss/scripts
</pre></div>
<p>Éditer ensuite le fichier <code>/etc/weewx/skins/ss/scripts/gauges.js</code> et le modifier en fonction des paramètres locaux et des choix d'affichage.</p>
<div class="highlight"><pre><span></span>weatherProgram : <span class="m">6</span>,
imgPathURL : <span class="s1">''</span>,
stationTimeout : <span class="m">10</span>, // <span class="nb">set</span> to twice archive interval, in minutes
showUvGauge : true, // <span class="nb">false</span> <span class="k">if</span> there is no UV sensor
showSolarGauge : true, // <span class="nb">false</span> <span class="k">if</span> there is no solar radiation sensor
showRoseGauge : false, // <span class="nb">true</span> <span class="k">if</span> field WindRoseData is populated
</pre></div>
<p>Pour afficher les mesures en temps réel il est nécessaire de synchroniser la Raspberry Pi avec le serveur web des opendata, cela se fait en modifiant les paramètres <code>[[RSYNC]]</code> de <code>weewx.conf</code>; les modifications sont commentées pour éviter que la synchronisation échoue tant que le réseau n'est pas correctement configuré(il s'agit d'une précaution) :</p>
<div class="highlight"><pre><span></span> <span class="o">[[</span>RSYNC<span class="o">]]</span>
<span class="c1">#delete = 1</span>
<span class="c1">#HTML_ROOT = /var/www/html/ss</span>
<span class="c1">#server = stationsdata.climatetmeteo.fr</span>
<span class="c1">#path = folder_name_path_on_server</span>
<span class="c1">#user = opendata</span>
</pre></div>
<p>Ajouter le service <code>weewx.service</code> </p>
<div class="highlight"><pre><span></span>sudo su
cat /etc/systemd/system/weewx.service
<span class="c1"># systemd configuration for weewx</span>
<span class="o">[</span>Unit<span class="o">]</span>
<span class="nv">Description</span><span class="o">=</span>weewx weather system
<span class="nv">Requires</span><span class="o">=</span>time-sync.target
<span class="nv">After</span><span class="o">=</span>time-sync.target
<span class="c1"># Uncomment the following two line if your database is written using mysql or MariaDB on the same host</span>
<span class="c1">#After=mysql.service</span>
<span class="c1">#BindsTo=mysql.service</span>
<span class="c1"># The following two lines should be uncommented and used if you</span>
<span class="c1"># have enabled Restart=on-failure in the [Service] section below.</span>
<span class="c1"># StartLimitIntervalSec=100</span>
<span class="c1"># StartLimitBurst=5</span>
<span class="o">[</span>Service<span class="o">]</span>
<span class="c1"># The following two lines may be uncommented and used if you</span>
<span class="c1"># want the weewx service to automatically restart if it crashes.</span>
<span class="c1"># This can be particularly useful if weewx has an IP connection to the weather station</span>
<span class="c1"># it is monitoring, since transient network problems are quite</span>
<span class="c1"># common, and may cause the daemon to crash.</span>
<span class="c1"># Adjust timing according to the typical recovery times in your situation</span>
<span class="c1">#Restart=on-failure</span>
<span class="c1">#RestartSec=20</span>
<span class="c1"># create a runtime directory below /run, because non-root users cannot create a file in /run itself</span>
<span class="c1"># This works for root as well as non-root users.</span>
<span class="nv">RuntimeDirectory</span><span class="o">=</span>weewx
<span class="nv">PIDFile</span><span class="o">=</span>/run/weewx/weewx.pid
<span class="c1"># setting the preserve option stops systemd deleting the PID file when weewx exits (debugging only)</span>
<span class="c1"># RuntimeDirectoryPreserve=yes</span>
<span class="nv">ExecStart</span><span class="o">=</span>/usr/bin/weewxd --daemon --pidfile<span class="o">=</span>/run/weewx/weewx.pid /etc/weewx/weewx.conf
<span class="nv">ExecReload</span><span class="o">=</span>/bin/kill -HUP <span class="nv">$MAINPID</span>
<span class="nv">Type</span><span class="o">=</span>forking
<span class="c1"># See notes later in this wiki; by default weewx will run with root privileges, so</span>
<span class="c1"># comment out the following two lines to run weewx as root.</span>
<span class="nv">User</span><span class="o">=</span>weewx
<span class="nv">Group</span><span class="o">=</span>weewx
<span class="o">[</span>Install<span class="o">]</span>
<span class="nv">WantedBy</span><span class="o">=</span>multi-user.target
</pre></div>
<h3><a name="head6.6.3"> </a> 6.6.3 Installation et configuration du pare-feu</h3>
<p>La Raspberry va être exposée sur le net il est important d'être attentifs à la sécurité de cette machine. Une première méthode est de mettre en place un pare-feu mais cette opération est délicate et difficile à faire à la main; nous utiliserons donc un logiciel d'asssitance à la création de pare-feu <code>nftables</code>. Ce logiciel permet d'établir des règles de filtrage avec une syntaxe (relativement) intelligible dans un fichier de configuration, il se charge ensuite de construire et activer les règles de filtrage correspondant aux instructions de l'usager. L'installation du paquet se fait avec la procédure habituelle.</p>
<div class="highlight"><pre><span></span>sudo dpkg -l nftables
sudo apt install nftables
</pre></div>
<p>Activer <code>nftables</code> au démarrage par défaut:</p>
<div class="highlight"><pre><span></span>sudo systemctl <span class="nb">enable</span> nftables.service
</pre></div>
<p>Le fichier de configuration se trouve ici <code>/etc/nftables.conf</code>. À titre d'exemple la configuration du pare-feu pour le projet tremplin est proposée ci-dessous commentée afin de permettre le fonctionnement par défaut de l'image. Le pare-feu doit être configuré avec les paramètres locaux de l'usager, si la configuration ne correspond pas à l'environnement réseau de la Raspberry cette dernière peut devenir inaccessible ! <strong>Soyez prudents</strong>. En cas de problème il est toujours possible d'accéder au contenu de la microSD depuis une machine GNU/linux et de modifier le fichier de configuration; si vous êtes sous un autre système d'exploitation il est possible de démarrer votre ordinateur en utilisant une clef USB GNU/linux live qui fournit un ordinateur opérationnel sans rien toucher de ce qui est installé par exemple debian live.</p>
<p>Propositions de fichier de configuration nftables.conf.</p>
<div class="highlight"><pre><span></span><span class="ch">#!/usr/sbin/nft -f</span>
flush ruleset
table inet filter <span class="o">{</span>
<span class="nb">set</span> ALLOWED_SSH <span class="o">{</span>
<span class="nb">type</span> ipv4_addr
flags interval
<span class="c1"># ENS de lyon : 140.77.89.0/24, 140.77.84.0/22, 140.77.176.0/21</span>
<span class="c1"># che : 82.224.43.181 - Gerard Vidal : 78.194.2.7 </span>
<span class="c1"># Éric le Jan : 109.12.222.143 - Rectorat de Lyon : 195.83.17.252/29</span>
<span class="c1"># Intenal : 172.23.75.0/24, 172.22.230.0/23, 192.168.137.0/24</span>
<span class="c1"># outbound : 192.168.221.41 </span>
<span class="nv">elements</span> <span class="o">=</span> <span class="o">{</span>
<span class="m">140</span>.77.89.0/24, <span class="se">\</span>
<span class="m">140</span>.77.84.0/22, <span class="se">\</span>
<span class="m">140</span>.77.176.0/21, <span class="se">\</span>
<span class="m">82</span>.253.162.44, <span class="se">\</span>
<span class="m">82</span>.224.43.181, <span class="se">\</span>
<span class="m">78</span>.194.2.7, <span class="se">\</span>
<span class="m">109</span>.12.222.143, <span class="se">\</span>
<span class="m">195</span>.83.17.252/29, <span class="se">\</span>
<span class="m">172</span>.23.75.0/24, <span class="se">\</span>
<span class="m">172</span>.22.230.0/23, <span class="se">\</span>
<span class="m">192</span>.168.137.0/24, <span class="se">\</span>
<span class="m">192</span>.168.221.41
<span class="o">}</span>
<span class="o">}</span>
chain input <span class="o">{</span>
<span class="nb">type</span> filter hook input priority <span class="m">0</span><span class="p">;</span>
policy drop<span class="p">;</span>
<span class="c1"># established/related connections</span>
ct state established,related accept
<span class="c1"># invalid connections</span>
ct state invalid drop
<span class="c1"># loopback interface</span>
iif lo accept
<span class="c1"># ICMP & IGMP</span>
ip protocol icmp icmp <span class="nb">type</span> <span class="o">{</span> echo-request, echo-reply, destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem <span class="o">}</span> accept
ip protocol igmp accept
<span class="c1"># SSH (port 24122)</span>
tcp dport <span class="m">24122</span> ip saddr @ALLOWED_SSH accept
<span class="c1"># HTTP (ports 80, 24180, 34180:34181)</span>
tcp dport <span class="o">{</span> http, https <span class="o">}</span> accept
<span class="c1"># HTTPS (ports 443, 24143)</span>
tcp dport <span class="o">{</span> https, <span class="m">24143</span> <span class="o">}</span> accept
<span class="c1"># mysql</span>
tcp dport <span class="m">34107</span> accept
<span class="c1"># email</span>
tcp dport <span class="o">{</span> <span class="m">25</span>, <span class="m">587</span> <span class="o">}</span> accept
<span class="o">}</span>
chain forward <span class="o">{</span>
<span class="nb">type</span> filter hook forward priority <span class="m">0</span><span class="p">;</span>
policy drop<span class="p">;</span>
<span class="o">}</span>
chain output <span class="o">{</span>
<span class="nb">type</span> filter hook output priority <span class="m">0</span><span class="p">;</span>
policy accept<span class="p">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<h3><a name="head6.6.4"> </a> 6.6.4 Installation et configuration de la base de données relationnelle mariadb</h3>
<p>Par défaut <code>weewx</code> utilise une base <code>sqlite</code>, pour des raisons d'interopérabilité et de facilitation du partage des données nous installons les composants serveur et client de la base <code>mariadb</code>. Nous effectuons un installation par défaut, au moment de la rédaction (27/11/2020) la dernière version disponible est 10.3.25-0+deb10u1.</p>
<div class="highlight"><pre><span></span>dpkg -l mariadb-client mariadb-server mariadb-common
sudo apt install mariadb-client mariadb-server mariadb-common
</pre></div>
<p>La base de données est maintenant installée, il est nécessaire de la configurer. On ajoute un mot de passe à l'utilisateur root, on ajoute ensuite un utilisateur admin avec privilèges qui évite d'utiliser root pour la configuration le mot de passe <code>Achanger1$</code> est utilisé pour tous les comptes cette valeur est à changer comme son nom l'indique !</p>
<div class="highlight"><pre><span></span>sudo mysql -u root
Welcome to the MariaDB monitor. Commands end with <span class="p">;</span> or <span class="se">\g</span>.
Your MariaDB connection id is <span class="m">2</span>
Server version: <span class="m">10</span>.1.26-MariaDB-0+deb9u1 Debian <span class="m">9</span>.1
Copyright <span class="o">(</span>c<span class="o">)</span> <span class="m">2000</span>, <span class="m">2017</span>, Oracle, MariaDB Corporation Ab and others.
Type <span class="s1">'help;'</span> or <span class="s1">'\h'</span> <span class="k">for</span> help. Type <span class="s1">'\c'</span> to clear the current input statement.
MariaDB <span class="o">[(</span>none<span class="o">)]</span>> <span class="k">select</span> password <span class="o">(</span><span class="s1">'AChanger1$'</span><span class="o">)</span><span class="p">;</span>
+-------------------------------------------+
<span class="p">|</span> password <span class="o">(</span><span class="s1">'AChanger1$'</span><span class="o">)</span> <span class="p">|</span>
+-------------------------------------------+
<span class="p">|</span> *695008F6BF1536D1C456BC7B1226080345359BB9 <span class="p">|</span>
+-------------------------------------------+
<span class="m">1</span> row in <span class="nb">set</span> <span class="o">(</span><span class="m">0</span>.01 sec<span class="o">)</span>
MariaDB <span class="o">[(</span>none<span class="o">)]</span>> use mysql
Reading table information <span class="k">for</span> completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> UPDATE user SET <span class="nv">password</span><span class="o">=</span>PASSWORD<span class="o">(</span><span class="s2">"*695008F6BF1536D1C456BC7B1226080345359BB9"</span><span class="o">)</span> WHERE <span class="nv">User</span><span class="o">=</span><span class="s1">'root'</span><span class="p">;</span>
Query OK, <span class="m">1</span> row affected <span class="o">(</span><span class="m">0</span>.00 sec<span class="o">)</span>
Rows matched: <span class="m">1</span> Changed: <span class="m">1</span> Warnings: <span class="m">0</span>
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> CREATE USER <span class="s1">'admin'</span>@<span class="s1">'localhost'</span> IDENTIFIED BY PASSWORD <span class="s1">'*695008F6BF1536D1C456BC7B1226080345359BB9'</span><span class="p">;</span>
Query OK, <span class="m">0</span> rows affected <span class="o">(</span><span class="m">0</span>.00 sec<span class="o">)</span>
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> GRANT ALL PRIVILEGES ON *.* TO <span class="s1">'admin'</span>@<span class="s1">'localhost'</span> WITH GRANT OPTION<span class="p">;</span>
Query OK, <span class="m">0</span> rows affected <span class="o">(</span><span class="m">0</span>.00 sec<span class="o">)</span>
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> CREATE USER <span class="s1">'admin'</span>@<span class="s1">'%'</span> IDENTIFIED BY PASSWORD <span class="s1">'*695008F6BF1536D1C456BC7B1226080345359BB9'</span><span class="p">;</span>
Query OK, <span class="m">0</span> rows affected <span class="o">(</span><span class="m">0</span>.01 sec<span class="o">)</span>
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> GRANT ALL PRIVILEGES ON *.* TO <span class="s1">'admin'</span>@<span class="s1">'%'</span> WITH GRANT OPTION<span class="p">;</span>
Query OK, <span class="m">0</span> rows affected <span class="o">(</span><span class="m">0</span>.00 sec<span class="o">)</span>
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> <span class="k">select</span> host, user, default_role, is_role, password from mysql.user<span class="p">;</span>
+-----------+-------+--------------+---------+-------------------------------------------+
<span class="p">|</span> host <span class="p">|</span> user <span class="p">|</span> default_role <span class="p">|</span> is_role <span class="p">|</span> password <span class="p">|</span>
+-----------+-------+--------------+---------+-------------------------------------------+
<span class="p">|</span> localhost <span class="p">|</span> root <span class="p">|</span> <span class="p">|</span> N <span class="p">|</span> *9FDA0930AF881812755F2746906A517D7C892BA6 <span class="p">|</span>
<span class="p">|</span> localhost <span class="p">|</span> admin <span class="p">|</span> <span class="p">|</span> N <span class="p">|</span> *695008F6BF1536D1C456BC7B1226080345359BB9 <span class="p">|</span>
<span class="p">|</span> % <span class="p">|</span> admin <span class="p">|</span> <span class="p">|</span> N <span class="p">|</span> *695008F6BF1536D1C456BC7B1226080345359BB9 <span class="p">|</span>
+-----------+-------+--------------+---------+-------------------------------------------+
<span class="m">3</span> rows in <span class="nb">set</span> <span class="o">(</span><span class="m">0</span>.00 sec<span class="o">)</span>
MariaDB <span class="o">[</span>mysql<span class="o">]</span>> <span class="se">\q</span>
Bye
</pre></div>
<p>Nous souhaitons pouvoir accéder à la base depuis des machines extérieures (pour partager les données dans le cadre du projet par exemple), pour cela il est nécessaire de modifier quelques paramètres du fichier de configuration <code>/etc/mysql/mariadb.conf.d/50-server.cnf</code>.</p>
<div class="highlight"><pre><span></span>sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
</pre></div>
<p>Pour avoir un accès distant ajouter le paramère <code>skip-bind-address</code> et pour changer le port le paramètre <code>port</code>. Sans changement la base écoute sur le port par défaut et seulement sur localhost.</p>
<div class="highlight"><pre><span></span><span class="o">[</span>mysqld<span class="o">]</span>
<span class="nv">port</span> <span class="o">=</span> ****
.../...
skip-networking<span class="o">=</span><span class="m">0</span>
skip-bind-address
</pre></div>
<p>Relancer le serveur pour vérifier que les paramètres sont priss en compte.</p>
<div class="highlight"><pre><span></span>sudo systemctl restart mysqld
sudo systemctl status mysqld
</pre></div>
<p>Le système doit être chargé et fournir une réponse du type suivant.</p>
<div class="highlight"><pre><span></span>● mariadb.service - MariaDB database server
Loaded: loaded <span class="o">(</span>/lib/systemd/system/mariadb.service<span class="p">;</span> enabled<span class="p">;</span> vendor preset: enabled<span class="o">)</span>
Active: active <span class="o">(</span>running<span class="o">)</span> since Fri <span class="m">2018</span>-01-19 <span class="m">01</span>:27:45 CET<span class="p">;</span> 6s ago
Process: <span class="m">3616</span> <span class="nv">ExecStartPost</span><span class="o">=</span>/bin/sh -c systemctl unset-environment _WSREP_START_POSITION <span class="o">(</span><span class="nv">code</span><span class="o">=</span>exited, <span class="nv">status</span><span class="o">=</span><span class="m">0</span>/SUCCESS<span class="o">)</span>
Process: <span class="m">3613</span> <span class="nv">ExecStartPost</span><span class="o">=</span>/etc/mysql/debian-start <span class="o">(</span><span class="nv">code</span><span class="o">=</span>exited, <span class="nv">status</span><span class="o">=</span><span class="m">0</span>/SUCCESS<span class="o">)</span>
Process: <span class="m">3496</span> <span class="nv">ExecStartPre</span><span class="o">=</span>/bin/sh -c <span class="o">[</span> ! -e /usr/bin/galera_recovery <span class="o">]</span> <span class="o">&&</span> <span class="nv">VAR</span><span class="o">=</span> <span class="o">||</span> <span class="nv">VAR</span><span class="o">=</span><span class="sb">`</span>/usr/bin/galera_recovery<span class="sb">`</span><span class="p">;</span> <span class="o">[</span> <span class="nv">$?</span> -eq <span class="m">0</span> <span class="o">]</span> <span class="o">&&</span>
Process: <span class="m">3491</span> <span class="nv">ExecStartPre</span><span class="o">=</span>/bin/sh -c systemctl unset-environment _WSREP_START_POSITION <span class="o">(</span><span class="nv">code</span><span class="o">=</span>exited, <span class="nv">status</span><span class="o">=</span><span class="m">0</span>/SUCCESS<span class="o">)</span>
Process: <span class="m">3487</span> <span class="nv">ExecStartPre</span><span class="o">=</span>/usr/bin/install -m <span class="m">755</span> -o mysql -g root -d /var/run/mysqld <span class="o">(</span><span class="nv">code</span><span class="o">=</span>exited, <span class="nv">status</span><span class="o">=</span><span class="m">0</span>/SUCCESS<span class="o">)</span>
Main PID: <span class="m">3586</span> <span class="o">(</span>mysqld<span class="o">)</span>
Status: <span class="s2">"Taking your SQL requests now..."</span>
CGroup: /system.slice/mariadb.service
└─3586 /usr/sbin/mysqld
janv. <span class="m">19</span> <span class="m">01</span>:27:42 raspwife3 systemd<span class="o">[</span><span class="m">1</span><span class="o">]</span>: Starting MariaDB database server...
janv. <span class="m">19</span> <span class="m">01</span>:27:43 raspwife3 mysqld<span class="o">[</span><span class="m">3586</span><span class="o">]</span>: <span class="m">2018</span>-01-19 <span class="m">1</span>:27:43 <span class="m">1996341248</span> <span class="o">[</span>Note<span class="o">]</span> /usr/sbin/mysqld <span class="o">(</span>mysqld <span class="m">10</span>.1.26-MariaDB-0+deb9u1<span class="o">)</span> start
janv. <span class="m">19</span> <span class="m">01</span>:27:45 raspwife3 systemd<span class="o">[</span><span class="m">1</span><span class="o">]</span>: Started MariaDB database server.
</pre></div>
<p>La suite des interventions sur la base de données peut alors se faire depuis un outil à ditance comme <code>DBeaver</code>, pour augmenter la sécurité PHPmyadmin n'est pas installé toutes les fonctionnalités étant fournies par le client <code>DBeaver</code></p>
<p>Pour obtenir un bon fonctionnement il est impératif de synchroniser la configuration de <code>weewx</code> et celle de <code>mariadb</code>. Ces éléments de configuration ne sont pas génériques et doivent être réalisés en fonction des besoins de chaque usager. On pourra notamment :</p>
<ul>
<li>créer un nouvel utilisateur pour les données issues du <code>collège1</code> (user_college1)</li>
<li>créer une nouvelle base de données dédiée au<code>collège1</code> (OpenMetEdu_College1)</li>
<li>donner tous les privilèges au nouvel utilisateur sur la nouvelle base</li>
<li>vérifier que weewx est configuré avec ces mêmes paramètres</li>
</ul>
<p>En fonctionnement sur une base locale weewx requiert une base <code>sqlite3</code> opérationnelle, les paquets sont installés par défaut mais il faut configurer la base en lançant weewx avec la configuration <code>weewx_binding</code> avant de lancer le dispositif opérationnel avec la base mariadb locale <code>wx_mariadblocal_binding</code>.</p>
<h3><a name="head6.6.5"> </a> 6.6.5 Mise en place d'un serveur web</h3>
<p>Nous allons utiliser la base de données locale mariadb installée ci dessus et les outils proposés par le site météo Villarzel. Le site web est installé dans le répertoire /opt/WeatherWeb. Le fichier à configurer est /opt/WeatherWeb/mysql_connect.php</p>
<div class="highlight"><pre><span></span>sudo mkdir /opt/WeatherWeb
sudo nano /opt/WeatherWeb/mysqli_connect.php
</pre></div>
<p>Le fichier est de la forme suivante en remplaçant les <strong>*</strong> par les valeurs correspondant à votre situation :</p>
<div class="highlight"><pre><span></span><?php
<span class="nv">$server</span> <span class="o">=</span><span class="s2">"localhost:********"</span><span class="p">;</span>
<span class="nv">$user</span><span class="o">=</span><span class="s2">"**********"</span><span class="p">;</span>
<span class="nv">$pass</span><span class="o">=</span><span class="s2">"***********"</span><span class="p">;</span>
<span class="nv">$db</span><span class="o">=</span><span class="s2">"******************"</span><span class="p">;</span>
mysql_connect<span class="o">(</span><span class="nv">$server</span>,<span class="nv">$user</span>,<span class="nv">$pass</span><span class="o">)</span> or die <span class="o">(</span><span class="s2">"Erreur SQL : "</span>.mysql_error<span class="o">()</span> <span class="o">)</span><span class="p">;</span>
mysql_select_db<span class="o">(</span><span class="nv">$db</span><span class="o">)</span> or die <span class="o">(</span><span class="s2">"Erreur SQL : "</span>.mysql_error<span class="o">()</span> <span class="o">)</span><span class="p">;</span>
?>
</pre></div>
<p>Il est aussi nécessaire de configurer le serveur web nginx installé par défaut en éditant le fichier <code>/etc/nginx/sites-available/meteoRaspWife3</code>.</p>
<div class="highlight"><pre><span></span>sudo nano /etc/nginx/sites-available/meteoRaspWife3
</pre></div>
<p>Le contenu du fichier doit être du type :</p>
<div class="highlight"><pre><span></span>server <span class="o">{</span>
listen <span class="m">80</span> default_server<span class="p">;</span>
listen <span class="o">[</span>::<span class="o">]</span>:80 default_server<span class="p">;</span>
root /opt/WeatherWeb/<span class="p">;</span>
index index.html index.htm index.php<span class="p">;</span>
server_name _<span class="p">;</span>
location / <span class="o">{</span>
try_files <span class="nv">$uri</span> <span class="nv">$uri</span>/ /index.html<span class="p">;</span>
<span class="o">}</span>
location ~ <span class="se">\.</span>php$ <span class="o">{</span>
fastcgi_split_path_info ^<span class="o">(</span>.+<span class="se">\.</span>php<span class="o">)(</span>/.+<span class="o">)</span>$<span class="p">;</span>
<span class="c1"># With php7-fpm:</span>
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock<span class="p">;</span>
fastcgi_index index.php<span class="p">;</span>
include fastcgi_params<span class="p">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>Pour terminer modifier le fichier de configuration par défaut du serveur web nginx.</p>
<div class="highlight"><pre><span></span>sudo rm /etc/nginx/sites-enabled/default
sudo ln -s /etc/nginx/sites-available/meteoRaspWife3 /etc/nginx/sites-enabled/
</pre></div>
<h2><a name="head7"> </a> 7. Configuration personnalisée de la Raspberry Pi par site</h2>
<p>Changement du port ssh et suppression du login par mot de passe (après avoir vérifié le fonctionnement du login par clef ssh) modifier le fichier <code>sshd_config</code>.</p>
<div class="highlight"><pre><span></span>sudo jed /etc/ssh/sshd_config
<span class="nv">Port</span><span class="o">=</span>******
.../...
PasswordAuthentication no
</pre></div>
<p>Modification de l'aspect de l'invite de commandes et alias de base pour <code>root</code> afin de retrouver un comportement identique à la console utilisateur et afficher en rouge l'invite lorsqu'on passe en mode administration.</p>
<div class="highlight"><pre><span></span>sudo su
<span class="nb">cd</span>
jed .bashrc
<span class="c1"># PS1='${debian_chroot:+($debian_chroot)}\h:\w\$ '</span>
<span class="nv">PS1</span><span class="o">=</span><span class="s1">'${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\u\[\033[00m\][\w]\[\033[01;31m\]\h.$</span>
<span class="s1"># umask 022</span>
<span class="s1"># You may uncomment the following lines if you want `ls'</span> to be colorized:
<span class="nb">export</span> <span class="nv">LS_OPTIONS</span><span class="o">=</span><span class="s1">'--color=auto'</span>
<span class="nb">eval</span> <span class="s2">"</span><span class="k">$(</span>dircolors<span class="k">)</span><span class="s2">"</span>
<span class="nb">alias</span> <span class="nv">ls</span><span class="o">=</span><span class="s1">'ls $LS_OPTIONS'</span>
<span class="nb">alias</span> <span class="nv">ll</span><span class="o">=</span><span class="s1">'ls $LS_OPTIONS -l'</span>
<span class="nb">alias</span> <span class="nv">la</span><span class="o">=</span><span class="s1">'ls $LS_OPTIONS -lA'</span>
<span class="c1">#</span>
</pre></div>
<h2><a name="head8"> </a> 8. Propagation des images par clonage</h2>
<h2><a name="head8.1"> </a> 8.1. Changement des noms et des paramètres locaux</h2>
<p>Dans le cadre du réseau météo il est nécessaire de nommer le système d'exploitation en fonction de l'établissement où il doit être installé. Les modifications suivantes doivent être effectuées. Le nom par défaut est <code>raspi3W</code> il est nécessaire de changer son nom dans les fichiers suivants pour obtenir un changement opérationnel du nom de la machine.</p>
<ul>
<li>Mise à jour des fichiers de nommage <code>/etc/hosts</code> et <code>/etc/hostname</code></li>
<li>Mise à jour des fichiers de gestion du réseau <code>50-wired.network</code> et <code>51-wired.network</code></li>
<li>Mise à jour du pare-feu <code>/etc/nftables.conf</code></li>
<li>Mise à jour du fichier de configuration de <code>weewx</code></li>
<li>Changement des mots de passe</li>
</ul>
<div class="highlight"><pre><span></span>sudo jed /etc/hosts
sudo jed /etc/hostname
sudo jed /etc/systemd/network/50-wired.network <span class="c1"># ou 50-wired.network-std</span>
sudo jed /etc/systemd/network/51-wired.network <span class="c1"># ou 51-wired.network-rescue</span>
sudo jed /etc/nftables.conf
sudo jed /etc/weewx/weewx.conf
</pre></div>
<h2><a name="head8.2"> </a> 8.2. Copie et conversion</h2>
<p>Une fois que tous les programmes souhaités sont ajoutés et toutes les options configurées les images peuvent être diffusées sous forme binaire compressée, il suffit alors à tout usager qui souhaite se les approprier de téchager le fichier et le copier sur une micro-SD qui sera immédiatement opérationnelle. Éteindre la Raspberry pi et extraire la micro-SD puis l'insérer dans un ordinateur (dans le cas ci-dessous elle apparaît sur le device <code>/dev/mmcblk0</code>. Copier "bit à bit" le contenu de la micro-SD sur le disque dur de l'ordinateur avec les options de maîtrise des espaces vides et le contrôle de la taille; l'image proposée dans ce blog pouvant contenir dans une micro-SD de 8Go. Le nom de l'image utilise les règles de nommage utilisées au <a href="#head1.3">chap 1.C</a>. Pour faciliter la copie de l'image on propose de créer le fichier bmap correspondant et de la compresser (le logiciel bmaptools traite directement les images compressées ce qui minimise les temps de téléchargement et évite le temps de décompression)</p>
<div class="highlight"><pre><span></span>sudo dd <span class="k">if</span><span class="o">=</span>/dev/mmcblk0 <span class="nv">of</span><span class="o">=</span><span class="m">2018</span>-01-07-rpi3-stretch.img <span class="nv">bs</span><span class="o">=</span>4M <span class="nv">conv</span><span class="o">=</span>sparse <span class="nv">count</span><span class="o">=</span><span class="m">2500</span>
bmaptool create -o <span class="m">2018</span>-01-07-rpi3-stretch.bmap <span class="m">2018</span>-01-07-rpi3-stretch.img
7z a -txz <span class="m">2018</span>-01-07-rpi3-stretch.img.xz <span class="m">2018</span>-01-07-rpi3-stretch.img
</pre></div>
<p>Les usagers devront télécharger les deux fichiers <code>2018-01-07-rpi3-stretch.img.xz</code> et <code>2018-01-07-rpi3-stretch.bmap</code> et utiliser ensuite bmaptool pour la recopier sur une micro-SD vierge :</p>
<div class="highlight"><pre><span></span>sudo bmaptool copy --bmap <span class="m">2018</span>-01-07-rpi3-stretch.bmap <span class="m">2018</span>-01-07-rpi3-stretch.img.xz /dev/mmcblk0
</pre></div>
<p>Une fois la copie terminée la micro-SD est immédiatement opérationnelle.</p>
<hr>
<h3><em>Webographie</em></h3>
<ol>
<li><a href="https://www.raspberrypi.org">Site principal Raspberry Pi</a></li>
<li><a href="https://github.com/drtyhlpr/rpi23-gen-image.git">Scripts de création de l'image</a> </li>
<li><a href="https://www.debian.org/CD/live/">Image Debian Live</a></li>
<li><a href="https://www.debian.org/CD/faq/#write-usb">Comment créer une clef USB bootable Debian</a></li>
<li><a href="https://jeffhoogland.blogspot.com/2012/05/howto-give-network-manager-sufficient.html">nmcli authorization management</a></li>
<li><a href="https://www.thegeekdiary.com/how-to-configure-and-manage-network-connections-using-nmcli/">nmcli examples</a></li>
<li><a href="https://shapeshed.com/linux-wifi/">wpa_cli configuration</a></li>
</ol>Installer python, jupyterlab et pipenv dans une machine windows2021-02-24T19:40:00+01:002021-02-24T19:40:00+01:00Gérard Vidaltag:blog.tremplin.ens-lyon.fr,2021-02-24:/GerardVidal/pythonJup-Win10.html<p>Cet article décrit la méthode permettant d'installer et de faire fonctionner convenablement un OS Windows10 à l'intérieur d'une machine virtuelle Qemu-KVM.</p><p><strong><em>Motivations</em></strong></p>
<p>Jupyterlab est un outil extrêmement puissant et versatile pour traiter des données ou des questions nécessitant l'utilisation de code <code>python</code>. Son installation est aisée avec <code>pipenv</code> dans les machines <code>linux</code>. Ce court tutorial explique comment installer <code>python</code>, <code>pipenv</code> et <code>jupyterlab</code> dans une machine windows. le seul inconvénient est qyue ce système d'exploitation est incapable de détecter une application externe et il est nécessaire de passer par le powershell pour installer puis lancer jupyterlab.
Ce tutoriel à été réalisé pour les collègues du projet OpenScience n'utilisant pas <code>linux</code>.</p>
<hr>
<h3><em>Sommaire</em></h3>
<ol>
<li>
<p><a href="#head1">Environnement dépendances et téléchargements</a></p>
<p>1.1 <a href="#head1.1">Installation de python</a> </p>
<p>1.2 <a href="#head1.2">Installation de pipenv et <code>jupyterlab</code></a></p>
<p>1.3 <a href="#head1.3">Modules complémentaires en fonction du projet</a></p>
</li>
<li>
<p><a href="#head2"> Lancement de jupyterlab</a></p>
<p>2.1 <a href="#head2.1">Quelques tests simples</a></p>
<p>2.2 <a href="#head2.2">Graphes avec <code>plotly</code> (anomalie de version)</a></p>
</li>
</ol>
<hr>
<h3><em>Téléchargements</em></h3>
<p>1; <a href="https://www.python.org/downloads/">python depuis le site python</a></p>
<h1><a name="head1"></a>1. Environnement dépendances et téléchargements</h1>
<p>L'installation a été réalisée sur une machine virtuelle <em>windows</em> <code>QEMU-KVM</code> à l'intérieur d'un ordinateur fonctionnant sous <code>debian testing (bullseye)</code>. Le comportement est celui d'une machine <em>windows</em> ordinaire et ce tutoriel a aussi été testé avec succès dans une configuration "ordinaire". Comme il est maintenant possible de disposer d'un linux complet (plusieurs distributions proposées) à l'intérieur d'un windows en affichant l'écran via le serveur de terminaux par défaut de windows, on peut aussi utiliser cette solution. Toutefois ce mode de fonctionnement n'est pas encore très répandue et l'installation proposée ici s'applique à toute machine <em>windows</em> à jour. </p>
<p>Dans ce qui suit pour ne pas alourdir ni dater le texte nous avons utilisé <code>python</code> sans préciser le numéro de la version qui est fourni par défaut dans le nom, utilisez le nom complet de la version que vous téléchargerez (python3 obligatoire !).</p>
<h2><a name="head1.1"></a>1.1 Installation de python</h2>
<p>Télécharger l'installateur <code>python</code> depuis le site <a href="https://www.python.org/downloads/">python</a> et l'installer avec la procédure habituelle d'installation de logiciels, bien penser à cocher la case permettant d'inclure python dans le <code>PATH</code>, l'option finale permettant de contourner une des limitations de windows peut s'avérer aussi utile.</p>
<p>Vous disposez maintenant d'une part de 4 exécutables :
* une console vous donnant directement accès à l' exécution de code python
* une interface de programmation et débugging extrêmement sommaire (il existe d'autres outils libres plus performants si besoin)
* une documentation interactive
* une document sur les modules complémentaires</p>
<p>Ces exécutable sont directement accessibles directement depuis le menu des programmes.</p>
<p>D'autre part tous les outils de base python sont disponibles en ligne de commande dans le <code>powershell</code>; par exemple en tapant <code>python</code> dans un <code>powershell</code> vous ouvrez une console python ce qui est absolument équivalent à lancer depuis le menu l'exécutable <code>python</code>. Nous allons utiliser les commandes de base à l'intérieur d'un <code>powershell</code></p>
<h2><a name="head1.2"></a>1.2 Installation de pipenv et <code>jupyterlab</code></h2>
<p>Une des fonctionnalités de python est de pouvoir s'exécuter dans un "environnement virtuel" c'est à dire que pour éviter de mélanger les modules particuliers ajoutés à <code>python</code> pour un projet précis avec les modules communs appliqués à tout le système on crée un lieu fermé dans lequel on installe les modules qui s'exécutent "comme dans le système de base" mais qui ne peuvent s'exécuter que dans ce lieu fermé. On parle d'environnement "virtuel" car il ne s'agit pas d'un dossier physique du système mais d'une sorte de "couche" parallèle au système donnant accès à tous les espaces réels comme si on était l'environnement ordinaire... avec des programmes <code>python</code> en plus!</p>
<p>On va utiliser l'outil d'installation <code>pip</code> en ligne de commande puis l'outil <code>pipenv</code> une fis qu'il sera installé. <code>pipenv</code> crée l'espace virtuel lors de son premier lancement et le gère ensuite en maintenant toujours les dépendances de <code>python</code> en état opérationnel.</p>
<ul>
<li>ouvrir une console <code>powershell</code></li>
<li>installer pipenv : <code>pip install pipenv</code></li>
<li>créer un répertoire dans lequel seront stockés les paramètres de l'environnement virtuel dans lequel on va travailler <code>OpenScience-jup</code> pour le jupyter d'Openscience avec la commande <code>mkdir OpenScience-jup</code> pour notre exemple <em>remplacer <code>OpenScience-jup</code> par le nom qui vous convient</em>.</li>
<li>aller dans le nouveau répertoire créé <code>cd OpenScience-jup</code></li>
<li>installer <code>jupyterlab</code> dans un environnement virtuel (toutes les dépendances du logiciel <code>Jupyterlab</code> seront automatiquement installées) avec la commande <code>pipenv install jupyterlab</code> </li>
</ul>
<p>Du fait du téléchargement de plusieurs dépendances cette opération peut prendre quelques minutes</p>
<h2><a name="head1.3"></a>1.3 Modules complémentaires en fonction du projet</h2>
<p>On utilise pour ce projet quelques modules de traitement et d'affichage de métadonnées ainsi que les modules permettant l'export en pdf des <code>notebooks</code> :</p>
<div class="highlight"><pre><span></span>pipenv install jupyterlab kotlin-jupyter-kernel rdflib pydotplus graphviz requests nbconvert jupyter_contrib_nbextensions
</pre></div>
<p>Jupyterlab est extrêmement versatile et abondamment utilisé, il existe pléthore d'extensions parfois redondantes avec des options différentes choiies par les développeurs. On peut directement ajouter ces extensions depuis le menu de gauche de <code>Jupyterlab</code> mais cette fonctionnalité est récente (apparue en 3.0) et il peut subsister certains problèmes en général bien documentés sur <code>github</code> au cas où vous les renconteriez. Il est possible de rajouter des extensions pour écrire du java, du scala, du latex, du C, etc... Ces extensions ne sont pas abordées ici (l'extension java est traitée dans le tutorial pour les <a href="">raspberriesPi</a>)</p>
<h1><a name="head2"></a>2. Lancement de jupyterlab</h1>
<p>Jupyter lab est une application web qui va apparaître dans votre navigateur <strong>mais</strong> elle doit être lancée depuis une ligne de commande du <code>powershell</code> windows ne reconnaissant pas tout seul les applications <code>python</code> comme des applications à part entière.</p>
<ul>
<li>aller dans le nouveau répertoire créé <code>cd OpenScience-jup</code></li>
<li>entrer dans l'environnement virtuel avec <code>pipenv shell</code> vous retrouvez une interface de commande <code>powershell</code> ordinaire</li>
<li>lancer <code>Jupyterlab</code> avec <code>jupyter lab</code> au premier lancement jupyter demande de choisir un navigateur ensuite c'est automatique</li>
<li>pour quitter l'environnement virtuel taper <code>exit</code> cela renvoie dans le <code>powershell</code> ordinaire</li>
</ul>
<p>L'entrée dans l'environnement virtuel se fait <strong>obligatoirement</strong> depuis le répertoire d'ancrage créé lors de l'installation de l'environnement virtuel (plusieurs environnements virtuels pouvant cohabiter sur des dossiers d'ancrage différents). Le lancement peut se faire depuis <em>n'importe quel répertoire</em> qui deviendra le répertoire de référence de la session <code>Jupyterlab</code> lancée. Une facçon simple de démarrer est de copier dans <code>OpenScience-jup</code> un fichier avec l'extension <code>.ipynb</code> (notebook jupyter) depuis un des sites spécialisés par exemple <a href="https://nbviewer.jupyter.org/">nbviewer</a>.</p>
<h2><a name="head2.1"></a>2.1. Quelques tests simples</h2>
<p>Si vous voulez directement tester vos aptitudes de programmation en <code>python</code> ouvrez un cahier (notebook) <code>python3</code> copiez le texte suivant</p>
<div class="highlight"><pre><span></span><span class="k">print</span> <span class="p">(</span><span class="s1">'Coucou le monde'</span><span class="p">)</span>
</pre></div>
<p>cliquez sur la flèche d'exécution dans la barre de commandes de votre cahier, la commande s'exécute et imprime <em>Coucou le monde</em> . Vous venez d'écrire et d'exécuter avec succès votre premier programme <code>python</code>.</p>
<p>Un peu plus compliqué : installer <code>lightning-python</code> avec <code>pipenv</code> puis lancer <code>jupyterlab</code> et ajouter dans un cahier <code>python3</code> le code suivant dans des blocs différents :</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">lightning</span> <span class="kn">import</span> <span class="n">Lightning</span>
<span class="kn">from</span> <span class="nn">numpy</span> <span class="kn">import</span> <span class="n">random</span>
<span class="c1">#------------------------</span>
<span class="n">lgn</span> <span class="o">=</span> <span class="n">Lightning</span><span class="p">(</span><span class="n">ipython</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">local</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">series</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">50</span><span class="p">)</span>
<span class="n">lgn</span><span class="o">.</span><span class="n">line</span><span class="p">(</span><span class="n">series</span><span class="p">)</span>
<span class="c1">#--------------------------</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span>
<span class="n">lgn</span><span class="o">.</span><span class="n">scatter</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">values</span><span class="o">=</span><span class="n">v</span><span class="p">,</span> <span class="n">colormap</span><span class="o">=</span><span class="s1">'Reds'</span><span class="p">)</span>
<span class="c1">#----------------------------------------</span>
<span class="n">mat</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">rand</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">100</span><span class="p">)</span>
<span class="n">mat</span><span class="p">[</span><span class="n">mat</span><span class="o"><</span><span class="mf">0.97</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">lgn</span><span class="o">.</span><span class="n">force</span><span class="p">(</span><span class="n">mat</span><span class="p">)</span>
</pre></div>
<p>Cela vous donne un exemple de dessins simples.</p>
<h2><a name="head2.2"></a>2.2. Graphes avec <code>plotly</code> (anomalie de version)</h2>
<p>La limite de version imposée pour <code>jupyterlab</code> est trp basse; créer un répertoire cloner la version actuelle de <code>plotly.py</code> et aller dans le rertoire <code>jupyterlab-plotly</code> modifier sa valeur.</p>
<div class="highlight"><pre><span></span>mkdir Plotly
<span class="nb">cd</span> Plotly
git clone https://github.com/plotly/plotly.py.git
<span class="nb">cd</span> /home/vidal/Jupyter/JupVirtEnv/Plotly/plotly.py/packages/javascript/jupyterlab-plotly
</pre></div>
<p>Modifier les limites de version pour accepter la version de jupyterlab utilisée <code>"@jupyterlab/rendermime-interfaces": "^1.3.0 || ^2.0.0 || ^3.1.0"</code> puis construire et installer le paquet</p>
<div class="highlight"><pre><span></span>npm install
npm run build
jupyter labextension install
</pre></div>
<hr>
<h3><em>Webographie</em></h3>
<ol>
<li><a href="https://www.python.org">python</a></li>
<li><a href="https://pypi.org/">Modules complémentaires python</a></li>
<li><a href="http://jupyterlab.io/">jupyterlab</a></li>
<li><a href="https://nbviewer.jupyter.org/">nbviewer</a></li>
</ol>Concevoir et construire une infrastructure numérique souveraine distribuée dans le réseau d'établissements.2020-09-07T10:38:00+02:002020-09-07T10:38:00+02:00Gérard Vidaltag:blog.tremplin.ens-lyon.fr,2020-09-07:/GerardVidal/concevoir-et-construire-une-infrastructure-numerique-souveraine-distribuee-dans-le-reseau-detablissements.html<p>Constat sur la situation actuelle du numérique éducatif et sur une cause probable d'une famille de dysfonctionnements et proposition d'une reconstruction globale du système selon un paradigme d'infrastructure souveraine distribuée</p><p><strong><em>Motivations</em></strong></p>
<p>Le format d'une contribution aux états généraux du numérique est limitée à 2000 caractères, ma <a href="https://etats-generaux-du-numerique.education.gouv.fr/processes/numerique-souverain/f/24/proposals/446">contribution sur la souveraineté</a> est un fragment légèrement modifié du texte publié ici dans son intégralité. Il est le résultat de plusieurs décennies d'observation et d'actions auprès des enseignants.</p>
<h3><em>Remerciements</em></h3>
<p>Sincères remerciements à toute l'équipe de Tremplin des sciences et du volet français de Nextlab-Graasp qui ont relu et modéré mes propos, Carole, Myriam Éric Charles-henri.</p>
<hr>
<h3><em>Sommaire</em></h3>
<ol>
<li>
<p><a href="#head1">Un constat</a></p>
</li>
<li>
<p><a href="#head2">Que faire ?</a></p>
</li>
</ol>
<h1><a name="head1">1. </a>Un constat.</h1>
<p>Quelle que soit notre implication dans le numérique, nous sommes en permanence exposés à et conditionnés par des modèles issus de l'industrie du numérique "grand public". Ces derniers sont conçus pour servir des stratégies commerciales ou économiques et non pour satisfaire en priorité des objectifs éducatifs. Certes le besoin éducatif est pris en compte mais il reste logiquement subrogé par la contrainte économique que subissent les entreprises commerciales. Notre esprit critique sur le numérique s'est émoussé, toute la curiosité et la soif d'innovantion des premiers moments du numérique éducatif s'est peu à peu échouée sur les hauts fond du manque de soutien et de formation ou sur les écueils techniques érigés par les fournisseurs. </p>
<p>Ces états généraux doivent être l'occasion d'une remise en question profonde de l'adéquation entre les infrastructures numériques grand-public "reconditionnées (ou pas)" pour l'éducation et les besoins du système éducatif. Même si l'offre des acteurs majeurs est "déclinée pour l'éducation", la logique est bien celle d'une modification aux limites de dispositifs rentables déjà existants conçus pour une autre cible, afin qu'ils satisfassent le moins mal possible les besoins des enseignants souvent incomplètement exprimés ou mal interprétés.</p>
<p>Pourquoi uniformiser les pratiques en imposant des plateformes centralisées, contraignantes et intrinsèquement incompatibles entre elles afin que chaque fournisseur puisse protéger sa part de marché ? Il est toutefois logique que l'administration centrale au niveau ministériel et académique ait recours au moins partiellement à une stratégie centralisée de ce type du fait de son organisation et de son fonctionnement, l'utilisation d'un nombre limité de plateformes et de services unifiés y compris dans le cloud semble réellement incontournable. Mais lorsqu'on aborde les établissements le problème est fondamentalement différent : l'établissement a une réalité physique, territoriale et de proximité, les enseignants et tous les usagers s'approprient leur établissement, il en découle une forme d'identité partagée et d'appartenance à un groupe qui se différencie de ses homologues. La part d'affectivité liée à cette revendication d'identité commune cimente et stimule les actions locales pédagogiques, éducatives et citoyennes. </p>
<p>Dans la situation actuelle les univers numériques organisent une situation opposée en anonymisant l'établissement dand des dispositifs normalisés dans le plus mauvais sens du terme. L'enseignant et sa pédagogie, l'élève et même la famille disparaissent dessière des logins dans des applications uniformisées. Les services sont volontairement imbriqués entre eux et indissociables de l'infrastructure, les diverses contraintes centralisées y compris de sécurité s'empilent les unes aux autres jusqu'à donner le sentiment aux élèves que le numérique de leur établissement n'est qu'un ersatz dégradé et démodé de ce qu'ils ont au fond de leur poche.</p>
<h1><a name="head1">2. </a>Que faire ?</h1>
<p>Les établissements forment dans chaque académie et dans le pays un réseau que l'on peut percevoir comme un maillage relativement régulier en fonction de la densité de population. Chaque établissement au nœud de cette grille pourrait devenir un nœud de ressource numérique distribuée, mutualisable dès lors qu'au lieu d'imposer un logiciel ou un service on impose l'interopérabilité des protocoles et des formats via des standards ouverts internationaux. En installant dans chaque établissement les serveurs qui lui sont nécessaires les collectivités territoriales exercent leur autonomie et mettent à la disposition de l'éducation nationale un "cloud souverain" et participatif. On attend d'un tel dispositif tous les avantages d'un cloud commercial en ajoutant les avantages suivants :
- l'appropriation de l'univers numérique au même titre que l'univers physique par tous les usagers de l'établissement
- la liberté de choix pédagogique des logiciels et des services sous la condition expresse qu'ils respectent des standards internationaux et des règles strictes d'interopérabilité.
- une liberté de collaboration accrue au sein de l'établissement (choix logiciels concertés et interdisciplinaires) et en inter-établissements sans contrainte de limite administrative ou territoriale du fait de l'interopérabilité
-l'accompagnement local et territorial d'une meilleure acculturation numérique.</p>
<p>Une telle stratégie n'est pas utopique, elle repose sur une redistribution des coûts d'exploitation des plateformes centralisées vers l'équipement des établissements et la prise en compte du temps de travail nécessaire à maintenir "l'établissement numérique" en conditions opérationnelles. Elle impose aussi une action de formation en profondeur pour accompagner les enseignants dans une métamorphose de leur statut actuel de consommateurs à celui d'experts de leur numérique. La logique d'établissement apprenant fait l'objet de recherches, il est temps d'envisager que l'établissement apprenant est aussi numérique dans les limites de son autonomie et de sa souveraineté.</p>Installer et régler une machine virtuelle Windows10 avec Qemu-KVM dand un linux2020-05-17T16:27:00+02:002021-02-24T19:40:00+01:00Gérard Vidaltag:blog.tremplin.ens-lyon.fr,2020-05-17:/GerardVidal/qemuKVM-Win10.html<p>Cet article décrit la méthode permettant d'installer et de faire fonctionner convenablement un OS Windows10 à l'intérieur d'une machine virtuelle Qemu-KVM.</p><p><strong><em>Motivations</em></strong></p>
<p>Cette migration vers Qemu-KVM a été entreprise du fait de la conjonction de trois événements :
* l'apparition de sérieux problèmes d'installation des mises à jour du logiciel Virtualbox en version testing de debian ayant rendu la machine virtuelle Windows 7 indisponible
* le caractère obsolète de windows7 et le nécessaire passage à windows10
* le fait que la multiplication des usages des Raspberies Pi imposait une façon plus efficace de compiler les logiciels embarqués que sur une instance dédiée de RaspberryPi.</p>
<p>Cette migration s'est révélée plus difficile que prévu !</p>
<hr>
<h3><em>Sommaire</em></h3>
<ol>
<li>
<p><a href="#head1">Environnement dépendances et téléchargements</a></p>
<p>a. <a href="#head1.1">ISO windows10</a> </p>
<p>b. <a href="#head1.2">Vérification de la configuration hardware</a></p>
<p>c. <a href="#head1.3">Installation des paquets nécessaires</a></p>
</li>
<li>
<p><a href="#head2">Création de la machine virtuelle et installation de windows10</a></p>
<p>a. <a href="#head2.1">Configuration standard de virt-manager</a></p>
<p>b. <a href="#head2.2">Configuration particulière de virt-manager</a></p>
<p>c. <a href="#head2.3">En cas d'utilisation de disque externe</a></p>
</li>
<li>
<p><a href="#head3">Mise en production</a></p>
</li>
</ol>
<hr>
<h3><em>Téléchargements</em></h3>
<ol>
<li><a href="https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.171-1/virtio-win-0.1.171.iso">Logiciels VirtIO</a></li>
</ol>
<h1><a name="head1"></a>1. Environnement dépendances et téléchargements</h1>
<p>L'installation a été réalisée et testée sur une machine <code>debian testing (bullseye]</code> équipée d'une cartegraphique <code>nvidia</code>.</p>
<h2><a name="head1.1"></a>1.1 ISO windows10</h2>
<p>Il est nécessaire disposer d'une <code>licence VDA</code> de <code>windows10</code> pour pouvoir l'installer dans une machine virtuelle. Cette licence particulière pour machines virtuelle dispose d'une documentation concernant exclusivement l'utilisation des solutions propriétaires du vendeur et il faut trouver le support Qemu-KVM ailleurs. L'<code>image ISO</code> qui m'a été fournie propose plusieurs installations possibles, il est bien sûr crucial de choisir l'installation qui correspond au code qui vous a été fourni. En ce qui me concerne la désignation du code qui m'avait été fourni n'avait rien à voir avec aucun des noms d'installations proposés, je suis passé par le support pour obtenir le nom de l'installation à utiliser.</p>
<p>Vous devez disposer d'une image iso du type <code>X##-$$$$$.ISO</code></p>
<h2><a name="head1.2"></a>1.2 Vérification de la configuration hardware</h2>
<p>Pour installer la virtualisation il est nécessaire que ces fonctions aient été activées depuis le BIOS. Afin de vérifier plusieurs solutions sont possibles.</p>
<h3>La plus simple</h3>
<p>Utiliser la commande <code>lscpu</code> et vérifier que la ligne "Virtualisation contient une information, par exemple :</p>
<div class="highlight"><pre><span></span>Virtualisation : VT-x
</pre></div>
<h3>La plus aboutie</h3>
<p>Installer le paquet <code>libvirt-clients</code> et utiliser la commande de validation de l'hote.</p>
<div class="highlight"><pre><span></span>sudo apt install libvirt-clients
<span class="o">[</span>sudo<span class="o">]</span> Mot de passe de <span class="c1">######## : </span>
Lecture des listes de paquets... Fait
Construction de l<span class="s1">'arbre des dépendances </span>
<span class="s1">Lecture des informations d'</span>état... Fait
Les paquets suivants ont été installés automatiquement et ne sont plus nécessaires :
cpp-7 lib32asan4 lib32gcc-7-dev libasan4 libx32asan4 libx32gcc-7-dev libx86emu2
Veuillez utiliser « sudo apt autoremove » pour les supprimer.
Les paquets supplémentaires suivants seront installés :
dmeventd libdevmapper-event1.02.1 liblvm2cmd2.03 libvirt0 lvm2 thin-provisioning-tools
Paquets suggérés :
libvirt-daemon
Les NOUVEAUX paquets suivants seront installés :
dmeventd libdevmapper-event1.02.1 liblvm2cmd2.03 libvirt-clients libvirt0 lvm2 thin-provisioning-tools
<span class="m">0</span> mis à jour, <span class="m">7</span> nouvellement installés, <span class="m">0</span> à enlever et <span class="m">0</span> non mis à jour.
Il est nécessaire de prendre <span class="m">6</span> 447 ko dans les archives.
Après cette opération, <span class="m">33</span>,0 Mo d<span class="s1">'espace disque supplémentaires seront utilisés.</span>
<span class="s1">.../...</span>
<span class="s1">virt-host-validate</span>
<span class="s1"> QEMU : Vérification for hardware virtualization : PASS</span>
<span class="s1"> QEMU : Vérification if device /dev/kvm exists : PASS</span>
<span class="s1"> QEMU : Vérification if device /dev/kvm is accessible : PASS</span>
<span class="s1"> QEMU : Vérification if device /dev/vhost-net exists : PASS</span>
<span class="s1"> QEMU : Vérification if device /dev/net/tun exists : PASS</span>
<span class="s1"> QEMU : Vérification for cgroup '</span>cpu<span class="s1">' controller support : PASS</span>
<span class="s1"> QEMU : Vérification for cgroup '</span>cpuacct<span class="s1">' controller support : PASS</span>
<span class="s1"> QEMU : Vérification for cgroup '</span>cpuset<span class="s1">' controller support : PASS</span>
<span class="s1"> QEMU : Vérification for cgroup '</span>memory<span class="s1">' controller support : PASS</span>
<span class="s1"> QEMU : Vérification for cgroup '</span>devices<span class="s1">' controller support : PASS</span>
<span class="s1"> QEMU : Vérification for cgroup '</span>blkio<span class="s1">' controller support : PASS</span>
<span class="s1"> QEMU : Vérification for device assignment IOMMU support : PASS</span>
<span class="s1"> QEMU : Vérification if IOMMU is enabled by kernel : PASS</span>
<span class="s1"> LXC : Vérification pour Linux >= 2.6.26 : PASS</span>
<span class="s1"> LXC : Vérification for namespace ipc : PASS</span>
<span class="s1"> LXC : Vérification for namespace mnt : PASS</span>
<span class="s1"> LXC : Vérification for namespace pid : PASS</span>
<span class="s1"> LXC : Vérification for namespace uts : PASS</span>
<span class="s1"> LXC : Vérification for namespace net : PASS</span>
<span class="s1"> LXC : Vérification for namespace user : PASS</span>
<span class="s1"> LXC : Vérification for cgroup '</span>cpu<span class="s1">' controller support : PASS</span>
<span class="s1"> LXC : Vérification for cgroup '</span>cpuacct<span class="s1">' controller support : PASS</span>
<span class="s1"> LXC : Vérification for cgroup '</span>cpuset<span class="s1">' controller support : PASS</span>
<span class="s1"> LXC : Vérification for cgroup '</span>memory<span class="s1">' controller support : PASS</span>
<span class="s1"> LXC : Vérification for cgroup '</span>devices<span class="s1">' controller support : PASS</span>
<span class="s1"> LXC : Vérification for cgroup '</span>freezer<span class="s1">' controller support : PASS</span>
<span class="s1"> LXC : Vérification for cgroup '</span>blkio<span class="err">'</span> controller support : PASS
LXC : Vérification <span class="k">if</span> device /sys/fs/fuse/connections exists : PASS
</pre></div>
<p>D'autres solutions et explications sont disponibles sur <a href="https://vitux.com/how-to-check-if-your-processor-supports-virtualization-technology/">Test des cpu</a></p>
<h2><a name="head1.3"></a>1.3 Installation des paquets nécessaires</h2>
<p>Il est possible de construire des images "à la main" en composant soi même la commande <code>qemu</code> qui créera la machine virtuelle mais il est plus simple d'utiliser l'interface graphique de <code>virt-manager</code> qui s'appuie sut la librairie <code>libvirt</code>. Fette stratégie facilite la configuration mais impose un certain nombre de choix compatibles avec l'usage moyen, pour des utilisations particulières prévoir une autre stratégie.</p>
<div class="highlight"><pre><span></span>sudo apt install qemu-kvm virt-manager libvirt-daemon
<span class="o">[</span>sudo<span class="o">]</span> Mot de passe de vidal :
Lecture des listes de paquets... Fait
Construction de l<span class="s1">'arbre des dépendances </span>
<span class="s1">Lecture des informations d'</span>état... Fait
Les paquets supplémentaires suivants seront installés :
augeas-lenses gir1.2-gtk-vnc-2.0 gir1.2-libosinfo-1.0 gir1.2-libvirt-glib-1.0
gir1.2-spiceclientglib-2.0 gir1.2-spiceclientgtk-3.0 libaugeas0 libgovirt-common libgovirt2
libnetcf1 libnss-mymachines libvirt-daemon-driver-lxc libvirt-daemon-driver-qemu
libvirt-daemon-driver-vbox libvirt-daemon-driver-xen libvirt-daemon-system
libvirt-daemon-system-systemd libvirt-glib-1.0-0 libxencall1 libxendevicemodel1
libxenevtchn1 libxenforeignmemory1 libxengnttab1 libxenmisc4.11 libxenstore3.0
libxentoolcore1 libxentoollog1 libxml2-utils netcat-openbsd ovmf python3-libvirt
qemu-system-x86 seabios systemd-container virt-viewer virtinst
Paquets suggérés :
augeas-doc augeas-tools libvirt-daemon-driver-storage-gluster
libvirt-daemon-driver-storage-rbd libvirt-daemon-driver-storage-zfs numad auditd nfs-common
open-iscsi pm-utils radvd systemtap zfsutils samba vde2 qemu-block-extra python3-guestfs
ssh-askpass
Les NOUVEAUX paquets suivants seront installés :
augeas-lenses gir1.2-gtk-vnc-2.0 gir1.2-libosinfo-1.0 gir1.2-libvirt-glib-1.0
gir1.2-spiceclientglib-2.0 gir1.2-spiceclientgtk-3.0 libaugeas0 libgovirt-common libgovirt2
libnetcf1 libnss-mymachines libvirt-daemon libvirt-daemon-driver-lxc
libvirt-daemon-driver-qemu libvirt-daemon-driver-vbox libvirt-daemon-driver-xen
libvirt-daemon-system libvirt-daemon-system-systemd libvirt-glib-1.0-0 libxencall1
libxendevicemodel1 libxenevtchn1 libxenforeignmemory1 libxengnttab1 libxenmisc4.11
libxenstore3.0 libxentoolcore1 libxentoollog1 libxml2-utils netcat-openbsd ovmf
python3-libvirt qemu-kvm qemu-system-x86 seabios systemd-container virt-manager virt-viewer
virtinst
<span class="m">0</span> mis à jour, <span class="m">39</span> nouvellement installés, <span class="m">0</span> à enlever et <span class="m">0</span> non mis à jour.
Il est nécessaire de prendre <span class="m">16</span>,7 Mo dans les archives.
Après cette opération, <span class="m">64</span>,5 Mo d<span class="err">'</span>espace disque supplémentaires seront utilisés.
</pre></div>
<p>Il est aussi nécessaire de télécharger une image contenant les logiciels windows nécessaires à la gestion de la virtualisation depuis le site <code>fedora</code>. </p>
<div class="highlight"><pre><span></span>curl https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.171-1/virtio-win-0.1.171.iso -o virtio-win
</pre></div>
<h1><a name="head2"></a>2. Création de la machine virtuelle et installation de windows10</h1>
<p>On utilise le gestionnaire de machines virtuelles <code>virt-manger</code> connecté au serveur libvirt, suivant les types d'installation les services <code>libvirt*</code> peuvent ne pas être démarrés par défaut, ils sont lancé au premier démarrage de <code>virt-manager</code>.</p>
<h2><a name="head2.1"></a>2.1 Configuration standard de virt-manager</h2>
<p>ajouter le user qui lancera la machine au groupe kvm sinon seul root dispose de ce privilège <code>sudo adduser name kvm</code></p>
<ul>
<li>Lancer virt-manager autoriser la connection au serveur <code>qemu</code> et choisir "créer une nouvelle machinevirtuelle"</li>
<li>Choisir le media d'installation <code>X##-$$$$$.ISO</code> choisir manuellement windows10</li>
<li>Choisir la taille de la mémoire et le nombre de cpus de la machine virtuelle</li>
<li>Sélectionner un stockage personnalisé </li>
<li>Créer une image <strong>au format raw</strong> (impératif pour des raisons de performance</li>
<li>Nommer la nouvelle machine et cocher "personnaliser la configuration avant l'installation"</li>
<li>terminer et activer le réseau virtuel (proposé automatiquement)
Modifier les paramètres avancés du disque dur :</li>
</ul>
<div class="highlight"><pre><span></span>Mode de cache none
mode d<span class="err">'</span>E/S native
</pre></div>
<p>Lancer l'installation.</p>
<p>Avec cette configuration on obtient un client windows10 opérationnel (après un reboot et une phase d'installation classique de windows) mais qui peut être très lent voir même se figer complètement. ce problème n'arrive peut-être pas pour toutes les configurations (ça reste du windows ;-) ), ce n'est pas risqué de tester car l'arrêt forcé fonctionne bien et ne cause pas de dommages à la machine virtuelle qui vient d'être installée. Le chapitre suivant précise les modifications de configuration à effectuer pour éviter cette lenteur si elle apparait.. </p>
<p>Le plus efficace est d'éteindre proprement la machine avant qu'elle ne ralentisse pour procéder aux manipulations suivantes La commande suivante permet de lancer automatiquement le réseau lorsque libvirt démarre.</p>
<div class="highlight"><pre><span></span>virsh net-autostart default
</pre></div>
<h2><a name="head2.2"></a>2.2 Configuration particulière de virt-manager</h2>
<p>Les modifications proposées permettent soit d'éviterle bug de lenteur excessive de windows soit de profiter des avantages de <code>libvirt</code>. Relancer virt-manager, choisir la machine qui vient d'être installée puis <code>ouvrir</code>, cliquer sur l'ampoule afficher les détails puis réaliser les modifications suivantes.</p>
<ul>
<li>Ajouter un lecteur de cd contenant le lien vers la deuxième image téléchargée depuis <code>fedora</code> nommée <code>virtio-win.iso</code> dans cet article.</li>
<li>Ajouter un disque dur au format VirtIO qui permettra de rajouter le driver <code>virtIO</code> dans le client win10</li>
<li>Vérifier et modifier si nécessaire les paramètres avancés des deux disques durs :</li>
</ul>
<div class="highlight"><pre><span></span>Mode de cache none
mode d<span class="err">'</span>E/S native
</pre></div>
<ul>
<li>Dans les préférences du gestionnaire <code>virt-manager</code> autoriser la modification des fichiers XML puis ans l'un des quatre premiers éléments de la liste du matériel choisir l'onglet XML chercher le paramètre <code>machine</code> ajouter <code>kernel_irqchip=on</code></li>
</ul>
<p>Au redémarrage vous devez obtenir une machine windows10 stable (ne ralentissant pas et ne se figeant pas).Le premier travail à réaliser est l'ajout de <code>guest-additions</code>depuis le CD <code>VirtIO</code>. pour cela ouvrir le navigateur de fichiers, le CD <code>VirtIO</code>, aller dans le répertoire <code>guest agent</code>choisir l'xécutable <code>qemu-ga-x86_64</code>. Une autre cause de ralentissement peut-être le fait que windows10 ne dispose pas nativement des drivers pour la machine virtuelle. Dans ce cas taper dans la barre de recherche "device manager" ensuite cliquer sur le bouton droit de la souris sur les drivers présentant une anomalie (icone jaune attention sur le coin de l'icone du driver) et rechercher le driver dans le CDROM <code>virtIO</code>, la procédure est automatisée le driver se trouve et se charge seul.</p>
<p>Il est possible que certains problèmes apparaissent, voici une solution si le réseau défault à disparu (après un reboot de l'hôte par exemple) et que la machine virtuelle refuse de booter. Exécuter la liste de commandes suivante.</p>
<div class="highlight"><pre><span></span>sudo virsh net-define /etc/libvirt/qemu/networks/default.xml
sudo virsh net-autostart default
sudo virsh net-start default
sudo virsh net-list
<span class="sb">```</span>shell
Dernière cause possible la gestion du cache de windows10, aller dans performance du paneau de configuration et dimensionner le cache manuellement.
une fois toutes les améliorations de driver effectuées il est possible de passer le disque dur en <span class="sb">`</span>virtIO<span class="sb">`</span> ce qui est aussi sensé améliorer la performance.
<span class="c1">## <a name="head2.3"></a>2.3 En cas d'utilisation de disque externe</span>
Si on utilise un disque externe monté sur <span class="sb">`</span>/media/user<span class="sb">`</span> il est nécessaire de permettre à <span class="sb">`</span>libvirt-qemu<span class="sb">`</span> d<span class="err">'</span>accéder à ce disque en modifiant les <span class="sb">`</span> ACL<span class="sb">`</span> avec la commande suivante :
<span class="sb">```</span>shell
sudo setfacl -m u:libvirt-qemu:rx /media/vidal
</pre></div>
<p>S'il ne s'agit pas d'une installation standard et si le user qui lance la machine virtuelle n'est pas <code>libvirt-qemu</code> modifier le nom de user en conséquence.</p>
<h1><a name="head3"></a>3. Mise en production</h1>
<p>La machine windows10 est totalement opérationnelle, il ne reste plus qu'ajouter le code d'activation et configurer l'univers windows comme vous le spouhaitez.
Bon travail.</p>
<hr>
<h3><em>Webographie</em></h3>
<ol>
<li><a href="https://vitux.com/how-to-check-if-your-processor-supports-virtualization-technology/">Test des cpu</a></li>
<li><a href="https://www.qemu.org/documentation/">documentation Qemu</a></li>
<li><a href="https://wiki.debian.org/KVM">documentation debian</a></li>
<li><a href="https://help.ubuntu.com/community/KVM/Installation">documentation ubuntu</a></li>
<li><a href="https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.171-1/">logiciels pour VirtIO</a></li>
<li><a href="https://www.funtoo.org/Windows_10_Virtualization_with_KVM">Guide virtualisation</a></li>
<li><a href="https://unix.stackexchange.com/questions/47082/how-to-improve-windows-perfomance-when-running-inside-kvm">Amélioration de la performance windows10</a></li>
</ol>Creating by hand EFI multiboot live USB key2020-03-22T18:28:00+01:002020-10-18T17:50:00+02:00Gérard Vidaltag:blog.tremplin.ens-lyon.fr,2020-03-22:/GerardVidal/build_multiboot-en.html<p>This article presents a simple way to build an EFI multiboot USB key unsing <code>rEFInd</code> and ISO images. The goal is to have a key with various linux live bootable images which is simple to keep up to date just by extracting the latest ISO and not touching anything else</p><p><strong><em>Motivations</em></strong></p>
<p>During the project <a href="tremplin.ens-lyon.fr">"Tremplin des sciences"</a> we deployed <code>RaspberryPi</code> nano computers and <a href="stations.tremplin.ens-lyon.fr">weatherstations in lower secondary schools of Lyon area</a> we faced many problems due to low compentencies and knowledge of the <code>linux</code> ecosystem. We needed an easy way to boot a linux OS on any computer to interact easily with the <code>RaspberryPi</code> or check their <code>microSD</code> condition.
In another side of my life I am contributing to install parties with colleagues and it is usefull and efficient to be able to demonstrate the differences between various linux distributions, display managers and window managers.</p>
<p>In both cases we need an <code>USB EFI multiboot linux live key</code>, here is the way to produce "by hand" such a key. <em>I have choosen to produce this key step by step and not relying on various "automatic tools" because I feel that they often do what they believe is good for me instead of what I want to get, you will find many user friendly tutorials with such tools on the web but if you want o master the process keep on reading !</em></p>
<hr>
<h3><em>Table of contents</em></h3>
<ol>
<li><a href="#head1"> What we have obtained</a></li>
<li><a href="#head2">Setting up the USB key</a><ul>
<li>2.1 <a href="#head2.1">Creating partitions</a></li>
<li>2.2 <a href="#head2.2">Checking and formatting partitons</a></li>
</ul>
</li>
<li><a href="#head3">Making USB key bootable with rEFInd</a><ul>
<li>3.1 <a href="#head3.1">Creating and filling folders in EFI partition</a></li>
<li>3.2 <a href="#head3.2">Configuring rEFInd</a></li>
</ul>
</li>
<li><a href="#head4">Adding live images in partitions and fine tuning</a><ul>
<li>4.1 <a href="#head4.1">Dealing with the debian family</a></li>
<li>4.2 <a href="#head4.2">Handling Manjaro case</a></li>
</ul>
</li>
</ol>
<hr>
<h3><em>Downloads</em></h3>
<ol>
<li><a href="http://sourceforge.net/projects/refind/files/0.12.0/refind-bin-gnuefi-0.13.2.zip/download">rEFInd binaries</a></li>
<li><a href="http://sourceforge.net/projects/refind/files/0.12.0/refind-flashdrive-0.12.0.zip/download">rEFInd bootable image</a></li>
<li><a href="https://cdimage.debian.org/images/unofficial/non-free/images-including-firmware/10.3.0-live+nonfree/amd64/iso-hybrid/debian-live-10.3.0-amd64-gnome+nonfree.iso">Debian buster</a></li>
<li><a href="https://cdimage.debian.org/images/unofficial/non-free/images-including-firmware/weekly-live-builds/amd64/iso-hybrid/debian-live-testing-amd64-gnome+nonfree.iso">Debian bullseye</a></li>
<li><a href="https://ubuntu.com/download/desktop/thank-you/?version=19.10&architecture=amd64">ubuntu</a></li>
<li><a href="http://ftp.crifo.org/mint-cd/stable/19.3/linuxmint-19.3-cinnamon-64bit.iso">linux Mint</a></li>
<li><a href="https://osdn.net/dl/manjaro/manjaro-gnome-19.0.2-200312-linux54.iso">Manjaro</a></li>
</ol>
<hr>
<h1><a name="head1"></a>1. What we have obtained</h1>
<p>The following image is a picture of the laptop screen when booted on the external USB key. The following images and tools are available :</p>
<ul>
<li>debian-gnome stable (buster) live</li>
<li>debian-gnome testing (bullseye) live</li>
<li>linuxMint 19.3-cinnamon live</li>
<li>ubuntu-19.10-desktop live</li>
<li>manjaro-gnome-19.0.2 live</li>
<li>information on rEFInd</li>
<li>EFI shell</li>
<li>rEFInd boot menu order</li>
<li>rEFInd installer</li>
<li>shutdown</li>
<li>reboot</li>
<li>setup</li>
<li></li>
</ul>
<p><img alt="Écran de boot" src="images/multibootS.png" title="rEFInd home screen"></p>
<h1><a name="head2"></a>2. Setting up the USB key</h1>
<p>We need a bootable USB key, we will prepare an <code>UEFI 64bit only</code> key that will be used with EFI capable computers only ; if you need legacy boot with <code>BIOS</code> see <a href="https://blog.tremplin.ens-lyon.fr/GerardVidal/UsbKey_Pi3W_Config.html">this tutorial</a>.</p>
<h1><a name="head2.1"></a>2.1 Creating partitions</h1>
<p>The number of operating systems that can be installed depends on the size of the key. Live images are around <code>3 Gb</code> each, to be prepared to any possible evolution we decided to build partitions of 5Gb plus an EFI partition of 100Mb. We built 5 partitions for distributions, one EFI partition and a partition to have persistence for some of the linuxes.</p>
<p>To create partitions we used <code>gdisk</code> on a clean USB key. Everything is erased on the key during this operation, be sure to make copies of the files you want to keep before starting the procedure. On our computer the USB key got mounted on /dev/sdg it might be on any value /dev/sdb, /dev/sdc, /dev/sdd, depending on your computer configuration. In the following lines we will use sdX to avoid any mistake by copy/paste operation. The partition number will be added after the <code>X</code></p>
<div class="highlight"><pre><span></span>sudo gdisk /dev/sdX
GPT fdisk <span class="o">(</span>gdisk<span class="o">)</span> version <span class="m">1</span>.0.3
Partition table scan:
MBR: MBR only
BSD: not present
APM: not present
GPT: not present
<span class="c1"># Create GPT partition table</span>
Command <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: o
This option deletes all partitions and creates a new protective MBR.
Proceed? <span class="o">(</span>Y/N<span class="o">)</span>: Y
<span class="c1"># Create EFI partition</span>
Command <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: n
Partition number <span class="o">(</span><span class="m">1</span>-128, default <span class="m">1</span><span class="o">)</span>:
First sector <span class="o">(</span><span class="m">34</span>-30277598, <span class="nv">default</span> <span class="o">=</span> <span class="m">4096</span><span class="o">)</span> or <span class="o">{</span>+-<span class="o">}</span>size<span class="o">{</span>KMGTP<span class="o">}</span>:
Last sector <span class="o">(</span><span class="m">4096</span>-30277598, <span class="nv">default</span> <span class="o">=</span> <span class="m">30277598</span><span class="o">)</span> or <span class="o">{</span>+-<span class="o">}</span>size<span class="o">{</span>KMGTP<span class="o">}</span>: +100M
Current <span class="nb">type</span> is <span class="s1">'Linux filesystem'</span>
Hex code or GUID <span class="o">(</span>L to show codes, <span class="nv">Enter</span> <span class="o">=</span> <span class="m">8300</span><span class="o">)</span>: ef00
Changed <span class="nb">type</span> of partition to <span class="s1">'EFI System'</span>
<span class="c1"># Create microsoft partition (one for each distribution according to the room on the key)</span>
Command <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: n
Partition number <span class="o">(</span><span class="m">2</span>-128, default <span class="m">2</span><span class="o">)</span>:
First sector <span class="o">(</span><span class="m">34</span>-30277598, <span class="nv">default</span> <span class="o">=</span> <span class="m">106496</span><span class="o">)</span> or <span class="o">{</span>+-<span class="o">}</span>size<span class="o">{</span>KMGTP<span class="o">}</span>:
Last sector <span class="o">(</span><span class="m">106496</span>-30277598, <span class="nv">default</span> <span class="o">=</span> <span class="m">30277598</span><span class="o">)</span> or <span class="o">{</span>+-<span class="o">}</span>size<span class="o">{</span>KMGTP<span class="o">}</span>: +5Gb
Current <span class="nb">type</span> is <span class="s1">'Linux filesystem'</span>
Hex code or GUID <span class="o">(</span>L to show codes, <span class="nv">Enter</span> <span class="o">=</span> <span class="m">8300</span><span class="o">)</span>: <span class="m">0700</span>
Changed <span class="nb">type</span> of partition to <span class="s1">'Microsoft basic data'</span>
<span class="c1"># Create ext4 partition for persistence</span>
Command <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: n
Partition number <span class="o">(</span><span class="m">7</span>-128, default <span class="m">7</span><span class="o">)</span>:
First sector <span class="o">(</span><span class="m">34</span>-30277598, <span class="nv">default</span> <span class="o">=</span> <span class="m">8495104</span><span class="o">)</span> or <span class="o">{</span>+-<span class="o">}</span>size<span class="o">{</span>KMGTP<span class="o">}</span>:
Last sector <span class="o">(</span><span class="m">8495104</span>-30277598, <span class="nv">default</span> <span class="o">=</span> <span class="m">30277598</span><span class="o">)</span> or <span class="o">{</span>+-<span class="o">}</span>size<span class="o">{</span>KMGTP<span class="o">}</span>:
Current <span class="nb">type</span> is <span class="s1">'Linux filesystem'</span>
Hex code or GUID <span class="o">(</span>L to show codes, <span class="nv">Enter</span> <span class="o">=</span> <span class="m">8300</span><span class="o">)</span>:
Changed <span class="nb">type</span> of partition to <span class="s1">'Linux filesystem'</span>
Écriture de la table de partitions
Command <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: w
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!
Do you want to proceed? <span class="o">(</span>Y/N<span class="o">)</span>: Y
OK<span class="p">;</span> writing new GUID partition table <span class="o">(</span>GPT<span class="o">)</span> to /dev/sdX.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot or after you
run partprobe<span class="o">(</span><span class="m">8</span><span class="o">)</span> or kpartx<span class="o">(</span><span class="m">8</span><span class="o">)</span>
The operation has completed successfully.
</pre></div>
<h1><a name="head2.2"></a>2. Checking and formatting partitons</h1>
<p>To check the structure and format the partitions use <code>gparted</code></p>
<div class="highlight"><pre><span></span>sudo gparted
</pre></div>
<p>Format the 6 first partitions in <code>FAT32</code> and the last one in EXT4, provide labels for the 5 partitions that will receive live images, in our example we have choosen :</p>
<div class="highlight"><pre><span></span><span class="o">*</span> <span class="n">Buster</span>
<span class="o">*</span> <span class="n">BullsEye</span>
<span class="o">*</span> <span class="n">Linux</span> <span class="n">Mint</span>
<span class="o">*</span> <span class="n">Mageia</span>
<span class="o">*</span> <span class="n">Manjaro</span>
<span class="o">*</span> <span class="n">Ubuntu</span>
</pre></div>
<p>It was not possible to get an operational <code>Mageia</code>, we were not able to find any <code>grubx64.efi</code> but we kept it in the structure.</p>
<p>We have now the necessary structure for our multiboot key.</p>
<div class="highlight"><pre><span></span>lsblk -f /dev/sdg
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINT
sdg
├─sdg1 vfat FAT32 EFI ********* <span class="m">195</span>,9M <span class="m">1</span>% /media/vidal/EFI
├─sdg2 ext4 <span class="m">1</span>.0 buster ********* <span class="m">770</span>,4M <span class="m">75</span>% /media/vidal/buster
├─sdg3 ext4 <span class="m">1</span>.0 bullseye ********* <span class="m">938</span>,1M <span class="m">71</span>% /media/vidal/bullseye
├─sdg4 ext4 <span class="m">1</span>.0 linuxmint ********* <span class="m">1</span>,8G <span class="m">48</span>% /media/vidal/linuxmint
├─sdg5 ext4 <span class="m">1</span>.0 mageia ********* <span class="m">1</span>,1G <span class="m">65</span>% /media/vidal/mageia
├─sdg6 ext4 <span class="m">1</span>.0 manjaro ********* 1G <span class="m">68</span>% /media/vidal/manjaro
├─sdg7 ext4 <span class="m">1</span>.0 ubuntu ********* <span class="m">1</span>,1G <span class="m">67</span>% /media/vidal/ubuntu
└─sdg8 ext4 <span class="m">1</span>.0 persistence ********* <span class="m">4</span>,2G <span class="m">0</span>% /media/vidal/persistence
</pre></div>
<h1><a name="head3"></a>3. Making USB key bootable with rEFInd</h1>
<p>To get all the capabilities we need on our key we will download two files from <a href="https://www.rodsbooks.com/refind/">rEFInd website</a> :</p>
<div class="highlight"><pre><span></span>sudo mkdir Refind
<span class="nb">cd</span> Refind
http://sourceforge.net/projects/refind/files/0.13.2/refind-bin-gnuefi-0.13.2.zip/download
http://sourceforge.net/projects/refind/files/0.13.2/refind-flashdrive-0.13.2.zip/download
unzip refind-flashdrive-0.13.2.zip
unzip refind-bin-gnuefi-0.13.2.zip
sudo gparted
</pre></div>
<p>We are going to use files from <code>refind-bin-gnuefi-0.13.2/refind/drivers_x64/</code> which provide the necessary drivers </p>
<div class="highlight"><pre><span></span>ls -1 refind-bin-gnuefi-0.13.2/refind/drivers_x64/
btrfs_x64.efi
ext2_x64.efi
ext4_x64.efi
hfs_x64.efi
iso9660_x64.efi
LICENSE_GPL.txt
LICENSE.txt
reiserfs_x64.efi
</pre></div>
<p>and files from the image from inside <code>refind-flashdrive-0.12.0</code> :</p>
<div class="highlight"><pre><span></span> 7z l refind-flashdrive-0.12.0/refind-flashdrive-0.12.0.img
.../...
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 D.... EFI
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 D.... EFI/boot
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 D.... EFI/tools
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">34678</span> <span class="m">34816</span> EFI/boot/refind.conf
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 D.... EFI/boot/drivers_x64
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 D.... EFI/boot/drivers_aa64
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 D.... EFI/boot/icons
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">34513</span> <span class="m">34816</span> EFI/boot/refind.conf-sample
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 D.... EFI/boot/drivers_ia32
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">243712</span> <span class="m">243712</span> EFI/boot/bootaa64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">269888</span> <span class="m">270336</span> EFI/boot/bootia32.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">254216</span> <span class="m">256000</span> EFI/boot/bootx64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">63688</span> <span class="m">65536</span> EFI/boot/drivers_x64/btrfs_x64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">24392</span> <span class="m">24576</span> EFI/boot/drivers_x64/hfs_x64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">22600</span> <span class="m">24576</span> EFI/boot/drivers_x64/ext2_x64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">22088</span> <span class="m">22528</span> EFI/boot/drivers_x64/iso9660_x64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">25224</span> <span class="m">26624</span> EFI/boot/drivers_x64/reiserfs_x64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">17992</span> <span class="m">18432</span> EFI/boot/drivers_x64/LICENSE_GPL.txt
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">2094</span> <span class="m">4096</span> EFI/boot/drivers_x64/LICENSE.txt
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">23048</span> <span class="m">24576</span> EFI/boot/drivers_x64/ext4_x64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">23136</span> <span class="m">24576</span> EFI/boot/drivers_aa64/hfs_aa64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">60832</span> <span class="m">61440</span> EFI/boot/drivers_aa64/btrfs_aa64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">21696</span> <span class="m">22528</span> EFI/boot/drivers_aa64/ext2_aa64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">24096</span> <span class="m">24576</span> EFI/boot/drivers_aa64/reiserfs_aa64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">17992</span> <span class="m">18432</span> EFI/boot/drivers_aa64/LICENSE_GPL.txt
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">2094</span> <span class="m">4096</span> EFI/boot/drivers_aa64/LICENSE.txt
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">22176</span> <span class="m">22528</span> EFI/boot/drivers_aa64/ext4_aa64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">20896</span> <span class="m">22528</span> EFI/boot/drivers_aa64/iso9660_aa64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">11658</span> <span class="m">12288</span> EFI/boot/icons/os_frugalware.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">6192</span> <span class="m">8192</span> EFI/boot/icons/os_artful.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">1418</span> <span class="m">2048</span> EFI/boot/icons/vol_internal.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">2479</span> <span class="m">4096</span> EFI/boot/icons/func_about.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">13776</span> <span class="m">14336</span> EFI/boot/icons/os_chakra.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">9754</span> <span class="m">10240</span> EFI/boot/icons/os_void.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">15008</span> <span class="m">16384</span> EFI/boot/icons/os_centos.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">3446</span> <span class="m">4096</span> EFI/boot/icons/tool_part.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">3018</span> <span class="m">4096</span> EFI/boot/icons/tool_memtest.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">3872</span> <span class="m">4096</span> EFI/boot/icons/os_win8.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">10391</span> <span class="m">12288</span> EFI/boot/icons/os_chrome.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">12854</span> <span class="m">14336</span> EFI/boot/icons/os_mandriva.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">5555</span> <span class="m">6144</span> EFI/boot/icons/os_arch.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">10097</span> <span class="m">10240</span> EFI/boot/icons/os_linux.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">5980</span> <span class="m">6144</span> EFI/boot/icons/os_freebsd.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">7229</span> <span class="m">8192</span> EFI/boot/icons/os_clover.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">10574</span> <span class="m">12288</span> EFI/boot/icons/os_mac.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">3772</span> <span class="m">4096</span> EFI/boot/icons/func_firmware.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">1761</span> <span class="m">2048</span> EFI/boot/icons/func_csr_rotate.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">8480</span> <span class="m">10240</span> EFI/boot/icons/os_crunchbang.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">8763</span> <span class="m">10240</span> EFI/boot/icons/os_fedora.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">11686</span> <span class="m">12288</span> EFI/boot/icons/os_unknown.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">5072</span> <span class="m">6144</span> EFI/boot/icons/os_devuan.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">12270</span> <span class="m">12288</span> EFI/boot/icons/os_ubuntu.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">2208</span> <span class="m">4096</span> EFI/boot/icons/func_exit.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">1346</span> <span class="m">2048</span> EFI/boot/icons/arrow_right.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">3785</span> <span class="m">4096</span> EFI/boot/icons/tool_netboot.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">13817</span> <span class="m">14336</span> EFI/boot/icons/tool_rescue.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">10041</span> <span class="m">10240</span> EFI/boot/icons/os_redhat.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">4313</span> <span class="m">6144</span> EFI/boot/icons/tool_windows_rescue.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">9202</span> <span class="m">10240</span> EFI/boot/icons/os_slackware.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">14836</span> <span class="m">16384</span> EFI/boot/icons/os_network.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">9025</span> <span class="m">10240</span> EFI/boot/icons/os_xenial.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">14608</span> <span class="m">16384</span> EFI/boot/icons/os_trusty.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">7231</span> <span class="m">8192</span> EFI/boot/icons/os_refind.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">7668</span> <span class="m">8192</span> EFI/boot/icons/os_systemd.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">5620</span> <span class="m">6144</span> EFI/boot/icons/os_legacy.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">14399</span> <span class="m">16384</span> EFI/boot/icons/os_hwtest.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">2423</span> <span class="m">4096</span> EFI/boot/icons/vol_optical.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">4507</span> <span class="m">6144</span> EFI/boot/icons/tool_apple_rescue.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">2010</span> <span class="m">2048</span> EFI/boot/icons/tool_shell.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">4398</span> <span class="m">6144</span> EFI/boot/icons/func_install.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">5177</span> <span class="m">6144</span> EFI/boot/icons/tool_fwupdate.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">4846</span> <span class="m">6144</span> EFI/boot/icons/mouse.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">10547</span> <span class="m">12288</span> EFI/boot/icons/os_xubuntu.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">9377</span> <span class="m">10240</span> EFI/boot/icons/os_debian.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">6246</span> <span class="m">8192</span> EFI/boot/icons/os_linuxmint.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">12873</span> <span class="m">14336</span> EFI/boot/icons/os_kubuntu.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">1974</span> <span class="m">2048</span> EFI/boot/icons/tool_mok_tool.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">12379</span> <span class="m">14336</span> EFI/boot/icons/os_netbsd.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">1892</span> <span class="m">2048</span> EFI/boot/icons/vol_net.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">5830</span> <span class="m">6144</span> EFI/boot/icons/os_haiku.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">8484</span> <span class="m">10240</span> EFI/boot/icons/os_refit.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">1344</span> <span class="m">2048</span> EFI/boot/icons/vol_external.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">2760</span> <span class="m">4096</span> EFI/boot/icons/func_shutdown.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">6349</span> <span class="m">8192</span> EFI/boot/icons/README
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">6572</span> <span class="m">8192</span> EFI/boot/icons/os_opensuse.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">1890</span> <span class="m">2048</span> EFI/boot/icons/os_manjaro.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">6565</span> <span class="m">8192</span> EFI/boot/icons/os_win.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">2602</span> <span class="m">4096</span> EFI/boot/icons/func_reset.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">1392</span> <span class="m">2048</span> EFI/boot/icons/arrow_left.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">7549</span> <span class="m">8192</span> EFI/boot/icons/os_gentoo.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">5371</span> <span class="m">6144</span> EFI/boot/icons/os_zesty.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">16482</span> <span class="m">18432</span> EFI/boot/icons/os_elementary.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">6572</span> <span class="m">8192</span> EFI/boot/icons/os_suse.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">6958</span> <span class="m">8192</span> EFI/boot/icons/os_bionic.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">7783</span> <span class="m">8192</span> EFI/boot/icons/os_mageia.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">11232</span> <span class="m">12288</span> EFI/boot/icons/os_lubuntu.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">3766</span> <span class="m">4096</span> EFI/boot/icons/boot_win.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">9077</span> <span class="m">10240</span> EFI/boot/icons/boot_linux.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">11777</span> <span class="m">12288</span> EFI/boot/icons/vol_efi.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">13342</span> <span class="m">14336</span> EFI/boot/icons/os_uefi.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">6930</span> <span class="m">8192</span> EFI/boot/icons/func_bootorder.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">213</span> <span class="m">2048</span> EFI/boot/icons/transparent.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">7161</span> <span class="m">8192</span> EFI/boot/icons/func_hidden.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">7668</span> <span class="m">8192</span> EFI/boot/icons/os_gummiboot.png
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">59456</span> <span class="m">61440</span> EFI/boot/drivers_ia32/btrfs_ia32.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">23360</span> <span class="m">24576</span> EFI/boot/drivers_ia32/reiserfs_ia32.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">22784</span> <span class="m">24576</span> EFI/boot/drivers_ia32/hfs_ia32.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">17992</span> <span class="m">18432</span> EFI/boot/drivers_ia32/LICENSE_GPL.txt
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">2094</span> <span class="m">4096</span> EFI/boot/drivers_ia32/LICENSE.txt
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">21184</span> <span class="m">22528</span> EFI/boot/drivers_ia32/ext4_ia32.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">20608</span> <span class="m">22528</span> EFI/boot/drivers_ia32/ext2_ia32.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">20224</span> <span class="m">20480</span> EFI/boot/drivers_ia32/iso9660_ia32.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">792064</span> <span class="m">792576</span> EFI/tools/gdisk_x64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">32384</span> <span class="m">32768</span> EFI/tools/gptsync_ia32.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">922272</span> <span class="m">923648</span> EFI/tools/shellx64.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">810496</span> <span class="m">811008</span> EFI/tools/shellia32.efi
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 ....A <span class="m">31688</span> <span class="m">32768</span> EFI/tools/gptsync_x64.efi
------------------- ----- ------------ ------------ ------------------------
<span class="m">2021</span>-03-13 <span class="m">19</span>:49:56 <span class="m">4555179</span> <span class="m">4669440</span> <span class="m">110</span> files, <span class="m">7</span> folders
</pre></div>
<p>Create temporary folders to mount the partitions of the <code>USB key</code></p>
<div class="highlight"><pre><span></span><span class="k">for</span> i in <span class="m">2</span> <span class="m">3</span> <span class="m">4</span> <span class="m">5</span> <span class="m">6</span> <span class="m">7</span><span class="p">;</span> <span class="k">do</span> sudo mkdir /mnt/disk<span class="nv">$i</span><span class="p">;</span> <span class="k">done</span>
</pre></div>
<h1><a name="head3.1"></a>3.1 Creating and filling folders in EFI partition</h1>
<p>mount EFI partition on <code>/mnt/disk1</code> then create folders to host <code>rEFInd</code></p>
<div class="highlight"><pre><span></span>sudo mount /dev/sdX1 /mnt/disk1
<span class="nb">cd</span> /mnt/disk1
sudo mkdir -p EFI/BOOT EFI/TOOLS
</pre></div>
<p>We use upper case to keep in mind that EFI is a <code>DOS like</code> environment folder names do not make difference between lower and upper case</p>
<p>Fill the folders with the appropriate data</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> Refind
cp refind-flashdrive-0.12.0/EFI/tools/*x64.efi /mnt/disk1/EFI/TOOLS
cp -r refind-bin-gnuefi-0.13.2/refind/drivers_x64 /mnt/disk1/EFI/BOOT
cp -r refind-bin-gnuefi-0.13.2/refind/icons /mnt/disk1/EFI/BOOT
cp refind-bin-gnuefi-0.13.2/refind/refind.conf-sample /mnt/disk1/EFI/BOOT
cp refind-bin-gnuefi-0.13.2/refind/refind.conf-sample /mnt/disk1/EFI/BOOT/refind.conf
cp refind-bin-gnuefi-0.13.2/refind/refind_x64.efi /mnt/disk1/EFI/BOOT/bootx64.efi
</pre></div>
<p>The <code>USB key</code>is now ready to boot but to get a multiboot key we have to configure <code>rEFInd</code> and provide live linux images.</p>
<h1><a name="head3.2"></a>3.2 Configuring rEFInd</h1>
<p>To configure <code>rEFInd</code> we need to provide Ad-Hoc parameters in <code>refind.conf</code> configuration file to enable <code>bootx64.efi</code> find all the linux loaders we want to use. The following configuration file is an example corresponding to our situation; you will have to change the configuration according to the number and names of distributions. We have been able to install :
* debian buster
* debian bullseye
* ubuntu
* linuxMint
* Manjaro (with a trick)</p>
<p>We keep a timeout that enable an automatic boot with the first bootloader <code>debian buster in thiscase</code>, we enable the mouse driver but it may not work in some computers in that case use the arrows to navigate between the possible choices the <code>tab</code>key displays the possible option if some exists.Scanning "manual" enables to choose only the bootloaders choosen and not scan automatically all disks for bootloaders.</p>
<p>There is a <code>menuentry</code> for each linux distribution, after having many trouble in installing manual stanzas we relied on automatic scanning from <code>refind</code>. Icons displayed on the <code>rEFInd</code> homepage are copied from the EFI partition on the linux live partition</p>
<p>Here is the <code>refind.conf</code> file which has been tested :</p>
<div class="highlight"><pre><span></span><span class="c1">#</span>
timeout <span class="m">20</span>
use_nvram <span class="nb">false</span>
enable_mouse
showtools shell, bootorder, gdisk, memtest, about, hidden_tags, reboot, exit, firmware, fwupdate
scanfor external, manual
</pre></div>
<p>Very simple config file to take full advantage of <code>rEFInd</code> autoscan capabilities</p>
<h1><a name="head4"></a>4. Adding live images in partitions and fine tuning</h1>
<p>Last step is to copy on the USB key the live distributions we have choosen and prepared in the <code>refind.conf</code>file. We suppose al the live distributions you want to use have been dowloaded; for us we have the following images located at <code>/date/IsoImages</code> :</p>
<div class="highlight"><pre><span></span>ls -1
debian-live-10.6.0-amd64-gnome+nonfree.iso
debian-live-testing-amd64-gnome+nonfree.iso
linuxmint-20-cinnamon-64bit.iso
Mageia-7.1-Live-GNOME-x86_64.iso
manjaro-gnome-20.1.1-201001-linux58.iso
ubuntu-20.04.1-desktop-amd64.iso
</pre></div>
<p>Each of these images will be copied on the USB key partitions <code>/dev/sdX2, /dev/sdX3, /dev/sdX4, /dev/sdX5, /dev/sdX6</code>. The situation is different for distributions of the debian family and others. We did not succed to add a Mageia distribution and used a dirty trick to force Manjaro in.</p>
<h1><a name="head4.1"></a>4.1 Dealing with the debian family</h1>
<p>As we have seen previously in the configuration file we use the default grub loader for all the debian family images, we just have to copy the iso image contents on the choosen partition. For Buster image we have created the partition with the following parameters :</p>
<div class="highlight"><pre><span></span>PARTUUID PARTLABEL UUID
bfb2657a-1896-4783-a8fe-xxxxxxxxxxxx Buster B475-####
</pre></div>
<p>By default on a debian system it is mounted on <code>/media/user/B475-####</code> you may use this value or mount it on the hook you prepared at the beginning</p>
<div class="highlight"><pre><span></span>sudo umount /dev/sdx2
sudo mount /dev/sdx2 /mnt/disk2
</pre></div>
<p>It is possible to mount all the 5 partitions at once :</p>
<div class="highlight"><pre><span></span><span class="k">for</span> i in <span class="m">2</span> <span class="m">3</span> <span class="m">4</span> <span class="m">5</span> <span class="m">6</span> <span class="p">;</span> <span class="k">do</span> sudo umount /dev/sdg<span class="nv">$i</span><span class="p">;</span> sudo mount /dev/sdg<span class="nv">$i</span> /mnt/disk<span class="nv">$i</span><span class="p">;</span> <span class="k">done</span>
sudo 7z x /data/IsoImages/debian-live-10.6.0-amd64-gnome+nonfree.iso -o/mnt/disk2
sudo 7z x /data/IsoImages/debian-live-testing-amd64-gnome+nonfree.iso -o/mnt/disk3
sudo 7z x /data/IsoImages/manjaro-gnome-20.1.1-201001-linux58.iso -o/mnt/disk4
sudo 7z x /data/IsoImages/ubuntu-20.04.1-desktop-amd64.iso -o/mnt/disk5
</pre></div>
<p>Check that after uncompressing and copying the images the efi grub executables are in the correct folder :
* debian buster -> /mnt/disk2/EFI/boot/grubx64.efi
* debian bullseye -> /mnt/disk3/EFI/boot/grubx64.efi
* ubuntu -> /mnt/disk4/EFI/BOOT/grubx64.efi
* linuxMint -> /mnt/disk5/EFI/BOOT/grubx64.efi</p>
<p>Check that the initial <code>grub.cfg</code> that detects the partition and starts the booting process is in the same folder <code>/EFI/boot/</code> or <code>/EFI/BOOT</code>, if another folder named <code>debian</code> exists beside the <code>boot</code> folder it must contain the same <code>grub.cfg</code>. The <code>grub.cfg</code> file must be in the form :</p>
<div class="highlight"><pre><span></span>search --label --set<span class="o">=</span>root LABEL_GIVEN_TO_THE_PARTITION
<span class="nb">set</span> <span class="nv">prefix</span><span class="o">=(</span><span class="nv">$root</span><span class="o">)</span>/boot/grub
<span class="nb">source</span> <span class="nv">$prefix</span>/x86_64-efi/grub.cfg
</pre></div>
<p>check that <code>/boot/grub/x86_64-efi/grub.cfg</code> exists and sends to the next step :</p>
<div class="highlight"><pre><span></span>cat ../../boot/grub/x86_64-efi/grub.cfg
insmod part_acorn
insmod part_amiga
insmod part_apple
insmod part_bsd
insmod part_dfly
insmod part_dvh
insmod part_gpt
insmod part_msdos
insmod part_plan
insmod part_sun
insmod part_sunpc
<span class="nb">source</span> /boot/grub/grub.cfg
</pre></div>
<p>For debian images change the search mode of the partitiion by <code>label</code>instead of <code>file</code> replace the first line of <code>/EFI/debian/grub.cfg</code></p>
<div class="highlight"><pre><span></span>search --label --set root bullseye
</pre></div>
<p>The four images belonging to the debian family are ready to boot from <code>rEFInd</code></p>
<h1><a name="head4.2"></a>4.2 Handling Manjaro case</h1>
<p>"Manjaro" is said to be an "easy to use" <code>linux Arch</code> version, the boot process differs from debian; it is loaded directly through the <code>vmlinuz</code> and the <code>initramfs</code>from the distribution. The name of the rootfs is retrieved from options and by default the loader looks for it using <code>by-label</code>method.</p>
<p>It is interesting to point out here that as long as the grub files (debian family) or initramfs and vmlinuz (Arch family) are provided in their default place, it is possible to reinstall or change the version of the distribution without changing anything else except the ̀<code>Labels</code> in the config files. There is no need to change the structure or the contents of the EFI partition and <code>rEFInd</code> configuration to change the version of any linux live distribution on the USB multiboot key.</p>Why we could not install linux on an iMac early 2006 (core Duo)2020-03-02T10:25:00+01:002020-03-02T10:25:00+01:00Gérard Vidaltag:blog.tremplin.ens-lyon.fr,2020-03-02:/GerardVidal/LinuxOnImacVintage-en.html<p>This <code>howto</code> describes step by step (plus comments) the method we used to try install a linux distribution on an iMac "early 2006 core duo", the famous first iMac-Intel. All the tricks failed to get graphics display, but the <code>hackintosh2006</code> works perfectly as a server!</p><p><strong><em>Motivations</em></strong>
This work was initiated when two needs happen to cross : on one path a colleague who participate on our research project on teaching climate change needed some linux machines for his higher secondary school and had some of those iMacs unused; on the other path during one of my voluntary participations on linux and free software aproposed asked the same question.</p>
<h3><em>Aknowledgements</em></h3>
<p>great thanks to Éric Lejan, distinguished Apple user who provided valuable advices, tricks and support all along this work.</p>
<h3><em>Summary</em></h3>
<ol>
<li><a href="#head1">Beforehand remarks</a></li>
<li>
<p><a href="#head2">Preparing an vintage iMac bootable key "iMac2006_key"</a>
a. <a href="#head2.1">Building and formatting an USB key</a>
i. Create partitions
i. Check and format</p>
<p>b. <a href="#head2.2">Install bootloader</a>
c. <a href="#head2.3">Install System on iMac2006_key</a>
i. Last amendments on EFI partition
1. <a href="#head3">Installing debian gnu-linux on a vintage iMac with our iMac2006_key</a>
a. <a href="#head3.1">Install standard linux system</a>
b. <a href="#head3.2">Low level configuration of the new linux system</a>
c. <a href="#head3.3">Advanced configuration of the new linux system</a></p>
</li>
</ol>
<hr>
<h3>* Downloads *</h3>
<ol>
<li><a href="https://cdimage.debian.org/images/unofficial/non-free/images-including-firmware/">debian unofficial non-free image</a>
https://astrofloyd.wordpress.com/2014/01/14/linux-only-installation-on-2006-macbook-using-refind/</li>
</ol>
<hr>
<h1><a name="head1"> </a> 1. Beforehand remarks</h1>
<p>All this work did not enable to get the <code>Radeon mobility X1600 to work</code>, here are some reasons that were identified :</p>
<div class="highlight"><pre><span></span><span class="o">*</span> <span class="nv">There</span> <span class="nv">is</span> <span class="nv">no</span> <span class="nv">driver</span> `<span class="nv">RV530</span>` <span class="nv">in</span> <span class="nv">the</span> <span class="nv">package</span> `<span class="nv">firmware</span><span class="o">-</span><span class="nv">amd</span><span class="o">-</span><span class="nv">graphics</span>`
<span class="o">*</span> <span class="nv">The</span> <span class="nv">driver</span> <span class="nv">is</span> <span class="nv">required</span> <span class="nv">at</span> <span class="nv">early</span> <span class="nv">boot</span> <span class="nv">stage</span> <span class="nv">but</span> <span class="nv">even</span> <span class="k">if</span> `<span class="nv">clover</span>` <span class="nv">may</span> <span class="k">do</span> <span class="nv">the</span> <span class="nv">job</span>, <span class="nv">last</span> <span class="nv">usable</span> <span class="nv">version</span> <span class="ss">(</span><span class="mi">1000</span><span class="ss">)</span> <span class="nv">is</span> <span class="nv">too</span> <span class="nv">old</span> <span class="nv">and</span> <span class="nv">no</span> <span class="nv">configuration</span> <span class="nv">fits</span> <span class="nv">the</span> <span class="nv">needs</span>
<span class="o">*</span> <span class="nv">In</span> <span class="nv">some</span> <span class="nv">tests</span> <span class="nv">during</span> <span class="nv">the</span> <span class="nv">boot</span> <span class="nv">process</span> <span class="nv">the</span> <span class="nv">machine</span> <span class="nv">claimed</span> <span class="nv">a</span> <span class="nv">BIOS</span> <span class="nv">driver</span> <span class="nv">which</span> <span class="nv">is</span> <span class="nv">peculiar</span> <span class="k">for</span> <span class="nv">an</span> `<span class="nv">EFI</span>` <span class="nv">system</span>
</pre></div>
<p>You may have participated to "install parties" and may wonder why I waste my time to write a tutorial that exists in many places on the net. In fact if you tackle this particular iMac with your ordinary tools like a<code>linux live key</code> or <code>linux install key</code>you might be very surprised because this vintage tool will probably not see your key as bootable and will never boot ! If you use one of the tricks available (and mostly hidden) on the net, you may succeed in booting installing it, you will not get a graphics display which is more than weird for an apple computer...
Those problems arise because this iMac sometimes known as vintage or collector is the first iMac-Intel, it was born at the beginning of the era of <code>EFI</code> in february 2006 and died the same year in october replaced by more stable and conventional models. We shall discover all the paricularities along the installation.
Another impotant point to have in mind is that this is an old machine that may have slept for long time and the "CMOS RAM battery" ("PRAM battery" in apple language) may be too weak to fullfill its job and in that case the iMac does not boot! Do not panic if you get the famous "blankscreen of the death" check the little battery and replace it if needed.</p>
<p>To be safe before any attempt clone your hard disk (that will be very usefull when the mac refuses to boot with the internal disk once modified), format a spare disk, check that you have 2 partitions on the disk : an <code>ESP</code> (EF) and an <code>HFS+</code> with the clone of he system and the data. </p>
<h1><a name="head2"> </a> 2. Preparing an vintage iMac bootable key "iMac2006_key"</h1>
<p>As described in the previous chapter we canot use an ISO linux image or a legacy boot install USB key this machine has the following requirements :
* provide USB key with <code>GPT partition table</code>
* provide USB key with <code>EFI partition</code> bearing an <code>/EFI</code> or <code>/efi</code> folder
* provide a <code>32bit</code>booting program named BOOT.EFI</p>
<h2><a name="head2.1"> </a> 2.1. Building and formatting an USB key</h2>
<p>To do this first step we need to install a <code>grub-efi 32bit</code> on an USB key which is a little tricky if you run a <code>64bit linux machine</code>. I will not consider other source OS than linux. <code>debian</code> distribution contain packages to install a 32 bit grub on a disk that's why I have choosen to use it. Of course it is possible to install the 32bit packages on a 64 bit machine, very easily if you run <code>multiarch support</code><strong>BUT</strong> I ran into serious trouble when I tried that... I cannot confirm that I did not any wrong typing but that was the firstcause of pain (in a long list...). To avoid those problems :
* create an USB debian 32 bit live key, I use the <a href="https://cdimage.debian.org/images/unofficial/non-free/images-including-firmware/">unofficial non-free image</a> because of some of the firmware needed by my laptop but any debian live image will do (if your harware drivers are all free)
* boot your computer on this image</p>
<p>You are now running a lightweight debian stable 32bit. We have to add some packages dedicated to our goal with the command</p>
<div class="highlight"><pre><span></span>sudo apt update
sudo apt install gparted grub-efi grub-efi-ia32 grub-efi-ia32-bin grub-customizer
</pre></div>
<p>Packages and all the required dependencies are installed</p>
<p>Take an empty USB key that will be used to install <code>debian</code> on the iMac. The key must be empy everything that might be on the key will be erased and totally lost. You can erase and format your key using <code>gparted</code>, <strong>take extreme care on these operations</strong> there is no way to go back, do not erase your internal hard disk do not erase the key on which you have booted.</p>
<h3>Create partitions</h3>
<p>Many methods are possible for this step, I'll use the command line one, in this situation my hard disk is <code>/dev/sda</code>, the key used to boot the 32 bit system is <code>/dev/sdb</code>, the key we want to use is <code>/dev/sdc</code>. I'll use <code>/dev/sdX</code> in this text but <code>/dev/sdX</code> is <code>/dev/sdc</code> in my case.</p>
<div class="highlight"><pre><span></span>sudo gdisk /dev/sdX
<span class="nb">type</span>
o <span class="c1"># creates a new GPT partition table</span>
n <span class="c1"># create a new partition</span>
<span class="m">1</span> <span class="c1"># first partition on the key</span>
enter <span class="c1"># accept the default first sector proposed</span>
+100M <span class="c1"># create a partition of 100MB size</span>
0ef00 <span class="c1"># create an EFI (esb) partition</span>
n <span class="c1"># create a new partition</span>
<span class="m">2</span> <span class="c1"># second partition on the key</span>
enter <span class="c1"># accept the default first sector proposed</span>
enter <span class="c1"># accept the default last sector proposed</span>
<span class="m">0700</span> <span class="c1"># create microsoft basic data partition</span>
w <span class="c1">#execute the commands</span>
y <span class="c1"># confirm</span>
</pre></div>
<h3>Check and format</h3>
<p>Use <code>sudo gparted</code> to check that the structure is correct and format in fat32 both partitions. At the end of the process you should have two partitions on your disk <code>dev/sdX</code> :
* EFI system fat 32 100Mio
* Microsoft basic data (rest of the key)</p>
<h2><a name="head2.2"> </a> 2.2. Install bootloader</h2>
<p>To install the bootloader we need to have acces to the new partitions we have just created we need to create mounting poionts and mount them.</p>
<div class="highlight"><pre><span></span>sudo mkdir /mnt/disk1
sudo mkdir /mnt/disk2
sudo mount /dev/sdX1 /mnt/disk1
sudo mount /dev/sdX2 /mnt/disk2
sudo grub-install --target<span class="o">=</span>i386-efi --efi-directory<span class="o">=</span>/mnt/disk1 --bootloader-id<span class="o">=</span>boot.efi --boot-directory<span class="o">=</span>/mnt/disk2/boot --removable /dev/sdX
</pre></div>
<p>Bootloader is installed we can go back to our standard linux laptop for the next steps.</p>
<div class="highlight"><pre><span></span>sudo umount /mnt/disk1
sudo umount /mnt/disk2
</pre></div>
<p>Eject iMac2006_key.</p>
<h2><a name="head2.3"> </a> 2.3. Install System on iMac2006_key</h2>
<p>Go back to your c"comfortable" computer plug in the iMac2006_key. To avoid any interference with ordinary files I mount the partitions on mnt/disk1 and mnt/disk2 mount points. My iMac2006_key is identified as <code>/dev/sdh</code> so here <code>/dev/sdh</code> is <code>/dev/sdX</code>. </p>
<div class="highlight"><pre><span></span>sudo umount /dev/sdX2
sudo mount /dev/sdX1 /mnt/disk1
sudo mount /dev/sdX2 /mnt/disk2
</pre></div>
<h3>Last amendments on EFI partition</h3>
<p>The first spacial feature is that the iMac will recognize as bootable keys that bear a <code>boot.efi</code> file. We have to change the boot name of our iMac2006_key to make it visible to the iMac. </p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /mnt/disk1/EFI/BOOT/
sudo cp BOOTIA32.EFI BOOT.EFI
</pre></div>
<h3>Add system on the iMac2006_key</h3>
<p>Dowload the <code>iso 32bit image</code> you want to install on your iMac I choosed <code>debian-live-10.3.0-i386-gnome+nonfree.iso</code> then uncompress the system on your iMac2006_key.</p>
<div class="highlight"><pre><span></span>sudo 7z x /pathTo/debian-live-9.1.0-amd64-gnome+nonfree.iso -o/mnt/disk2
<span class="c1">#click A to replace all the "old" files provided by grub-install with files provided by the distribution you want to install</span>
</pre></div>
<p>The extraction/copy will take some time. and finally you'll get the following structure on your key :</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /mnt/disk2
ls
boot/ <span class="s1">'[BOOT]'</span>/ d-i/ dists/ EFI/ firmware/ isolinux/ live/ pool/
sudo cp -r EFI/debian/ grub
sudo mv EFI liveEFI
</pre></div>
<p>Your iMac2006_key is ready to install a system on the iMac. Unfortunately we have some new problems to tackle because of the <code>Radeon Mobility X1600 graphic board</code> installed on the iMac. It will not be possible to boot on the brand new linux live but the installer works perfectly. It is also possible to boot the live image without graphics which could be usefull in case of any trouble by enabling remote login. Edit <code>/boot/grub/grub.cfg</code> and add "nomodeset" on kernel command line.</p>
<p>Let's use the install program.</p>
<div class="highlight"><pre><span></span>sudo umount /mnt/disk1
sudo umount /mnt/disk2
</pre></div>
<p>retrieve the USB key</p>
<h1><a name="head3"> </a> 3. Installing debian gnu-linux on a vintage iMac with our iMac2006_key</h1>
<p>Here starts the tricky part of the process !</p>
<h2><a name="head3.1"> </a> 3.1. Install standard linux system</h2>
<p>switch off the iMac plug in the iMac2006_key, switch on the iMac and as soon as you hear the chime press one of the <code>alt keys</code> after few seconds you'll see the two possible boot disks choose the external key click <code>enter</code>. You get a white screen then the grub boot screen. Unfortunately there is no operational graphics driver then you <strong>must choose</strong> one of the available install methods. The graphic method functions properly.</p>
<p>Do not interrupt the installation and wait for the iMac to reboot on its own.</p>
<p>When the iMac reboots choose advanced menu and recovery boot, click on "e" to edit the boot menu and add <code>nomodeset</code> or <code>radeon.modeset=0</code> at the end of the line starting with <code>linux</code>. The imac will boot in standalone mode without trying to activate the <code>radeon mobility X1600</code> board that will bring a standard standalone linux behaviour and will enable further work.</p>
<p>Note that at that point this iMac is fully operationnal in console mode or a as a terminal server. </p>
<h2><a name="head3.2"> </a> 3.2. Low level configuration of the new linux system</h2>
<p>When the iMac is booted in linux standalone we need to install some packages, start some services and remove some locks to work comfortably. We will start the network, install and start the <code>ssh</code>server, remove the standalone lock. On the standalone shell on the iMac type the following commands</p>
<div class="highlight"><pre><span></span>apt update
apt upgrade
apt install openssh-server
apt systemctl start network-manager
rm /run/nologin
</pre></div>
<p>It is now possible to join on the iMac from a remote machine. We created the user moonraker with sudo capability, we can login from any computer on the same network :</p>
<div class="highlight"><pre><span></span>ssh moonraker@192.168.***.***
</pre></div>
<p>At this point we have a fully operationnal hackintosh with no graphics if we add the <code>nomodeset</code> option to the linux command line in the grub.cfg file.</p>
<h2><a name="head4.0"> </a> 4. All the tricks that did not work</h2>
<h3>Trying to cheat on the driver</h3>
<h3>Using Bootloader managers</h3>
<h4>On the linux side with rEFInd</h4>
<h4>On Apple side with Clover</h4>
<p>Even if linux works on the iMac we need to find a way to activate the graphics interface. The problem is that the <code>radeon mobility X1600</code>driver must be loaded during the early stages of booting process. To do that we are going to install <code>rEFInd</code> boot manager and modify the configuration to provide yhe drivers</p>
<p>sudo apt install refind
refind-install</p>
<p>add contrib non-free in /etc/apt/sources.list</p>
<p>sudo apt install firmware-b43-installer</p>
<p>add module name to /etc/modules to load at boot time
lsinitramfs /boot/initrd.img-4.19.0-8-686 | m</p>
<p>cp /lib/firmware/radeon/R520_cp.bin /lib/firmware/radeon/RV530_cp.bin
/usr/share/metainfo/firmware-amd-graphics.metainfo.xml</p>
<p>(cpio -id; zcat | cpio -id) < /boot/initrd.img-4.19.0-8-686</p>
<p>F10 key ==> File Edit Search Buffers Windows System Help</p>
<h1>!/bin/sh -e</h1>
<p>PREREQS=""</p>
<p>prereqs() { echo "$PREREQS"; }</p>
<p>case "$1" in
prereqs)
prereqs
exit 0
;;
esac</p>
<p>. /usr/share/initramfs-tools/hook-functions</p>
<p>cp /lib/firmware/radeon/R520_cp.bin "$DESTDIR/usr/lib/firmware/radeon/RV530_cp.bin"</p>
<p>https://www.mediafire.com/file/hnzneqtomdk/ATI_Mobility_Radeon_X1300%252C_X1400_and_X1600_series.rar/file</p>Faire du streaming live avec une Raspberry Pi et les ressources de l'ENS-IFÉ2019-11-08T07:17:00+01:002019-11-08T07:17:00+01:00Gérard Vidaltag:blog.tremplin.ens-lyon.fr,2019-11-08:/GerardVidal/faire-du-streaming-live-avec-une-raspberry-pi-et-les-ressources-de-lens-ife.html<p>Utilisation d'une Raspberry Pi pour faire de la diffusion en direct d'images. Cet article explique comment mettre en place un service de "vidéodiffusion en ligne" utilisant une raspberry Pi comme encodeur / serveur de flux vidéo. Travail encore en cours !working copy!</p><p><strong><em>Motivations</em></strong></p>
<p>Les raspberries Pi sont proposées avec une caméra vidéo connectable avec une nappe qui évite d'occuper un connecteur USB. cette caméra est de bonne qualité et de très petite taille ce qui peut permettre de construire des outils d'exploration très maniables et très performants ou de fabriquer des dispotifs de veille discrets et peu encombrants.</p>
<p>Il existe une bibliothèque dédiée à la caméra de la raspberry qui a été installée dans les images <a href="https://media.tremplin.ens-lyon.fr/isoImages/RaspBerry/">fournies par l'IFÉ-ENS de Lyon</a> mais il est aussi possible d'utiliser des outils linux génériques qui permettent d'acquérir un savoir faire réutilisable dans toutes les conditions ou d'insérer la raspberry et sa caméra dans un univers linux (ou autre) préexistant en utilisant des solutions standard. Nous n'aborderons pas ici les "chaînes toutes prêtes" pour aborder plutôt la compréhension du fonctionnement d'un service de streaming vidéo live.</p>
<h3><em>Remerciements</em></h3>
<p>Charles-Henri Eyraud.</p>
<hr>
<h3><em>Sommaire</em></h3>
<ol>
<li>
<p><a href="#head1">Principes de la vidéodiffusion</a></p>
</li>
<li>
<p><a href="#head2">Configuration de l'encodeur</a></p>
<ol>
<li><a href="#head2.1">Informations sur le matériel utilisé</a></li>
<li><a href="#head2.2">Configuration de la caméra</a></li>
<li><a href="#head2.3">Les commandes d'acquisition et d'encodage <code>raspivid</code> et <code>ffmpeg</code></a></li>
</ol>
</li>
<li><a href="#head3">Configuration du serveur et format du flux transporté</a><ol>
<li><a href="#head3.1">Le serveur web <code>nginx rtmp</code></a><ol>
<li><a href="#head3.1.1">Configuration d'un serveur <code>hls</code> avec <code>ffmpeg</code></a></li>
</ol>
</li>
<li><a href="#head3.2">Le serveur web <code>nginx HLS</code></a></li>
<li><a href="#head3.3">Le serveur web <code>nginx DASH</code></a></li>
<li><a href="#head3.2">Raspberry Pi comme encodeur et serveur</a></li>
</ol>
</li>
<li><a href="#head4">Configuration du player dans une page web</a></li>
</ol>
<hr>
<h3><em>Téléchargements</em></h3>
<ol>
<li><a href="https://media.tremplin.ens-lyon.fr/isoImages/RaspBerry/DebianBusterPi3/2019-02-18-rpi3-buster.img.xz">image proposée par le projet Tremplin de l'ENS-IFÉ</a></li>
<li><a href="https://depot.tremplin.ens-lyon.fr/Raspi2-3_GenImage">g_vidal rpi23-gen-image</a></li>
<li><a href="http://mediaserv.climatetmeteo.fr/images/RaspBerry/DebianStretchPi3/">Images raspberryPi du projet Tremplin</a></li>
</ol>
<hr>
<h3><em>Résumé</em></h3>
<p>Si vous êtes pressé et souhaitez immédiatement faire de la vidéodiffusion sans forcément en connaître les tenants et les aboutissants voici la procédure :</p>
<div class="highlight"><pre><span></span><span class="o">*</span> <span class="n">Installer</span> <span class="n">les</span> <span class="n">paquets</span> <span class="err">ǹ</span><span class="n">ginx</span><span class="ss">` `</span><span class="n">ffmpeg</span><span class="ss">`, `</span><span class="n">v4l2</span><span class="ss">`, `</span><span class="n">nginx</span><span class="o">-</span><span class="n">extras</span><span class="ss">`, `</span><span class="n">libnginx</span><span class="o">-</span><span class="k">mod</span><span class="o">-</span><span class="n">rtmp</span><span class="ss">`.</span>
<span class="ss"> 1. `</span><span class="n">sudo</span> <span class="n">apt</span> <span class="n">install</span> <span class="n">nginx</span><span class="o">-</span><span class="n">extras</span> <span class="n">ffmpeg</span> <span class="n">libnginx</span><span class="o">-</span><span class="k">mod</span><span class="o">-</span><span class="n">rtmp</span> <span class="n">v4l</span><span class="o">-</span><span class="n">utils</span> <span class="n">qv4l2</span><span class="ss">`</span>
<span class="ss">* ajouter à la fin du fichier `</span><span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">nginx</span><span class="o">/</span><span class="n">nginx</span><span class="p">.</span><span class="n">conf</span><span class="o">`</span> <span class="n">de</span> <span class="n">votre</span> <span class="n">raspberry</span> <span class="n">le</span> <span class="n">contenu</span> <span class="n">du</span> <span class="n">bloc</span> <span class="n">ci</span><span class="o">-</span><span class="n">dessous</span>
</pre></div>
<div class="highlight"><pre><span></span><span class="err">rtmp</span> <span class="p">{</span>
<span class="err">server</span> <span class="err">{</span>
<span class="err">listen</span> <span class="err">1935;</span>
<span class="err">chunk_size</span> <span class="err">4096;</span>
<span class="err">application</span> <span class="err">live</span> <span class="err">{</span>
<span class="err">live</span> <span class="err">on;</span>
<span class="err">record</span> <span class="err">off;</span>
<span class="err">allow</span> <span class="err">publish</span> <span class="err">all;</span>
<span class="err">allow</span> <span class="err">play</span> <span class="err">all;</span>
<span class="p">}</span>
<span class="err">application</span> <span class="err">hls</span> <span class="p">{</span>
<span class="err">live</span> <span class="err">on;</span>
<span class="err">hls</span> <span class="err">on;</span>
<span class="err">hls_cleanup</span> <span class="err">on;</span>
<span class="err">hls_sync</span> <span class="err">100ms;</span>
<span class="err">hls_fragment</span> <span class="err">2s;</span>
<span class="err">hls_path</span> <span class="err">/tmp/hls;</span>
<span class="err">allow</span> <span class="err">play</span> <span class="err">all;</span>
<span class="p">}</span>
<span class="err">application</span> <span class="err">dash</span> <span class="p">{</span>
<span class="err">live</span> <span class="err">on;</span>
<span class="err">dash</span> <span class="err">on;</span>
<span class="err">dash_path</span> <span class="err">/tmp/dash;</span>
<span class="err">allow</span> <span class="err">play</span> <span class="err">all;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="err">}</span>
</pre></div>
<div class="highlight"><pre><span></span><span class="o">*</span> <span class="n">relancer</span> <span class="n">nginx</span> <span class="o">`</span><span class="n">sudo</span> <span class="n">systemctl</span> <span class="k">restart</span> <span class="n">nginx</span><span class="o">`</span>
<span class="o">*</span> <span class="n">lancer</span> <span class="n">l</span><span class="s1">'encodage `ffmpeg -f v4l2 -r 25 -pix_fmt h264 -video_size 640x360 -i /dev/video0 -c:v libx264 -an -b:v 1600k -preset veryfast -f flv -r 25 rtmp://127.0.0.1:1935/live`</span>
<span class="s1">* se connecter sur l'</span><span class="n">adresse</span> <span class="n">de</span> <span class="n">la</span> <span class="n">raspberry</span><span class="p">,</span> <span class="n">sur</span> <span class="n">le</span> <span class="n">port</span> <span class="mi">1935</span> <span class="n">sur</span> <span class="n">le</span> <span class="n">r</span><span class="err">é</span><span class="n">pertoire</span> <span class="n">live</span>
</pre></div>
<hr>
<h1><a name="head1">1. </a>Principes de la vidéodiffusion</h1>
<p>Un système de vidéodiffusion (live streaming) est composé de 3 segments :</p>
<div class="highlight"><pre><span></span> <span class="n">encodage</span> <span class="o">-></span> <span class="n">serveur</span> <span class="n">vid</span><span class="err">é</span><span class="n">o</span> <span class="o">-></span> <span class="n">d</span><span class="err">é</span><span class="n">codeur</span><span class="o">/</span><span class="n">visualiseur</span>
</pre></div>
<p>Les deux premiers segments peuvent être assumés par la même machine mais dans ce cas la fonction serveur est limitée et on privilégie cet usage plutôt dans une logique point à point plutôt que pour un service de vidéodiffusion. Que l'on utilise une seule machine ou une série de machines dédiées plusieurs problèmes se posent :</p>
<div class="highlight"><pre><span></span><span class="o">*</span> <span class="n">Compatibilit</span><span class="err">é</span> <span class="n">des</span> <span class="n">formats</span> <span class="n">entre</span> <span class="n">segments</span>
<span class="o">*</span> <span class="n">choix</span> <span class="n">des</span> <span class="n">protocoles</span> <span class="n">de</span> <span class="n">transfert</span>
<span class="o">*</span> <span class="n">configuration</span> <span class="n">de</span> <span class="n">chacun</span> <span class="n">des</span> <span class="n">segments</span>
</pre></div>
<p>Il n'existe pas de solution unique générale, il est nécessaire d'établir le besoin, de comprendre les contraintes que cela entraine et de faire des choix en conséquence.</p>
<p>Aujourd'hui la vidéodiffusion en direct se fait selon deux protocoles principaux, soit une famille de protocoles dédiés : rtp://, rtmp://, rtsp:// ; soit plus "simplement" en http. Il existe bien sûr aussi un certain nombre de protocoles de communication </p>
<h1><a name="head2">2. </a>Configuration de l'encodeur</h1>
<p>la configuration de l'encodeur repose sur une bonne connaissance du matériel utilisé. L'exemple ci-dessous utilise la raspicam mais il fonctionne avec toute caméra connectée à la raspberry <strong>et reconnue</strong> par le système</p>
<h2><a name="head2.1">2.1. </a>Informations sur le matériel utilisé</h2>
<p>S'ils ne sont pas déjà installés sur le système ajouter les outils <code>video for linux (v4l v4l2)</code>, pour cela installer les paquets suivants :</p>
<div class="highlight"><pre><span></span>sudo apt install v4l-utils qv4l2
</pre></div>
<p>Une fois ces outils installés il est possible d'obtenir de nombreuses informations sur l'équipement que l'on utilise, le bloc ci-dessous propose une liste non exhaustive de commandes utiles. les commandes <code>v4l2-ctl</code> permettent de contrôler les paramètres d'acquisition de la caméra, les commandes <code>ffmpeg</code> permettent d'obtenir les informations sur les capacités de l'encodeur.</p>
<div class="highlight"><pre><span></span><span class="c1"># liste des caméras disponibles </span>
ens-ife<span class="o">[</span>~<span class="o">]</span> raspi9-€ : v4l2-ctl --list-devices
bcm2835-codec-decode <span class="o">(</span>platform:bcm2835-codec<span class="o">)</span>:
/dev/video10
/dev/video11
/dev/video12
mmal service <span class="m">16</span>.1 <span class="o">(</span>platform:bcm2835-v4l2<span class="o">)</span>:
/dev/video0
<span class="c1"># liste de l'état des paramètres de la caméra</span>
ens-ife<span class="o">[</span>~<span class="o">]</span> raspi9-€ : v4l2-ctl --log-status
Status Log:
<span class="o">[</span><span class="m">10566</span>.765068<span class="o">]</span> bcm2835-v4l2: <span class="o">=================</span> START <span class="nv">STATUS</span> <span class="o">=================</span>
<span class="o">[</span><span class="m">10566</span>.765082<span class="o">]</span> bcm2835-v4l2: Saturation: <span class="m">0</span>
<span class="o">[</span><span class="m">10566</span>.765093<span class="o">]</span> bcm2835-v4l2: Sharpness: <span class="m">0</span>
<span class="o">[</span><span class="m">10566</span>.765102<span class="o">]</span> bcm2835-v4l2: Contrast: <span class="m">0</span>
<span class="o">[</span><span class="m">10566</span>.765112<span class="o">]</span> bcm2835-v4l2: Brightness: <span class="m">50</span>
<span class="o">[</span><span class="m">10566</span>.765121<span class="o">]</span> bcm2835-v4l2: ISO Sensitivity: <span class="m">0</span>
<span class="o">[</span><span class="m">10566</span>.765131<span class="o">]</span> bcm2835-v4l2: ISO Sensitivity, Auto: Auto
<span class="o">[</span><span class="m">10566</span>.765141<span class="o">]</span> bcm2835-v4l2: Image Stabilization: <span class="nb">false</span>
<span class="o">[</span><span class="m">10566</span>.765150<span class="o">]</span> bcm2835-v4l2: Auto Exposure: Auto Mode
<span class="o">[</span><span class="m">10566</span>.765160<span class="o">]</span> bcm2835-v4l2: Exposure Time, Absolute: <span class="m">1000</span>
<span class="o">[</span><span class="m">10566</span>.765169<span class="o">]</span> bcm2835-v4l2: Auto Exposure, Bias: <span class="m">0</span>
<span class="o">[</span><span class="m">10566</span>.765179<span class="o">]</span> bcm2835-v4l2: Exposure, Dynamic Framerate: <span class="nb">false</span>
<span class="o">[</span><span class="m">10566</span>.765188<span class="o">]</span> bcm2835-v4l2: Exposure, Metering Mode: Average
<span class="o">[</span><span class="m">10566</span>.765198<span class="o">]</span> bcm2835-v4l2: White Balance, Auto <span class="p">&</span> Preset: Auto
<span class="o">[</span><span class="m">10566</span>.765207<span class="o">]</span> bcm2835-v4l2: Red Balance: <span class="m">1000</span>
<span class="o">[</span><span class="m">10566</span>.765216<span class="o">]</span> bcm2835-v4l2: Blue Balance: <span class="m">1000</span>
<span class="o">[</span><span class="m">10566</span>.765226<span class="o">]</span> bcm2835-v4l2: Color Effects: None
<span class="o">[</span><span class="m">10566</span>.765235<span class="o">]</span> bcm2835-v4l2: Color Effects, CbCr: <span class="m">32896</span>
<span class="o">[</span><span class="m">10566</span>.765244<span class="o">]</span> bcm2835-v4l2: Rotate: <span class="m">0</span>
<span class="o">[</span><span class="m">10566</span>.765254<span class="o">]</span> bcm2835-v4l2: Horizontal Flip: <span class="nb">false</span>
<span class="o">[</span><span class="m">10566</span>.765263<span class="o">]</span> bcm2835-v4l2: Vertical Flip: <span class="nb">false</span>
<span class="o">[</span><span class="m">10566</span>.765272<span class="o">]</span> bcm2835-v4l2: Video Bitrate Mode: Variable Bitrate
<span class="o">[</span><span class="m">10566</span>.765282<span class="o">]</span> bcm2835-v4l2: Video Bitrate: <span class="m">10000000</span>
<span class="o">[</span><span class="m">10566</span>.765291<span class="o">]</span> bcm2835-v4l2: Compression Quality: <span class="m">30</span>
<span class="o">[</span><span class="m">10566</span>.765301<span class="o">]</span> bcm2835-v4l2: Power Line Frequency: <span class="m">50</span> Hz
<span class="o">[</span><span class="m">10566</span>.765310<span class="o">]</span> bcm2835-v4l2: Repeat Sequence Header: <span class="nb">false</span>
<span class="o">[</span><span class="m">10566</span>.765319<span class="o">]</span> bcm2835-v4l2: H264 Profile: High
<span class="o">[</span><span class="m">10566</span>.765328<span class="o">]</span> bcm2835-v4l2: H264 Level: <span class="m">4</span>
<span class="o">[</span><span class="m">10566</span>.765337<span class="o">]</span> bcm2835-v4l2: Scene Mode: None
<span class="o">[</span><span class="m">10566</span>.765347<span class="o">]</span> bcm2835-v4l2: H264 I-Frame Period: <span class="m">60</span>
<span class="o">[</span><span class="m">10566</span>.765356<span class="o">]</span> bcm2835-v4l2: <span class="o">==================</span> END <span class="nv">STATUS</span> <span class="o">==================</span>
<span class="c1"># liste des formats disponibles en utilisant ffmpeg</span>
ens-ife<span class="o">[</span>~<span class="o">]</span> raspi9-€ : ffmpeg -f v4l2 -list_formats all -i /dev/video0
.../...
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Raw : yuv420p : Planar YUV <span class="m">4</span>:2:0 : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Raw : yuyv422 : YUYV <span class="m">4</span>:2:2 : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Raw : rgb24 : <span class="m">24</span>-bit RGB <span class="m">8</span>-8-8 : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Compressed: mjpeg : JFIF JPEG : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Compressed: h264 : H.264 : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Compressed: mjpeg : Motion-JPEG : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Raw : Unsupported : YVYU <span class="m">4</span>:2:2 : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Raw : Unsupported : VYUY <span class="m">4</span>:2:2 : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Raw : uyvy422 : UYVY <span class="m">4</span>:2:2 : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Raw : nv12 : Y/CbCr <span class="m">4</span>:2:0 : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Raw : bgr24 : <span class="m">24</span>-bit BGR <span class="m">8</span>-8-8 : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Raw : yuv420p : Planar YVU <span class="m">4</span>:2:0 : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Raw : Unsupported : Y/CrCb <span class="m">4</span>:2:0 : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
<span class="o">[</span>video4linux2,v4l2 @ 0x12121c0<span class="o">]</span> Raw : bgr0 : <span class="m">32</span>-bit BGRA/X <span class="m">8</span>-8-8-8 : <span class="o">{</span><span class="m">32</span>-3280, <span class="m">2</span><span class="o">}</span>x<span class="o">{</span><span class="m">32</span>-2464, <span class="m">2</span><span class="o">}</span>
</pre></div>
<h2><a name="head2.2">2.2. </a>Configuration de la caméra</h2>
<p>Cette configuration s'effectue avec l'outil <code>v4l2-ctl</code> plusieursoptions de la commande permettent de choisir la stratégie d'acquisition ; le nombre de paramètres et de menus est important la commande <code>v4l2-ctl --log-status</code> vue ci-dessus fournit l'état des réglages, la commande <code>v4l2-ctl -L</code> fournit le détail des options et des menus la commande ci-dessous permet d'avoir une version simplifiée.</p>
<div class="highlight"><pre><span></span>ens-ife<span class="o">[</span>~<span class="o">]</span> raspi9-€ : v4l2-ctl -l
User Controls
brightness 0x00980900 <span class="o">(</span>int<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">100</span> <span class="nv">step</span><span class="o">=</span><span class="m">1</span> <span class="nv">default</span><span class="o">=</span><span class="m">50</span> <span class="nv">value</span><span class="o">=</span><span class="m">50</span> <span class="nv">flags</span><span class="o">=</span>slider
contrast 0x00980901 <span class="o">(</span>int<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span>-100 <span class="nv">max</span><span class="o">=</span><span class="m">100</span> <span class="nv">step</span><span class="o">=</span><span class="m">1</span> <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span> <span class="nv">flags</span><span class="o">=</span>slider
saturation 0x00980902 <span class="o">(</span>int<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span>-100 <span class="nv">max</span><span class="o">=</span><span class="m">100</span> <span class="nv">step</span><span class="o">=</span><span class="m">1</span> <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span> <span class="nv">flags</span><span class="o">=</span>slider
red_balance 0x0098090e <span class="o">(</span>int<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">1</span> <span class="nv">max</span><span class="o">=</span><span class="m">7999</span> <span class="nv">step</span><span class="o">=</span><span class="m">1</span> <span class="nv">default</span><span class="o">=</span><span class="m">1000</span> <span class="nv">value</span><span class="o">=</span><span class="m">1000</span> <span class="nv">flags</span><span class="o">=</span>slider
blue_balance 0x0098090f <span class="o">(</span>int<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">1</span> <span class="nv">max</span><span class="o">=</span><span class="m">7999</span> <span class="nv">step</span><span class="o">=</span><span class="m">1</span> <span class="nv">default</span><span class="o">=</span><span class="m">1000</span> <span class="nv">value</span><span class="o">=</span><span class="m">1000</span> <span class="nv">flags</span><span class="o">=</span>slider
horizontal_flip 0x00980914 <span class="o">(</span>bool<span class="o">)</span> : <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span>
vertical_flip 0x00980915 <span class="o">(</span>bool<span class="o">)</span> : <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span>
power_line_frequency 0x00980918 <span class="o">(</span>menu<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">3</span> <span class="nv">default</span><span class="o">=</span><span class="m">1</span> <span class="nv">value</span><span class="o">=</span><span class="m">1</span>
sharpness 0x0098091b <span class="o">(</span>int<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span>-100 <span class="nv">max</span><span class="o">=</span><span class="m">100</span> <span class="nv">step</span><span class="o">=</span><span class="m">1</span> <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span> <span class="nv">flags</span><span class="o">=</span>slider
color_effects 0x0098091f <span class="o">(</span>menu<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">15</span> <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span>
rotate 0x00980922 <span class="o">(</span>int<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">360</span> <span class="nv">step</span><span class="o">=</span><span class="m">90</span> <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span> <span class="nv">flags</span><span class="o">=</span>modify-layout
color_effects_cbcr 0x0098092a <span class="o">(</span>int<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">65535</span> <span class="nv">step</span><span class="o">=</span><span class="m">1</span> <span class="nv">default</span><span class="o">=</span><span class="m">32896</span> <span class="nv">value</span><span class="o">=</span><span class="m">32896</span>
Codec Controls
video_bitrate_mode 0x009909ce <span class="o">(</span>menu<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">1</span> <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span> <span class="nv">flags</span><span class="o">=</span>update
video_bitrate 0x009909cf <span class="o">(</span>int<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">25000</span> <span class="nv">max</span><span class="o">=</span><span class="m">25000000</span> <span class="nv">step</span><span class="o">=</span><span class="m">25000</span> <span class="nv">default</span><span class="o">=</span><span class="m">10000000</span> <span class="nv">value</span><span class="o">=</span><span class="m">10000000</span>
repeat_sequence_header 0x009909e2 <span class="o">(</span>bool<span class="o">)</span> : <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span>
h264_i_frame_period 0x00990a66 <span class="o">(</span>int<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">2147483647</span> <span class="nv">step</span><span class="o">=</span><span class="m">1</span> <span class="nv">default</span><span class="o">=</span><span class="m">60</span> <span class="nv">value</span><span class="o">=</span><span class="m">60</span>
h264_level 0x00990a67 <span class="o">(</span>menu<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">11</span> <span class="nv">default</span><span class="o">=</span><span class="m">11</span> <span class="nv">value</span><span class="o">=</span><span class="m">11</span>
h264_profile 0x00990a6b <span class="o">(</span>menu<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">4</span> <span class="nv">default</span><span class="o">=</span><span class="m">4</span> <span class="nv">value</span><span class="o">=</span><span class="m">4</span>
Camera Controls
auto_exposure 0x009a0901 <span class="o">(</span>menu<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">3</span> <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span>
exposure_time_absolute 0x009a0902 <span class="o">(</span>int<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">1</span> <span class="nv">max</span><span class="o">=</span><span class="m">10000</span> <span class="nv">step</span><span class="o">=</span><span class="m">1</span> <span class="nv">default</span><span class="o">=</span><span class="m">1000</span> <span class="nv">value</span><span class="o">=</span><span class="m">1000</span>
exposure_dynamic_framerate 0x009a0903 <span class="o">(</span>bool<span class="o">)</span> : <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span>
auto_exposure_bias 0x009a0913 <span class="o">(</span>intmenu<span class="o">)</span>: <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">24</span> <span class="nv">default</span><span class="o">=</span><span class="m">12</span> <span class="nv">value</span><span class="o">=</span><span class="m">12</span>
white_balance_auto_preset 0x009a0914 <span class="o">(</span>menu<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">10</span> <span class="nv">default</span><span class="o">=</span><span class="m">1</span> <span class="nv">value</span><span class="o">=</span><span class="m">1</span>
image_stabilization 0x009a0916 <span class="o">(</span>bool<span class="o">)</span> : <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span>
iso_sensitivity 0x009a0917 <span class="o">(</span>intmenu<span class="o">)</span>: <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">4</span> <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span>
iso_sensitivity_auto 0x009a0918 <span class="o">(</span>menu<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">1</span> <span class="nv">default</span><span class="o">=</span><span class="m">1</span> <span class="nv">value</span><span class="o">=</span><span class="m">1</span>
exposure_metering_mode 0x009a0919 <span class="o">(</span>menu<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">2</span> <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span>
scene_mode 0x009a091a <span class="o">(</span>menu<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">0</span> <span class="nv">max</span><span class="o">=</span><span class="m">13</span> <span class="nv">default</span><span class="o">=</span><span class="m">0</span> <span class="nv">value</span><span class="o">=</span><span class="m">0</span>
JPEG Compression Controls
compression_quality 0x009d0903 <span class="o">(</span>int<span class="o">)</span> : <span class="nv">min</span><span class="o">=</span><span class="m">1</span> <span class="nv">max</span><span class="o">=</span><span class="m">100</span> <span class="nv">step</span><span class="o">=</span><span class="m">1</span> <span class="nv">default</span><span class="o">=</span><span class="m">30</span> <span class="nv">value</span><span class="o">=</span><span class="m">30</span>
</pre></div>
<p>Le choix de ces paramètres est plus important et délicat qu'il n'y parait et les valeurs par défaut ne conviennent pas forcément à ce que l'on souhaite faire. On notera par exemple que l'intervalle des Iframes est par défaut à 60 ce qui convient parffaitement pour un découpage de segments en secondes pour un encodage à 60 images/seconde mais si on encode à 25 images/seconde les choses deviennent compliquées car un segment requiert impérativement de débuter par une Iframe.... Ce point est crucial pour la vidéodiffusion en <code>HLS</code>.</p>
<p>Exemple de modification des paramètres avec la commande <code>v4l2-ctl -c</code> permettant le passage d'un flux variable à un flux fixe à 1500000 b/s (1.5 Mb/s) :</p>
<div class="highlight"><pre><span></span>ens-ife<span class="o">[</span>~<span class="o">]</span> raspi9-€ : v4l2-ctl -c <span class="nv">video_bitrate_mode</span><span class="o">=</span><span class="m">1</span>
ens-ife<span class="o">[</span>~<span class="o">]</span> raspi9-€ : v4l2-ctl -c <span class="nv">video_bitrate</span><span class="o">=</span><span class="m">1500000</span>
<span class="c1"># Visualisation des effets</span>
ens-ife<span class="o">[</span>~<span class="o">]</span> raspi9-€ : v4l2-ctl --log-status
Status Log:
<span class="o">[</span><span class="m">21317</span>.086681<span class="o">]</span> bcm2835-v4l2: <span class="o">=================</span> START <span class="nv">STATUS</span> <span class="o">=================</span>
.../...
<span class="o">[</span><span class="m">21317</span>.086886<span class="o">]</span> bcm2835-v4l2: Video Bitrate Mode: Constant Bitrate
<span class="o">[</span><span class="m">21317</span>.086896<span class="o">]</span> bcm2835-v4l2: Video Bitrate: <span class="m">1500000</span>
.../...
<span class="o">[</span><span class="m">21317</span>.086970<span class="o">]</span> bcm2835-v4l2: <span class="o">==================</span> END <span class="nv">STATUS</span> <span class="o">==================</span>
</pre></div>
<h2><a name="head2.3">2.3. </a>Les commandes d'acquisition et d'encodage <code>raspivid</code> et <code>ffmpeg</code></h2>
<p><code>raspivid</code> est le logiciel construit spécialement pour la raspicam et la raspberry, l'avantage est une optimisation forte mais l'inconvénient est la non portabilité des ce que l'on produit. <code>ffmpeg</code> est le couteau suisse de la vidéo, de nombreux logiciels reposent sur ce code (vlc,...), l'inconvénient est l'extrême flexibilité de cet outil proposée pour optimiser au maximum les performances ce qui se traduit par <em>énormément</em> d'options et parfois des pertes de performances dues à de mauvais choix de paramètres; l'avantage est est la portabilité totale et la capacité d'évolution au cours du temps.</p>
<p>Nous privilégions ici l'utilisation de <code>ffmpeg</code> à des fins d'interopérabilité et pour permettre de prendre en compte le maximum de matériels. Le bloc ci-dessous présente quelques exemples d'utilisation de <code>raspivid</code> dans un mode production de fichier local ou streaming.</p>
<div class="highlight"><pre><span></span>raspivid -t <span class="m">0</span> -w <span class="m">240</span> -h <span class="m">135</span> -b <span class="m">512000</span> -fps <span class="m">15</span> -g <span class="m">5</span>/15 -o - -pf main -v <span class="p">|</span> ffmpeg -i - -an -vcodec copy -f rtp_mpegts -r <span class="m">15</span> rtp://192.168.221.52:1935/live
raspivid -t <span class="m">0</span> -w <span class="m">480</span> -h <span class="m">270</span> -b <span class="m">512000</span> -fps <span class="m">15</span> -g <span class="m">5</span>/15 -o - -pf main -v <span class="p">|</span> ffmpeg -i - -an -vcodec copy -f rtp_mpegts -r <span class="m">15</span> rtp://192.168.221.32:1935/live
raspivid -w <span class="m">960</span> -h <span class="m">540</span> -b <span class="m">2000000</span> -v -t <span class="m">0</span> -fps <span class="m">25</span>.0 -k -o test.mp4
raspivid -t <span class="m">0</span> -w <span class="m">960</span> -h <span class="m">540</span> -o - <span class="p">|</span> ffmpeg -i - -f rtp rtmp://192.168.221.118:1935/live
raspivid -t <span class="m">10000</span> -w <span class="m">480</span> -h <span class="m">270</span> -b <span class="m">512000</span> -fps <span class="m">25</span> -g <span class="m">5</span>/25 -pf main -o test.mp4 -v
raspivid -t <span class="m">20000</span> -w <span class="m">480</span> -h <span class="m">270</span> -b <span class="m">512000</span> -fps <span class="m">25</span> -g <span class="m">5</span>/25 -pf main -o test.mp4 -v
raspivid -t <span class="m">20000</span> -w <span class="m">480</span> -h <span class="m">270</span> -b <span class="m">512000</span> -fps <span class="m">25</span> -g <span class="m">5</span>/25 -pf main -o - -v <span class="p">|</span> ffmpeg -i - -vcodec copy -an -f rtp rtp://192.168.221.118/live
raspivid -t <span class="m">0</span> -ex night -w <span class="m">480</span> -h <span class="m">270</span> -b <span class="m">512000</span> -fps <span class="m">25</span> -g <span class="m">5</span>/25 -pf main -o - -v <span class="p">|</span> ffmpeg -re -thread_queue_size <span class="m">4</span> -i - -strict -2 -vcodec copy -an -f
raspivid -t <span class="m">0</span> -ex night -w <span class="m">960</span> -h <span class="m">540</span> -b <span class="m">1024000</span> -fps <span class="m">25</span> -g <span class="m">5</span>/25 -pf main -o - -v <span class="p">|</span> ffmpeg -i - -f rtp_mpegts -r <span class="m">25</span> rtp://192.168.221.118:1935/live
</pre></div>
<p>Les exemples ci-dessous sont opérationnels et démontrent l'utilisation de quelques paramètres. Le protocole <code>rtp://</code> ne permet apparemment pas de faire du multicast (regarder le flux vidéo sur plusieurs postes par contre le flux <code>rtmp://</code> le permet. Dans l'exemple suivant on utilise je format <code>flv</code> (flash) en sortie qui est le plus accessible ainsi que le format <code>v4l2</code> qui permet la plus large interopérabilité. De nombreuses autres configurations sont possibles, nous n'explorerons pas cet univers mais toutes les contributions sont bienvenues ici.</p>
<div class="highlight"><pre><span></span>ffmpeg -f v4l2 -r <span class="m">25</span> -pix_fmt h264 -video_size 640x360 -i /dev/video0 -c:v libx264 -an -b:v 1600k -preset veryfast -f flv -r <span class="m">25</span> rtmp://192.168.221.37:1935/live
ffmpeg -f v4l2 -r <span class="m">25</span> -pix_fmt h264 -video_size 1280x720 -i /dev/video0 -c:v libx264 -an -b:v 1600k -preset ultrafast -f flv -r <span class="m">25</span> rtmp://192.168.221.37:1935/live
ffmpeg -f v4l2 -r <span class="m">25</span> -pix_fmt h264 -video_size 640x360 -i /dev/video0 -c:v libx264 -an -b:v 1600k -preset fast -f flv -r <span class="m">25</span> rtmp://192.168.221.37:1935/live
</pre></div>
<h1><a name="head3">3. </a>Configuration du serveur et format du flux transporté</h1>
<p>L'évolution importante de la vidéo sur le web a conduit à une simplification radicale de la chaine de vidéodiffusion, il y a une dizaine d'années les outils d'encodage, les serveurs et les visionneurs étaient des logiciels dédiés souvent construits sur un format ou un protocole particulier. Aujourd'hui l'encodage peut se faire via un outil généraliste (<code>ffmpeg</code>) les serveurs web modernes (<code>nginx</code>) proposent les protocoles de vidéodiffusion (<code>rtmp</code>, <code>hls</code>) au même titre que l'hypertexte (<code>http</code>), et les navigateurs web ou les logiciels de visualisation de films ordinaires acceptent de restituer vidéo à la demande ou vidéodiffusion, la contrepartie est l'utilisation de standards.</p>
<p>Ces standards s'appliquent de bout en bout et du fait de la pression du marché économique autour de la vidéo il n'existe pas de solution "clef en main" en logiciel libre, la communauté ayant mis en place une grande variété de solutions. Le seul point invariant de tout le système est le flux transporté. Nous avons déjà vu ci-dessus le flux au format <code>flv</code> transporté via le protocole <code>rtmp</code>; nous allons aborder maintenant un flux au format <code>HLS</code> transporté via le protocole <code>http</code>.</p>
<h1><a name="head3.1">3.1. </a>Le serveur web <code>nginx rtmp</code></h1>
<p><code>nginx</code> est le logiciel de serveurs web qui tend à se répendre rapidement aux dépens d'apache, de nombreux serveurs <code>nodejs</code> apparaissent aussi du fait de la simplicité de la mise en oeuvre de sites web avec nodeJS. Nous utilisons ici la version <code>nginx-extras</code> du serveur nginx.</p>
<p>Pour mettre en place un serveur vidéo il suffit de rajouter la configuration du protocole <code>rtmp</code> au fichier de configuration <code>/etc/nginx/nginx.conf</code> comme indiqué ci dessous. Toutes les précisions se trouvent sur la <a href="https://github.com/arut/nginx-rtmp-module/wiki/Directives#rtmp">documentation nginx-rtmp</a>.</p>
<div class="highlight"><pre><span></span>rtmp <span class="o">{</span>
server <span class="o">{</span>
listen <span class="m">1935</span><span class="p">;</span>
chunk_size <span class="m">4096</span><span class="p">;</span>
application live <span class="o">{</span>
live on<span class="p">;</span>
record off<span class="p">;</span>
allow publish all<span class="p">;</span>
allow play all<span class="p">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<div class="highlight"><pre><span></span><span class="o">*</span> <span class="ss">`rtmp`</span> <span class="n">au</span> <span class="n">m</span><span class="err">ê</span><span class="n">me</span> <span class="n">titre</span> <span class="n">que</span> <span class="ss">`http`</span> <span class="n">d</span><span class="err">é</span><span class="n">signe</span> <span class="n">le</span> <span class="n">protocole</span>
<span class="o">*</span> <span class="ss">`server`</span> <span class="n">impos</span><span class="err">é</span> <span class="n">par</span> <span class="n">la</span> <span class="n">syntaxe</span> <span class="n">de</span> <span class="n">la</span> <span class="n">configuration</span> <span class="n">nginx</span> <span class="n">indique</span> <span class="n">que</span> <span class="n">l</span><span class="s1">'on décrit un serveur en ligne</span>
<span class="s1">* `listen` imposé par la syntaxe de la configuration nginx désigne le port d'</span><span class="err">é</span><span class="n">coute</span> <span class="o">-></span> <span class="mi">1935</span>
<span class="o">*</span> <span class="ss">`chunk_size`</span> <span class="n">d</span><span class="err">é</span><span class="n">crit</span> <span class="n">la</span> <span class="n">taille</span> <span class="n">des</span> <span class="n">morceaux</span> <span class="n">d</span><span class="err">é</span><span class="n">coup</span><span class="err">é</span><span class="n">s</span> <span class="n">pour</span> <span class="n">le</span> <span class="n">multiplexage</span>
<span class="o">*</span> <span class="ss">`application`</span> <span class="n">d</span><span class="err">é</span><span class="n">claration</span> <span class="n">d</span><span class="s1">'un flux `rtmp`</span>
<span class="s1">* `live` activation/désactivation du mode vidéodiffusion en direct</span>
<span class="s1">* `record` activation/désactivation de l'</span><span class="n">enregistrement</span>
<span class="o">*</span> <span class="ss">`allow`</span> <span class="p">(</span><span class="ss">`deny`</span><span class="p">)</span> <span class="ss">`publish`</span> <span class="o">/</span> <span class="ss">`play`</span> <span class="n">gestion</span> <span class="n">de</span> <span class="n">la</span> <span class="n">publication</span> <span class="n">et</span> <span class="n">de</span> <span class="n">la</span> <span class="n">diffusion</span>
</pre></div>
<p>De nombreuses options sont disponibles pour gérer tous les paramètres du serveur, se reporter à la <a href="https://github.com/arut/nginx-rtmp-module/wiki/Directives#rtmp">documentation nginx-rtmp</a> pour toutes les précisions possibles.</p>
<h1><a name="head3.2">3.2. </a>Le serveur web <code>nginx HLS</code></h1>
<p>La mise en place d'un flux <code>hls</code> est un peu plus compexe et requiert à la fois la configuration d'une application <code>hls</code> dans le serveur <code>rtmp</code> et la mise en place d'un point de diffusion dans le serveur <code>http</code>. Le bloc ci-dessous propose une configuration simple via le fichier <code>/etc/nginx/nginx.conf</code> qui peut servir de point de départ à des configurations plus élaborées (prenant en compte les flux les tailles les codecs).
Attention les fragments doivent impérativement commencer par ine Iframe bien ajuster les paramètres de l'encodeur et du serveur.</p>
<div class="highlight"><pre><span></span><span class="c1">#For good HLS experience we recommend using 3 seconds fragments with 60 seconds playlist.</span>
rtmp <span class="o">{</span>
server <span class="o">{</span>
listen <span class="m">1935</span><span class="p">;</span> <span class="c1"># Listen on standard RTMP port</span>
chunk_size <span class="m">4000</span><span class="p">;</span>
application hls <span class="o">{</span>
live on<span class="p">;</span>
<span class="c1"># Turn on HLS</span>
hls on<span class="p">;</span>
hls_path /mnt/hls/<span class="p">;</span>
hls_fragment <span class="m">3</span><span class="p">;</span>
hls_playlist_length <span class="m">60</span><span class="p">;</span>
<span class="c1"># disable consuming the stream from nginx as rtmp</span>
deny play all<span class="p">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>Le bloc suivant est une proposition de point d'accès <code>hls</code> sur le serveur <code>http</code>. cat > /etc/nginx/sites-available/10-hls</p>
<div class="highlight"><pre><span></span>#Since HLS consists of static files, a simple http server can be set up with two additions, correct MIME types and CORS headers.
server {
listen 8080;
location /hls {
# Disable cache
add_header Cache-Control no-cache;
# CORS setup
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length';
# allow CORS preflight requests
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /mnt/;
}
}
</pre></div>
<p>Lecture du stream rtmp pour hls.</p>
<p>http://192.168.221.38:1935/hls/test</p>
<h1><a name="head3.2.1">3.2.1. </a>Configuration d'un serveur <code>HLS</code> avec <code>ffmpeg</code></h1>
<p>Comme cela a été dit en introduction de ce chapître l'encodage <code>hls</code> est un peu plus compliqué, nous allons procéder étape par étape et d'abord considérer les paramètres de l'encoder <code>ffmpeg</code> avec la commande :</p>
<div class="highlight"><pre><span></span>ens-ife<span class="o">[</span>~<span class="o">]</span> raspi9-€ : ffmpeg -h <span class="nv">muxer</span><span class="o">=</span>hls
.../...
Muxer hls <span class="o">[</span>Apple HTTP Live Streaming<span class="o">]</span>:
Common extensions: m3u8.
Default video codec: h264.
Default audio codec: aac.
Default subtitle codec: webvtt.
hls muxer AVOptions:
-start_number <int64> E........ <span class="nb">set</span> first number in the sequence <span class="o">(</span>from <span class="m">0</span> to I64_MAX<span class="o">)</span> <span class="o">(</span>default <span class="m">0</span><span class="o">)</span>
-hls_time <float> E........ <span class="nb">set</span> segment length in seconds <span class="o">(</span>from <span class="m">0</span> to FLT_MAX<span class="o">)</span> <span class="o">(</span>default <span class="m">2</span><span class="o">)</span>
-hls_init_time <float> E........ <span class="nb">set</span> segment length in seconds at init list <span class="o">(</span>from <span class="m">0</span> to FLT_MAX<span class="o">)</span> <span class="o">(</span>default <span class="m">0</span><span class="o">)</span>
-hls_list_size <int> E........ <span class="nb">set</span> maximum number of playlist entries <span class="o">(</span>from <span class="m">0</span> to INT_MAX<span class="o">)</span> <span class="o">(</span>default <span class="m">5</span><span class="o">)</span>
-hls_delete_threshold <int> E........ <span class="nb">set</span> number of unreferenced segments to keep before deleting <span class="o">(</span>from <span class="m">1</span> to INT_MAX<span class="o">)</span> <span class="o">(</span>default <span class="m">1</span><span class="o">)</span>
-hls_ts_options <string> E........ <span class="nb">set</span> hls mpegts list of options <span class="k">for</span> the container format used <span class="k">for</span> hls
-hls_vtt_options <string> E........ <span class="nb">set</span> hls vtt list of options <span class="k">for</span> the container format used <span class="k">for</span> hls
-hls_wrap <int> E........ <span class="nb">set</span> number after which the index wraps <span class="o">(</span>will be deprecated<span class="o">)</span> <span class="o">(</span>from <span class="m">0</span> to INT_MAX<span class="o">)</span> <span class="o">(</span>default <span class="m">0</span><span class="o">)</span>
-hls_allow_cache <int> E........ explicitly <span class="nb">set</span> whether the client MAY <span class="o">(</span><span class="m">1</span><span class="o">)</span> or MUST NOT <span class="o">(</span><span class="m">0</span><span class="o">)</span> cache media segments <span class="o">(</span>from INT_MIN to INT_MAX<span class="o">)</span> <span class="o">(</span>default -1<span class="o">)</span>
-hls_base_url <string> E........ url to prepend to each playlist entry
-hls_segment_filename <string> E........ filename template <span class="k">for</span> segment files
-hls_segment_size <int> E........ maximum size per segment file, <span class="o">(</span>in bytes<span class="o">)</span> <span class="o">(</span>from <span class="m">0</span> to INT_MAX<span class="o">)</span> <span class="o">(</span>default <span class="m">0</span><span class="o">)</span>
-hls_key_info_file <string> E........ file with key URI and key file path
-hls_enc <boolean> E........ <span class="nb">enable</span> AES128 encryption support <span class="o">(</span>default <span class="nb">false</span><span class="o">)</span>
-hls_enc_key <string> E........ hex-coded <span class="m">16</span> byte key to encrypt the segments
-hls_enc_key_url <string> E........ url to access the key to decrypt the segments
-hls_enc_iv <string> E........ hex-coded <span class="m">16</span> byte initialization vector
-hls_subtitle_path <string> E........ <span class="nb">set</span> path of hls subtitles
-hls_segment_type <int> E........ <span class="nb">set</span> hls segment files <span class="nb">type</span> <span class="o">(</span>from <span class="m">0</span> to <span class="m">1</span><span class="o">)</span> <span class="o">(</span>default mpegts<span class="o">)</span>
mpegts E........ make segment file to mpegts files in m3u8
fmp4 E........ make segment file to fragment mp4 files in m3u8
-hls_fmp4_init_filename <string> E........ <span class="nb">set</span> fragment mp4 file init filename <span class="o">(</span>default <span class="s2">"init.mp4"</span><span class="o">)</span>
-hls_flags <flags> E........ <span class="nb">set</span> flags affecting HLS playlist and media file generation <span class="o">(</span>default <span class="m">0</span><span class="o">)</span>
single_file E........ generate a single media file indexed with byte ranges
temp_file E........ write segment to temporary file and rename when <span class="nb">complete</span>
delete_segments E........ delete segment files that are no longer part of the playlist
round_durations E........ round durations in m3u8 to whole numbers
discont_start E........ start the playlist with a discontinuity tag
omit_endlist E........ Do not append an endlist when ending stream
split_by_time E........ split the hls segment by <span class="nb">time</span> which user <span class="nb">set</span> by hls_time
append_list E........ append the new segments into old hls segment list
program_date_time E........ add EXT-X-PROGRAM-DATE-TIME
second_level_segment_index E........ include segment index in segment filenames when use_localtime
second_level_segment_duration E........ include segment duration in segment filenames when use_localtime
second_level_segment_size E........ include segment size in segment filenames when use_localtime
periodic_rekey E........ reload keyinfo file periodically <span class="k">for</span> re-keying
independent_segments E........ add EXT-X-INDEPENDENT-SEGMENTS, whenever applicable
-use_localtime <boolean> E........ <span class="nb">set</span> filename expansion with strftime at segment creation<span class="o">(</span>will be deprecated <span class="o">)</span> <span class="o">(</span>default <span class="nb">false</span><span class="o">)</span>
-strftime <boolean> E........ <span class="nb">set</span> filename expansion with strftime at segment creation <span class="o">(</span>default <span class="nb">false</span><span class="o">)</span>
-use_localtime_mkdir <boolean> E........ create last directory component in strftime-generated filename<span class="o">(</span>will be deprecated<span class="o">)</span> <span class="o">(</span>default <span class="nb">false</span><span class="o">)</span>
-strftime_mkdir <boolean> E........ create last directory component in strftime-generated filename <span class="o">(</span>default <span class="nb">false</span><span class="o">)</span>
-hls_playlist_type <int> E........ <span class="nb">set</span> the HLS playlist <span class="nb">type</span> <span class="o">(</span>from <span class="m">0</span> to <span class="m">2</span><span class="o">)</span> <span class="o">(</span>default <span class="m">0</span><span class="o">)</span>
event E........ EVENT playlist
vod E........ VOD playlist
-method <string> E........ <span class="nb">set</span> the HTTP method<span class="o">(</span>default: PUT<span class="o">)</span>
-hls_start_number_source <int> E........ <span class="nb">set</span> <span class="nb">source</span> of first number in sequence <span class="o">(</span>from <span class="m">0</span> to <span class="m">2</span><span class="o">)</span> <span class="o">(</span>default generic<span class="o">)</span>
generic E........ start_number value <span class="o">(</span>default<span class="o">)</span>
epoch E........ seconds since epoch
datetime E........ current datetime as YYYYMMDDhhmmss
-http_user_agent <string> E........ override User-Agent field in HTTP header
-var_stream_map <string> E........ Variant stream map string
-cc_stream_map <string> E........ Closed captions stream map string
-master_pl_name <string> E........ Create HLS master playlist with this name
-master_pl_publish_rate <int> E........ Publish master play list every after this many segment intervals <span class="o">(</span>from <span class="m">0</span> to UINT32_MAX<span class="o">)</span> <span class="o">(</span>default <span class="m">0</span><span class="o">)</span>
-http_persistent <boolean> E........ Use persistent HTTP connections <span class="o">(</span>default <span class="nb">false</span><span class="o">)</span>
-timeout <duration> E........ <span class="nb">set</span> timeout <span class="k">for</span> socket I/O operations <span class="o">(</span>default -0.000001<span class="o">)</span>
</pre></div>
<p>Instruction pour un streaming direct depuis la raspberry sur le serveur vidéo <code>192.168.221.37:1935</code> ou dans le fichier <code>out.m3u8</code> :</p>
<div class="highlight"><pre><span></span>ffmpeg -f v4l2 -r <span class="m">25</span> -pix_fmt h264 -video_size 640x360 -i /dev/video0 -f alsa -ac <span class="m">1</span> -i hw:1,0 -c:v libx264 -b:v 800k -preset ultrafast -b:a 64k -f flv -r <span class="m">25</span> rtmp://192.168.221.37:1935/hls/live
ffmpeg -f v4l2 -r <span class="m">25</span> -pix_fmt h264 -video_size 640x360 -i /dev/video0 -c:v h264 -flags +cgop -g <span class="m">25</span> -hls_time <span class="m">1</span> out.m3u8
ffmpeg -f v4l2 -r <span class="m">25</span> -video_size 640x360 -i /dev/video0 -f alsa -i hw:1,0 -c:v libx265 -b:v 600k -preset ultrafast -c:a aac -b:a 64k -ac <span class="m">2</span> -r <span class="m">25</span> -f hls -method PUT -hls_time <span class="m">10</span> -hls_playlist_type event -hls_segment_type <span class="m">1</span> /tmp/test.m3u8
</pre></div>
<h1><a name="head3.3">3.3. </a>Le serveur web <code>nginx DASH</code></h1>
<p>La configuration du mode <code>DASH</code> est un petit peu plus simple que celle du <code>HLS</code> mais requiert tout de même un peu d'attention pour le paramétrisation.</p>
<div class="highlight"><pre><span></span>ffmpeg -h <span class="nv">muxer</span><span class="o">=</span>dash
.../...
Muxer dash <span class="o">[</span>DASH Muxer<span class="o">]</span>:
Common extensions: mpd.
Default video codec: h264.
Default audio codec: aac.
dash muxer AVOptions:
-adaptation_sets <string> E........ Adaptation sets. Syntax: <span class="nv">id</span><span class="o">=</span><span class="m">0</span>,streams<span class="o">=</span><span class="m">0</span>,1,2 <span class="nv">id</span><span class="o">=</span><span class="m">1</span>,streams<span class="o">=</span><span class="m">3</span>,4 and so on
-window_size <int> E........ number of segments kept in the manifest <span class="o">(</span>from <span class="m">0</span> to INT_MAX<span class="o">)</span> <span class="o">(</span>default <span class="m">0</span><span class="o">)</span>
-extra_window_size <int> E........ number of segments kept outside of the manifest before removing from disk <span class="o">(</span>from <span class="m">0</span> to INT_MAX<span class="o">)</span> <span class="o">(</span>default <span class="m">5</span><span class="o">)</span>
-min_seg_duration <int> E........ minimum segment duration <span class="o">(</span>in microseconds<span class="o">)</span> <span class="o">(</span>will be deprecated<span class="o">)</span> <span class="o">(</span>from <span class="m">0</span> to INT_MAX<span class="o">)</span> <span class="o">(</span>default 5e+06<span class="o">)</span>
-seg_duration <duration> E........ segment duration <span class="o">(</span>in seconds, fractional value can be <span class="nb">set</span><span class="o">)</span> <span class="o">(</span>default <span class="m">5</span><span class="o">)</span>
-remove_at_exit <boolean> E........ remove all segments when finished <span class="o">(</span>default <span class="nb">false</span><span class="o">)</span>
-use_template <boolean> E........ Use SegmentTemplate instead of SegmentList <span class="o">(</span>default <span class="nb">true</span><span class="o">)</span>
-use_timeline <boolean> E........ Use SegmentTimeline in SegmentTemplate <span class="o">(</span>default <span class="nb">true</span><span class="o">)</span>
-single_file <boolean> E........ Store all segments in one file, accessed using byte ranges <span class="o">(</span>default <span class="nb">false</span><span class="o">)</span>
-single_file_name <string> E........ DASH-templated name to be used <span class="k">for</span> baseURL. Implies storing all segments in one file, accessed using byte ranges
-init_seg_name <string> E........ DASH-templated name to used <span class="k">for</span> the initialization segment <span class="o">(</span>default <span class="s2">"init-stream</span><span class="nv">$RepresentationID</span>$<span class="s2">.m4s"</span><span class="o">)</span>
-media_seg_name <string> E........ DASH-templated name to used <span class="k">for</span> the media segments <span class="o">(</span>default <span class="s2">"chunk-stream</span><span class="nv">$RepresentationID$-$Number</span><span class="s2">%05d</span>$<span class="s2">.m4s"</span><span class="o">)</span>
-utc_timing_url <string> E........ URL of the page that will <span class="k">return</span> the UTC timestamp in ISO format
-method <string> E........ <span class="nb">set</span> the HTTP method
-http_user_agent <string> E........ override User-Agent field in HTTP header
-http_persistent <boolean> E........ Use persistent HTTP connections <span class="o">(</span>default <span class="nb">false</span><span class="o">)</span>
-hls_playlist <boolean> E........ Generate HLS playlist files<span class="o">(</span>master.m3u8, media_%d.m3u8<span class="o">)</span> <span class="o">(</span>default <span class="nb">false</span><span class="o">)</span>
-streaming <boolean> E........ Enable/Disable streaming mode of output. Each frame will be moof fragment <span class="o">(</span>default <span class="nb">false</span><span class="o">)</span>
-timeout <duration> E........ <span class="nb">set</span> timeout <span class="k">for</span> socket I/O operations <span class="o">(</span>default -0.000001<span class="o">)</span>
-index_correction <boolean> E........ Enable/Disable segment index correction logic <span class="o">(</span>default <span class="nb">false</span><span class="o">)</span>
-format_options <string> E........ <span class="nb">set</span> list of options <span class="k">for</span> the container format <span class="o">(</span>mp4/webm<span class="o">)</span> used <span class="k">for</span> dash
-dash_segment_type <int> E........ <span class="nb">set</span> dash segment files <span class="nb">type</span> <span class="o">(</span>from <span class="m">0</span> to <span class="m">1</span><span class="o">)</span> <span class="o">(</span>default mp4<span class="o">)</span>
mp4 E........ make segment file in ISOBMFF format
webm E........ make segment file in WebM format
</pre></div>
<p>Encodage de la video seule avec un seul flux. les paramètres de la vidéo sont fournis avec la variable externe <code>VP9_LIVE_PARAMS="-speed 6 -tile-columns 4 -frame-parallel 1 -threads 8 -static-thresh 0 -max-intra-rate 300 -deadline realtime -lag-in-frames 0 -error-resilient 1"</code></p>
<div class="highlight"><pre><span></span>ffmpeg <span class="se">\</span>
-f v4l2 -input_format mjpeg -r <span class="m">30</span> -s 1280x720 -i /dev/video0 <span class="se">\</span>
-pix_fmt yuv420p <span class="se">\</span>
-c:v libvpx-vp9 <span class="se">\</span>
-s 1280x720 -keyint_min <span class="m">60</span> -g <span class="m">60</span> <span class="si">${</span><span class="nv">VP9_LIVE_PARAMS</span><span class="si">}</span> <span class="se">\</span>
-b:v 3000k <span class="se">\</span>
-f webm_chunk <span class="se">\</span>
-header <span class="s2">"/var/www/webm_live/glass_360.hdr"</span> <span class="se">\</span>
-chunk_start_index <span class="m">1</span> <span class="se">\</span>
/var/www/webm_live/glass_360_%d.chk <span class="se">\</span>
</pre></div>
<p>Encodage audio video avec un seul flux</p>
<div class="highlight"><pre><span></span>ffmpeg <span class="se">\</span>
-f v4l2 -input_format mjpeg -r <span class="m">30</span> -s 1280x720 -i /dev/video0 <span class="se">\</span>
-f alsa -ar <span class="m">44100</span> -ac <span class="m">2</span> -i hw:2 <span class="se">\</span>
-map <span class="m">0</span>:0 <span class="se">\</span>
-pix_fmt yuv420p <span class="se">\</span>
-c:v libvpx-vp9 <span class="se">\</span>
-s 1280x720 -keyint_min <span class="m">60</span> -g <span class="m">60</span> <span class="si">${</span><span class="nv">VP9_LIVE_PARAMS</span><span class="si">}</span> <span class="se">\</span>
-b:v 3000k <span class="se">\</span>
-f webm_chunk <span class="se">\</span>
-header <span class="s2">"/var/www/webm_live/glass_360.hdr"</span> <span class="se">\</span>
-chunk_start_index <span class="m">1</span> <span class="se">\</span>
/var/www/webm_live/glass_360_%d.chk <span class="se">\</span>
-map <span class="m">1</span>:0 <span class="se">\</span>
-c:a libvorbis <span class="se">\</span>
-b:a 128k -ar <span class="m">44100</span> <span class="se">\</span>
-f webm_chunk <span class="se">\</span>
-audio_chunk_duration <span class="m">2000</span> <span class="se">\</span>
-header /var/www/webm_live/glass_171.hdr <span class="se">\</span>
-chunk_start_index <span class="m">1</span> <span class="se">\</span>
/var/www/webm_live/glass_171_%d.chk<span class="sb">```</span>
Instruction pour un streaming direct depuis la raspberry sur le serveur vidéo <span class="sb">`</span><span class="m">192</span>.168.221.37:1935<span class="sb">`</span> :
<span class="sb">```</span>shell
ffmpeg -f v4l2 -r <span class="m">25</span> -pix_fmt h264 -video_size 640x360 -i /dev/video0 -f alsa -ac <span class="m">1</span> -i hw:1,0 -c:v libx264 -b:v 800k -preset ultrafast -b:a 64k -f flv -r <span class="m">25</span> rtmp://192.168.221.37:1935/hls/test
</pre></div>
<h1><a name="head3.4">3.4. </a>Raspberry Pi comme encodeur et serveur</h1>
<p>Comme expliqué au début la chaîne de vidéodiffusion est composé d'éléments indépendants il est donc possible de donner à la Raspberry Pi les deux fonctions : encodeur et serveur. Il suffit pour cela de remplacer l'adresse du serveur par l'adresse locale de la raspberry <code>127.0.0.1</code>. Il suffit alors de se connecter avec un lecteur de flux vidéo et le tour est joué.</p>
<div class="highlight"><pre><span></span>ffmpeg -f v4l2 -r <span class="m">25</span> -pix_fmt h264 -video_size 640x360 -i /dev/video0 -c:v libx264 -an -b:v 1500k -preset veryfast -f flv -r <span class="m">25</span> rtmp://127.0.0.1:1935/live
</pre></div>
<p>Pour le hls</p>
<div class="highlight"><pre><span></span>ffmpeg -f v4l2 -r <span class="m">25</span> -pix_fmt h264 -video_size 640x360 -i /dev/video0 -c:v libx264 -an -b:v 1500k -preset veryfast -f flv -r <span class="m">25</span> rtmp://127.0.0.1:1935/hls/test
</pre></div>
<p>Il est impératif aussi de modifier le configuration du serveur nginx de la raspberry pour qu'il soit capable de servir le <code>rtmp</code>, le <code>hls</code> et le <code>dash</code> on regroupe donc les configurations vues précédemment :</p>
<div class="highlight"><pre><span></span><span class="err">rtmp</span> <span class="p">{</span>
<span class="err">server</span> <span class="err">{</span>
<span class="err">listen</span> <span class="err">1935;</span>
<span class="err">chunk_size</span> <span class="err">4096;</span>
<span class="err">application</span> <span class="err">live</span> <span class="err">{</span>
<span class="err">live</span> <span class="err">on;</span>
<span class="err">record</span> <span class="err">off;</span>
<span class="err">allow</span> <span class="err">publish</span> <span class="err">all;</span>
<span class="err">allow</span> <span class="err">play</span> <span class="err">all;</span>
<span class="p">}</span>
<span class="err">application</span> <span class="err">hls</span> <span class="p">{</span>
<span class="err">live</span> <span class="err">on;</span>
<span class="err">hls</span> <span class="err">on;</span>
<span class="err">hls_cleanup</span> <span class="err">on;</span>
<span class="err">hls_sync</span> <span class="err">100ms;</span>
<span class="err">hls_fragment</span> <span class="err">2s;</span>
<span class="err">hls_path</span> <span class="err">/tmp/hls;</span>
<span class="err">allow</span> <span class="err">play</span> <span class="err">all;</span>
<span class="p">}</span>
<span class="err">application</span> <span class="err">dash</span> <span class="p">{</span>
<span class="err">live</span> <span class="err">on;</span>
<span class="err">dash</span> <span class="err">on;</span>
<span class="err">dash_path</span> <span class="err">/tmp/dash;</span>
<span class="err">allow</span> <span class="err">play</span> <span class="err">all;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="err">}</span>
</pre></div>
<h2>variantes</h2>
<p>Utilisation de la commande <code>exec_pull</code> pour convertir le format rtmp avec ffmpeg.</p>
<div class="highlight"><pre><span></span>rtmp <span class="o">{</span>
access_log /var/log/nginx/rtmp_access.log<span class="p">;</span>
server <span class="o">{</span>
listen <span class="m">1935</span><span class="p">;</span>
ping 30s<span class="p">;</span>
notify_method get<span class="p">;</span>
application camera1 <span class="o">{</span>
live on<span class="p">;</span>
exec_pull ffmpeg -i rtsp://admin:admin@10.10.10.11/axis-media/media.amp -threads <span class="m">2</span> -f flv -r <span class="m">25</span> -s 1280x720 -an rtmp://localhost:1935/cam1/stream <span class="m">2</span>>>/var/log/nginx/ffmpeg.log<span class="p">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<div class="highlight"><pre><span></span>rtmp <span class="o">{</span>
server <span class="o">{</span>
listen <span class="m">1935</span><span class="p">;</span>
chunk_size <span class="m">4096</span><span class="p">;</span>
application live <span class="o">{</span>
live on<span class="p">;</span>
record off<span class="p">;</span>
hls on<span class="p">;</span>
hls_nested on<span class="p">;</span>
hls_path /usr/local/nginx/html/hls/<span class="p">;</span>
hls_fragment <span class="m">3</span><span class="p">;</span>
hls_playlist_length <span class="m">60</span><span class="p">;</span>
exec_pull /usr/bin/ffmpeg -i rtsp://10.103.0.77:8050/<span class="nv">$name</span> -vcodec copy -acodec copy -f flv rtmp://10.103.2.106:1935/live/<span class="nv">$name</span><span class="p">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<h1><a name="head4">4. </a>Configuration du player dans une page web</h1>
<p>Ajout d'un player <code>nodejs</code> via <code>sudo npm install -g --upgrade video.js</code></p>
<div class="highlight"><pre><span></span><span class="cp"><!DOCTYPE html></span>
<span class="p"><</span><span class="nt">html</span> <span class="na">lang</span><span class="o">=</span><span class="s">"en"</span><span class="p">></span>
<span class="p"><</span><span class="nt">head</span><span class="p">></span>
<span class="p"><</span><span class="nt">meta</span> <span class="na">charset</span><span class="o">=</span><span class="s">"UTF-8"</span><span class="p">></span>
<span class="p"><</span><span class="nt">title</span><span class="p">></span>Live Streaming<span class="p"></</span><span class="nt">title</span><span class="p">></span>
<span class="p"><</span><span class="nt">link</span> <span class="na">href</span><span class="o">=</span><span class="s">"//vjs.zencdn.net/5.8/video-js.min.css"</span> <span class="na">rel</span><span class="o">=</span><span class="s">"stylesheet"</span><span class="p">></span>
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"//vjs.zencdn.net/5.8/video.min.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
<span class="p"></</span><span class="nt">head</span><span class="p">></span>
<span class="p"><</span><span class="nt">body</span><span class="p">></span>
<span class="p"><</span><span class="nt">video</span> <span class="na">id</span><span class="o">=</span><span class="s">"player"</span> <span class="na">class</span><span class="o">=</span><span class="s">"video-js vjs-default-skin"</span> <span class="na">height</span><span class="o">=</span><span class="s">"360"</span> <span class="na">width</span><span class="o">=</span><span class="s">"640"</span> <span class="na">controls</span> <span class="na">preload</span><span class="o">=</span><span class="s">"none"</span><span class="p">></span>
<span class="p"><</span><span class="nt">source</span> <span class="na">src</span><span class="o">=</span><span class="s">"http://localhost:8080/hls/stream.m3u8"</span> <span class="na">type</span><span class="o">=</span><span class="s">"application/x-mpegURL"</span> <span class="p">/></span>
<span class="p"></</span><span class="nt">video</span><span class="p">></span>
<span class="p"><</span><span class="nt">script</span><span class="p">></span>
<span class="kd">var</span> <span class="nx">player</span> <span class="o">=</span> <span class="nx">videojs</span><span class="p">(</span><span class="s1">'#player'</span><span class="p">);</span>
<span class="p"></</span><span class="nt">script</span><span class="p">></span>
<span class="p"></</span><span class="nt">body</span><span class="p">></span>
<span class="p"></</span><span class="nt">html</span><span class="p">></span>
</pre></div>
<p>Autre possibilité</p>
<div class="highlight"><pre><span></span><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"dash-old.all.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
<span class="p"><</span><span class="nt">script</span><span class="p">></span>
<span class="kd">function</span> <span class="nx">getUrlVars</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">vars</span> <span class="o">=</span> <span class="p">{};</span>
<span class="kd">var</span> <span class="nx">parts</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/[?&]+([^=&]+)=([^&]*)/gi</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">m</span><span class="p">,</span><span class="nx">key</span><span class="p">,</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">vars</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">vars</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">startVideo</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">vars</span> <span class="o">=</span> <span class="nx">getUrlVars</span><span class="p">(),</span>
<span class="nx">url</span> <span class="o">=</span> <span class="s2">"http://192.168.100.107:80/dash/Screen.mpd"</span><span class="p">,</span>
<span class="nx">video</span><span class="p">,</span>
<span class="nx">context</span><span class="p">,</span>
<span class="nx">player</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">vars</span> <span class="o">&&</span> <span class="nx">vars</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="s2">"url"</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">url</span> <span class="o">=</span> <span class="nx">vars</span><span class="p">.</span><span class="nx">url</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">video</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s2">".dash-video-player video"</span><span class="p">);</span>
<span class="nx">context</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Dash</span><span class="p">.</span><span class="nx">di</span><span class="p">.</span><span class="nx">DashContext</span><span class="p">();</span>
<span class="nx">player</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">MediaPlayer</span><span class="p">(</span><span class="nx">context</span><span class="p">);</span>
<span class="nx">player</span><span class="p">.</span><span class="nx">startup</span><span class="p">();</span>
<span class="nx">player</span><span class="p">.</span><span class="nx">attachView</span><span class="p">(</span><span class="nx">video</span><span class="p">);</span>
<span class="nx">player</span><span class="p">.</span><span class="nx">setAutoPlay</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
<span class="nx">player</span><span class="p">.</span><span class="nx">attachSource</span><span class="p">(</span><span class="nx">url</span><span class="p">);</span>
<span class="p">}</span>
<span class="p"></</span><span class="nt">script</span><span class="p">></span>
</pre></div>
<hr>
<h3><em>Webographie</em></h3>
<ol>
<li><a href="http://blog.climatetmeteo.fr/GerardVidal/RaspberryPi-2_3BuildImage.html">Création de l'image</a></li>
<li><a href="http://mediaserv.climatetmeteo.fr/images/RaspBerry/">présentation des images disponibles</a></li>
<li><a href="http://weewx.com/">weewx</a></li>
<li><a href="https://www.dacast.com/blog/hls-streaming-protocol/">article HLS</a></li>
<li><a href="https://trac.ffmpeg.org/wiki/Capture/Webcam">capture de la webcam</a></li>
<li><a href="https://github.com/arut/nginx-rtmp-module/wiki/Directives#rtmp">documentation nginx-rtmp</a></li>
<li><a href="https://docs.peer5.com/guides/setting-up-hls-live-streaming-server-using-nginx/">documentation HLS</a></li>
<li><a href="https://stackoverflow.com/questions/34322021/nginx-rtmp-module-and-mpeg-dashdash-industry-dash-js">documentation DASH</a></li>
</ol>