Paillasse/design/js/contenus-sys-5.js

172 lines
38 KiB
JavaScript
Raw Normal View History

// Cours complets · Systèmes et électronique lot 5 : architecture des ordinateurs, IoT et MQTT, VoIP
(function () {
var reg = function (c) {
(window.CONTENUS_PRO = window.CONTENUS_PRO || []).unshift(c.cours);
(window.CONTENUS_PLUS = window.CONTENUS_PLUS || {})[c.cours.id] = c.plus;
(window.CONTENUS_EXEMPLES = window.CONTENUS_EXEMPLES || {})[c.cours.id] = c.exemples;
(window.CONTENUS_SCHEMAS = window.CONTENUS_SCHEMAS || {})[c.cours.id] = { termes: c.termes, figs: [] };
};
reg({
cours: { id: 'archi', match: /architecture des ordinateurs|von Neumann|processeur|CPU|mémoire|assembleur|composants/i,
titre: 'Architecture des ordinateurs : processeur, mémoire et exécution d’un programme', duree: '',
niveau: 'NSI Première · BTS CIEL · BTS SIO · BUT Informatique / R&T S1',
prerequis: ['Binaire et hexadécimal'],
competences: ['NSI 1re · Architectures matérielles et systèmes d’exploitation', 'BTS CIEL · C02 · Analyser un système électronique', 'BUT · Compétence « Réaliser » · comprendre la machine'],
intro: 'Savoir pourquoi un serveur rame, choisir une configuration pour une salle de TP ou comprendre une faille comme Spectre suppose de savoir ce qui se passe réellement dans la machine. Ce module décrit l’architecture de von Neumann, le cycle d’exécution d’une instruction, la hiérarchie des mémoires et les mécanismes des processeurs modernes, jusqu’aux mesures que l’on fait sur un système Linux.',
cm: [
{ t: 'Le modèle de von Neumann', d: '', html: 'Proposé en 1945, ce modèle organise encore presque tous les ordinateurs. Une <b>unité de calcul</b> (UAL) effectue les opérations arithmétiques et logiques, une <b>unité de contrôle</b> décode les instructions et pilote le reste, une <b>mémoire</b> contient à la fois le programme et les données, et des <b>entrées-sorties</b> relient la machine au monde. Ces éléments communiquent par des <b>bus</b> (données, adresses, contrôle). Le fait que programme et données partagent la même mémoire et le même bus crée le « goulot de von Neumann » : le processeur attend souvent la mémoire.' },
{ t: 'Le cycle d’exécution', d: '', html: 'Le processeur répète sans fin le cycle <b>chargement, décodage, exécution</b>. Le <b>compteur ordinal</b> (PC) contient l’adresse de la prochaine instruction ; elle est lue en mémoire, placée dans le registre d’instruction, décodée, puis exécutée, avec éventuellement un accès mémoire et l’écriture du résultat dans un <b>registre</b>. Les registres sont les mémoires les plus rapides, internes au processeur, en très petit nombre (16 registres généraux en x86-64).<br><br>Un <b>jeu d’instructions</b> (ISA) définit les instructions disponibles : x86-64 sur les PC et serveurs, ARM sur les smartphones, les Raspberry Pi et de plus en plus de serveurs et portables, RISC-V, architecture ouverte en plein essor.', exemple: '; additionner deux cases mémoire (pseudo-assembleur)\nLOAD R1, [0x1000] ; R1 ← mémoire[0x1000]\nLOAD R2, [0x1004]\nADD R3, R1, R2 ; R3 ← R1 + R2\nSTORE R3, [0x1008] ; mémoire[0x1008] ← R3' },
{ t: 'La hiérarchie des mémoires', d: '', html: 'Plus une mémoire est rapide, plus elle est petite et chère. On les organise donc en hiérarchie : registres, caches <b>L1</b>, <b>L2</b>, <b>L3</b> dans le processeur, <b>RAM</b>, puis stockage (SSD NVMe, disque). Les caches exploitent la <b>localité</b> : un programme réutilise souvent les mêmes données (localité temporelle) et lit des données voisines (localité spatiale), si bien que la plupart des accès sont servis par le cache.', table: [['Niveau', 'Taille typique', 'Latence approximative'], ['Registre', 'quelques octets', '< 1 ns'], ['Cache L1', '32 à 64 Kio par cœur', '≈ 1 ns'], ['Cache L2', '256 Kio à 2 Mio par cœur', '≈ 4 ns'], ['Cache L3', '8 à 64 Mio partagés', '≈ 10 à 20 ns'], ['RAM', '8 à 512 Gio', '≈ 80 à 100 ns'], ['SSD NVMe', 'To', '≈ 20 à 100 µs'], ['Disque dur', 'To', '≈ 5 à 10 ms']] },
{ t: 'Accélérer : pipeline, cœurs et prédiction', d: '', html: 'Un processeur moderne traite plusieurs instructions en même temps grâce au <b>pipeline</b> : pendant qu’une instruction s’exécute, la suivante est décodée et la suivante chargée. Il anticipe les branchements (<b>prédiction de branchement</b>) et exécute des instructions à l’avance (<b>exécution spéculative</b>). Les failles <b>Spectre</b> et <b>Meltdown</b> (2018) ont montré que cette spéculation laisse des traces mesurables dans le cache, exploitables pour lire des données protégées.<br><br>Au-delà d’une certaine fréquence, la chaleur limite la montée en vitesse ; on multiplie donc les <b>cœurs</b>. Un programme n’en profite que s’il est écrit pour exécuter plusieurs tâches en parallèle.' },
{ t: 'Le rôle du système d’exploitation', d: '', html: 'Le système d’exploitation partage le processeur entre les processus (<b>ordonnancement</b>), donne à chacun une <b>mémoire virtuelle</b> isolée que le processeur traduit en adresses physiques grâce à la MMU et aux tables de pages, et gère les périphériques par des pilotes. Quand la RAM manque, des pages sont écrites sur disque (<b>swap</b>) : les performances s’effondrent, car un accès disque est des milliers de fois plus lent qu’un accès mémoire.' },
{ t: 'Mesurer sous Linux', d: '', html: '<code>lscpu</code> décrit le processeur (cœurs, fils, caches), <code>free -h</code> la mémoire, <code>lsblk</code> les disques. La <b>charge</b> affichée par <code>uptime</code> est le nombre moyen de processus prêts ou en attente d’entrée-sortie sur 1, 5 et 15 minutes : durablement supérieure au nombre de cœurs, la machine est saturée. <code>vmstat 1</code> distingue le temps processeur utilisateur, système, d’attente d’entrée-sortie (wa) et l’activité du swap (si, so).' }
],
synthese: ['Von Neumann : UAL, contrôle, mémoire commune programme-données, entrées-sorties, bus', 'Cycle chargement-décodage-exécution, compteur ordinal, registres', 'Hiérarchie registres → caches → RAM → stockage ; localité', 'Pipeline, prédiction, spéculation (Spectre), multicœur', 'OS : ordonnancement, mémoire virtuelle, swap', 'lscpu, free, uptime, vmstat pour mesurer'],
qcm: [
['Que contient le compteur ordinal ?', ['Le résultat', 'L’adresse de la prochaine instruction', 'Le nombre de cœurs', 'La fréquence'], 1, 'PC ou IP.'],
['Quelle mémoire est la plus rapide ?', ['RAM', 'Cache L3', 'Registre', 'SSD'], 2, 'Interne au cœur.'],
['Qu’est-ce que la localité spatiale ?', ['Les données sont à distance', 'Un programme lit souvent des données voisines', 'Le cache est proche', 'Le disque est local'], 1, 'D’où les lignes de cache.'],
['Sur quel mécanisme reposent Spectre et Meltdown ?', ['Le swap', 'L’exécution spéculative', 'Le bus USB', 'Le BIOS'], 1, 'Traces laissées dans le cache.'],
['Charge de 12 sur une machine 4 cœurs, pendant 15 min :', ['normal', 'saturation', 'machine éteinte', 'réseau coupé'], 1, 'Trois fois plus de travail que de cœurs.'],
['Pourquoi le swap dégrade-t-il fortement les performances ?', ['Il chiffre', 'Un accès disque est des milliers de fois plus lent que la RAM', 'Il consomme du réseau', 'Il désactive le cache'], 1, 'Latence.']
],
td: [
{ n: 'Application', c: 'Dérouler le programme pseudo-assembleur du cours avec mémoire[0x1000] = 7 et mémoire[0x1004] = 5 : contenu des registres et de la mémoire après chaque instruction.', r: 'R1 = 7 · R2 = 5 · R3 = 12 · mémoire[0x1008] = 12' },
{ n: 'Application', c: 'Un programme accède 1 million de fois à la mémoire ; 95 % des accès sont servis par le cache (1 ns), les autres par la RAM (100 ns). Temps total ?', r: '950 000 × 1 + 50 000 × 100 = 5 950 000 ns ≈ 6 ms (contre 100 ms sans cache).' },
{ n: 'Approfondissement', c: 'Interpréter une sortie vmstat où wa vaut 60 et si/so sont non nuls.', r: 'Le processeur attend les entrées-sorties 60 % du temps et la machine swappe : manque de RAM. Ajouter de la mémoire ou réduire la consommation.' }
],
tp: { type: 'Lab VM', url: 'apercu-labs.html', desc: 'Mesurer les caractéristiques et la charge d’une VM.', etapes: ['Relever lscpu, free, lsblk', 'Générer de la charge avec stress-ng', 'Lire uptime et vmstat', 'Provoquer du swap et mesurer l’impact', 'Rédiger une recommandation de dimensionnement'] },
plusLoin: [['From Nand to Tetris', 'https://www.nand2tetris.org/'], ['Eduscol · NSI architectures matérielles', 'https://eduscol.education.fr/'], ['Latency numbers every programmer should know', 'https://gist.github.com/jboner/2841832']] },
plus: { cas: { titre: '', texte: '' },
resolu: { enonce: 'Le serveur de fichiers devient très lent chaque jour vers 10 h, alors que le processeur semble peu utilisé.', etapes: [
['Mesurer la charge', 'uptime\nload average: 9.8, 8.7, 6.1\nnproc\n4\n→ Charge élevée pour 4 cœurs.'],
['Distinguer calcul et attente', 'vmstat 1 5\n r b swpd free si so us sy id wa\n 1 8 2.1G 120M 850 920 4 3 18 75\n→ 8 processus bloqués (b), 75 % d’attente d’entrée-sortie, swap actif : ce n’est pas le calcul, c’est la mémoire.'],
['Trouver le consommateur', 'ps aux --sort=-%mem | head -3\nroot … 61.2 clamd\n→ L’analyse antivirus programmée à 10 h charge ses signatures et occupe 61 % de la RAM.'],
['Corriger', '→ Déplacement de l’analyse complète à 2 h, limite mémoire du service par systemd (MemoryMax), et ajout de 8 Go de RAM au prochain budget.'],
['Vérifier', 'vmstat 1 5 à 10 h le lendemain : wa < 5, si/so = 0.\n→ Compte rendu avec les mesures avant et après.']
] },
erreurs: ['Confondre charge et pourcentage CPU', 'Ajouter des cœurs quand le problème est la mémoire', 'Ignorer le swap', 'Croire qu’un programme profite automatiquement de tous les cœurs'],
memo: [['Commande', 'Usage'], ['lscpu', 'processeur, cœurs, caches'], ['nproc', 'nombre de cœurs utilisables'], ['free -h', 'mémoire et swap'], ['uptime', 'charge 1, 5, 15 min'], ['vmstat 1', 'CPU, attente disque, swap'], ['top · htop', 'processus en direct'], ['ps aux --sort=-%mem', 'plus gros consommateurs de mémoire'], ['lsblk · lsusb · lspci', 'matériel'], ['dmidecode -t memory', 'barrettes installées']],
examen: { titre: 'Sujet type · 20 points', q: ['Schématiser l’architecture de von Neumann. (4 pts)', 'Dérouler un programme en pseudo-assembleur. (5 pts)', 'Calculer un temps d’accès moyen avec cache. (4 pts)', 'Interpréter une sortie vmstat. (4 pts)', 'Expliquer le principe de Spectre. (3 pts)'], r: ['voir cours', 'registres pas à pas', 'moyenne pondérée', 'wa, si/so', 'spéculation et cache'] },
prof: { deroule: [['Ouverture', 'Démonter un PC de récupération'], ['Cours', 'Von Neumann et cycle'], ['Pratique', 'Pseudo-assembleur'], ['Cours', 'Mémoires et mesures'], ['Clôture', 'Quiz flash']], diff: 'Élèves en difficulté : schéma à compléter. Élèves avancés : Nand to Tetris.', eval: 'Sujet type.' } },
exemples: [
['Décrire le processeur', 'Inventaire d’un serveur.', 'lscpu | grep -E "Model name|^CPU\\(s\\)|Thread|L3"', 'Model name: Intel(R) Xeon(R) E-2336 CPU @ 2.90GHz\nCPU(s): 12\nThread(s) per core: 2\nL3 cache: 12 MiB', '6 cœurs physiques, 2 fils par cœur : 12 processeurs logiques.'],
['Lire la mémoire', 'Un service manque-t-il de RAM ?', 'free -h', ' total used free shared buff/cache available\nMem: 15Gi 13Gi 210Mi 120Mi 2.1Gi 1.4Gi\nSwap: 2.0Gi 1.8Gi 200Mi', 'Il faut lire available (1,4 Gi) et non free ; le swap presque plein confirme le manque de mémoire.'],
['Interpréter la charge', 'Serveur lent.', 'uptime ; nproc', 'load average: 3.9, 3.8, 3.7\n4', 'Charge proche du nombre de cœurs : machine bien utilisée mais pas saturée.'],
['Voir l’attente disque', 'Lenteurs intermittentes.', 'vmstat 1 3', ' r b us sy id wa\n 0 6 2 1 20 77', '77 % d’attente d’entrée-sortie : le disque est le goulot, pas le processeur.'],
['Plus gros consommateurs', 'Qui occupe la mémoire ?', 'ps -eo pid,comm,%mem --sort=-%mem | head -4', ' PID COMMAND %MEM\n 1204 java 48.1\n 790 mariadbd 21.6', 'L’application Java prend la moitié de la mémoire : vérifier son paramètre -Xmx.'],
['Vulnérabilités matérielles', 'Audit de sécurité.', 'grep . /sys/devices/system/cpu/vulnerabilities/*', '…/meltdown:Not affected\n…/spectre_v2:Mitigation: Enhanced / Automatic IBRS', 'Le noyau indique les protections actives contre chaque faille connue du processeur.']
],
termes: ['von Neumann', 'UAL', 'unité de contrôle', 'bus', 'registre', 'compteur ordinal', 'jeu d’instructions', 'x86-64', 'ARM', 'RISC-V', 'cache', 'L1', 'L2', 'L3', 'RAM', 'localité', 'pipeline', 'exécution spéculative', 'Spectre', 'mémoire virtuelle', 'MMU', 'swap', 'lscpu', 'vmstat', 'load average']
});
reg({
cours: { id: 'iot', match: /IoT|objets connectés|MQTT|capteur|ESP32|Arduino|Raspberry|embarqué/i,
titre: 'Objets connectés : capteurs, microcontrôleurs et MQTT', duree: '',
niveau: 'SNT · BTS CIEL IR / ER · BUT R&T parcours IoT · BUT GEII',
prerequis: ['Binaire', 'Réseau : TCP/IP'],
competences: ['SNT · Informatique embarquée et objets connectés', 'BTS CIEL · C05 · Réaliser un système communicant', 'BUT R&T IoT · Compétence « Déployer un réseau d’objets »'],
intro: 'Un capteur de CO₂ dans chaque salle, des compteurs d’énergie sur les bâtiments, une serre pédagogique pilotée à distance : les objets connectés mesurent, transmettent et agissent. Ils posent des contraintes particulières : peu de mémoire, alimentation sur batterie, réseaux radio à faible débit et sécurité souvent négligée. Ce module va du capteur au tableau de bord, en passant par le microcontrôleur, le protocole MQTT et la sécurisation.',
cm: [
{ t: 'Chaîne d’un système connecté', d: '', html: 'Un objet connecté suit une chaîne <b>acquérir, traiter, communiquer, agir</b>. Un <b>capteur</b> convertit une grandeur physique (température, CO₂, mouvement) en signal électrique. Un <b>microcontrôleur</b> (ESP32, STM32, RP2040) le lit, le traite et le transmet. Une <b>passerelle</b> ou un réseau relaie les données vers un <b>serveur</b> qui les stocke et les affiche, et peut renvoyer des commandes vers des <b>actionneurs</b> (relais, moteur, vanne).' },
{ t: 'Lire un capteur', d: '', html: 'Un capteur <b>analogique</b> fournit une tension que le <b>convertisseur analogique-numérique</b> (CAN) du microcontrôleur transforme en nombre : sur 12 bits, 0 à 4 095 pour 0 à 3,3 V. Un capteur <b>numérique</b> communique par un bus : <b>I²C</b> (deux fils, adresses, plusieurs capteurs sur le même bus), <b>SPI</b> (plus rapide, un fil de sélection par composant), ou <b>UART</b> (liaison série). Le choix de la fréquence d’échantillonnage dépend du phénomène : une température toutes les minutes suffit, une vibration exige des milliers de mesures par seconde.', exemple: '# MicroPython sur ESP32 : capteur I2C SCD41 (CO2)\nfrom machine import I2C, Pin\ni2c = I2C(0, scl=Pin(22), sda=Pin(21))\nprint([hex(a) for a in i2c.scan()]) # ["0x62"] : adresse du capteur' },
{ t: 'Réseaux de l’IoT', d: '', html: 'Le choix du réseau dépend de la portée, du débit et de la consommation. <b>Wi-Fi</b> : débit élevé, forte consommation, adapté aux objets alimentés. <b>Bluetooth Low Energy</b> : courte portée, très faible consommation. <b>Zigbee</b> et <b>Thread</b> : maillage à faible consommation pour le bâtiment. <b>LoRaWAN</b> : plusieurs kilomètres, quelques octets par message, des années sur pile, idéal pour des capteurs dispersés. <b>NB-IoT</b> et <b>LTE-M</b> : réseaux cellulaires dédiés aux objets.' },
{ t: 'MQTT, le protocole de publication', d: '', html: '<b>MQTT</b> est un protocole léger fondé sur la <b>publication-abonnement</b>. Les objets <b>publient</b> des messages sur des <b>topics</b> hiérarchiques (<code>lycee/batA/salle204/co2</code>) auprès d’un <b>broker</b> (Mosquitto, EMQX) ; les applications s’<b>abonnent</b> aux topics qui les intéressent, avec des jokers (<code>+</code> pour un niveau, <code>#</code> pour tous les niveaux suivants). Émetteurs et récepteurs ne se connaissent pas.<br><br>Trois niveaux de <b>QoS</b> : 0 au plus une fois, 1 au moins une fois, 2 exactement une fois. Le drapeau <b>retain</b> garde la dernière valeur pour les nouveaux abonnés, et le <b>testament</b> (Last Will) publie un message si l’objet se déconnecte brutalement. MQTT fonctionne sur TCP 1883, ou 8883 en TLS.', exemple: 'mosquitto_sub -h broker.lycee.local -t "lycee/+/+/co2" -v\nlycee/batA/salle204/co2 1180\nlycee/batB/salle112/co2 640\n\nmosquitto_pub -h broker.lycee.local -t lycee/batA/salle204/fenetre -m ouvrir -q 1' },
{ t: 'Stocker et afficher', d: '', html: 'Les mesures sont des <b>séries temporelles</b>. Une chaîne classique : broker MQTT, puis un collecteur (Telegraf, Node-RED) qui écrit dans une base de séries temporelles (InfluxDB, TimescaleDB), puis un tableau de bord (Grafana) avec seuils et alertes. Pour le CO₂ dans les salles, les recommandations sanitaires invitent à aérer au-delà d’environ 800 ppm.' },
{ t: 'Sécurité des objets', d: '', html: 'Les objets connectés sont une porte d’entrée fréquente : mots de passe par défaut, services ouverts, micrologiciels jamais mis à jour. Le botnet <b>Mirai</b> (2016) a compromis des centaines de milliers de caméras par leurs identifiants d’usine. Mesures : identifiants uniques, <b>TLS</b> et authentification sur le broker, listes de contrôle d’accès par topic, <b>VLAN dédié</b> aux objets sans accès au reste du réseau, mise à jour du micrologiciel, désactivation des services inutiles. Le règlement européen sur la cyber-résilience impose progressivement ces exigences aux fabricants.' }
],
synthese: ['Acquérir, traiter, communiquer, agir', 'CAN pour l’analogique ; I²C, SPI, UART pour le numérique', 'Réseau selon portée, débit, consommation : Wi-Fi, BLE, Zigbee, LoRaWAN', 'MQTT : broker, topics, jokers, QoS, retain, testament', 'Séries temporelles et tableaux de bord', 'Identifiants uniques, TLS, ACL, VLAN dédié, mises à jour'],
qcm: [
['Sur 12 bits, combien de valeurs le CAN peut-il produire ?', ['1 024', '4 096', '256', '65 536'], 1, '2¹².'],
['Quel bus permet plusieurs capteurs sur deux fils avec des adresses ?', ['SPI', 'I²C', 'UART', 'USB'], 1, 'SDA et SCL.'],
['Pour des capteurs à plusieurs kilomètres sur pile :', ['Wi-Fi', 'LoRaWAN', 'Bluetooth', 'Ethernet'], 1, 'Longue portée, faible débit.'],
['Que signifie lycee/+/salle204/co2 ?', ['Tous les topics', 'Un niveau quelconque à la place de +', 'Une erreur', 'Seulement le bâtiment +'], 1, '+ remplace un seul niveau.'],
['À quoi sert le testament MQTT ?', ['Chiffrer', 'Publier un message si l’objet se déconnecte brutalement', 'Garder la dernière valeur', 'Supprimer un topic'], 1, 'Détecter une panne.'],
['Quelle mesure isole les objets du reste du réseau ?', ['Un VLAN dédié', 'Le QoS', 'Le retain', 'Le CAN'], 0, 'Cloisonnement.']
],
td: [
{ n: 'Application', c: 'Un capteur analogique de 0 à 3,3 V pour 0 à 50 °C, lu sur 12 bits, renvoie 2 458. Température ?', r: '2 458 / 4 095 × 3,3 ≈ 1,98 V → 1,98 / 3,3 × 50 ≈ 30 °C' },
{ n: 'Application', c: 'Proposer l’arborescence de topics MQTT pour des capteurs de CO₂, température et présence dans 3 bâtiments, et l’abonnement qui reçoit tout le CO₂.', r: 'lycee/<bat>/<salle>/<mesure> · abonnement lycee/+/+/co2' },
{ n: 'Approfondissement', c: 'Sécuriser un broker Mosquitto : écoute en TLS seulement, authentification, et droits en écriture limités à son propre topic pour chaque capteur.', r: 'listener 8883 + cafile/certfile/keyfile · allow_anonymous false · password_file · acl_file avec pattern write lycee/%u/# (identifiant = salle).' }
],
tp: { type: 'Lab VM', url: 'apercu-labs.html', desc: 'Broker Mosquitto, capteurs simulés et tableau de bord.', etapes: ['Installer Mosquitto', 'Publier des mesures simulées', 'S’abonner avec jokers', 'Enregistrer dans InfluxDB via Telegraf', 'Tableau de bord et alerte à 800 ppm', 'Activer TLS et authentification'] },
plusLoin: [['Spécification MQTT 5 (OASIS)', 'https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html'], ['Documentation Mosquitto', 'https://mosquitto.org/documentation/'], ['MicroPython', 'https://docs.micropython.org/'], ['ANSSI · Recommandations relatives à la sécurité des objets connectés', 'https://cyber.gouv.fr/']] },
plus: { cas: { titre: '', texte: '' },
resolu: { enonce: 'Le tableau de bord du CO₂ n’affiche plus aucune valeur pour le bâtiment B depuis hier, alors que les capteurs clignotent normalement.', etapes: [
['Écouter le broker', 'mosquitto_sub -h broker.lycee.local -t "lycee/batB/#" -v -W 30\n(aucun message en 30 s)\n→ Les capteurs de B ne publient plus rien au broker.'],
['Lire les journaux du broker', 'journalctl -u mosquitto --since yesterday | grep batB | tail -2\nClient capteur-B112 disconnected, not authorised.\n→ Les capteurs sont rejetés à la connexion.'],
['Trouver le changement', '→ Hier, le broker a été reconfiguré avec allow_anonymous false ; les capteurs du bâtiment B, installés en premier, n’avaient pas d’identifiants.'],
['Corriger', 'mosquitto_passwd -b /etc/mosquitto/passwd capteur-B112 <mot_de_passe>\n(identifiant par capteur, poussé par mise à jour du micrologiciel)\nsystemctl reload mosquitto\n→ Les capteurs se reconnectent et publient.'],
['Prévenir', '→ Testament sur chaque capteur (topic …/etat = hors_ligne) et alerte Grafana si un capteur ne publie plus depuis 15 minutes. Inventaire des identifiants des objets.']
] },
erreurs: ['Laisser le broker anonyme et en clair', 'Même identifiant pour tous les objets', 'Objets sur le même réseau que les postes', 'Pas de testament ni d’alerte d’absence', 'Mesurer trop souvent et vider la batterie', 'Oublier les mises à jour du micrologiciel'],
memo: [['Commande', 'Usage'], ['mosquitto_sub -t "a/#" -v', 's’abonner et voir les topics'], ['mosquitto_pub -t t -m v -q 1 -r', 'publier, QoS 1, retain'], ['mosquitto_passwd', 'gérer les comptes du broker'], ['journalctl -u mosquitto', 'journaux du broker'], ['i2c.scan()', 'détecter les capteurs I²C (MicroPython)'], ['machine.ADC(Pin(34)).read()', 'lire une entrée analogique'], ['machine.deepsleep(60000)', 'veille profonde pour économiser la batterie'], ['influx query', 'interroger les séries temporelles']],
examen: { titre: 'Sujet type · 20 points', q: ['Décrire la chaîne d’un capteur de CO₂ jusqu’au tableau de bord. (5 pts)', 'Convertir une mesure CAN. (3 pts)', 'Justifier un choix de réseau pour un cas donné. (4 pts)', 'Concevoir les topics et abonnements MQTT. (4 pts)', 'Proposer quatre mesures de sécurité. (4 pts)'], r: ['capteur → MCU → MQTT → base → Grafana', 'règle de trois', 'portée, débit, énergie', 'hiérarchie + jokers', 'TLS, ACL, VLAN, identifiants uniques'] },
prof: { deroule: [['Ouverture', 'Un capteur de CO₂ dans la salle'], ['Cours', 'Chaîne et capteurs'], ['Pratique', 'Lecture I²C en MicroPython'], ['Cours', 'MQTT'], ['Pratique', 'Lab broker et tableau de bord'], ['Clôture', 'Quiz flash']], diff: 'Élèves en difficulté : capteurs simulés. Élèves avancés : LoRaWAN, TLS mutuel.', eval: 'Lab validé, sujet type.' } },
exemples: [
['Détecter un capteur I²C', 'Câblage d’un nouveau capteur.', '>>> i2c.scan()', '[]', 'Liste vide : aucun capteur détecté. On vérifie SDA/SCL inversés, l’alimentation et les résistances de tirage.'],
['Écouter toutes les mesures', 'Vérifier ce qui transite.', 'mosquitto_sub -h broker.lycee.local -t "lycee/#" -v -C 3', 'lycee/batA/salle204/co2 1180\nlycee/batA/salle204/temp 22.4\nlycee/batA/salle204/etat en_ligne', 'La salle 204 dépasse 800 ppm : il faut aérer.'],
['Tester la sécurité du broker', 'Audit.', 'mosquitto_sub -h broker.lycee.local -p 1883 -t "#" -C 1', 'Connection error: Connection Refused: not authorised.', 'Le broker refuse les connexions anonymes : correct.'],
['Retrouver la dernière valeur', 'Nouveau tableau de bord.', 'mosquitto_sub -t lycee/batA/salle204/co2 -C 1', '1180', 'Grâce au retain, l’abonné reçoit immédiatement la dernière valeur sans attendre la prochaine mesure.'],
['Mesurer la consommation', 'Autonomie trop courte.', 'Mesure ampèremètre : actif 160 mA pendant 2 s, veille 10 µA, une mesure par minute', 'Moyenne ≈ 160 × 2/60 + 0,01 ≈ 5,3 mA → pile de 2 000 mAh ≈ 16 jours', 'Le Wi-Fi coûte cher en énergie : passer à une mesure toutes les 5 minutes ou à LoRaWAN.'],
['Déclarer un testament', 'Détecter un capteur débranché.', 'client.set_last_will("lycee/batA/salle204/etat", "hors_ligne", retain=True)', '(après coupure) lycee/batA/salle204/etat hors_ligne', 'Le broker publie le message à la place du capteur disparu.']
],
termes: ['IoT', 'capteur', 'actionneur', 'microcontrôleur', 'ESP32', 'CAN', 'I²C', 'SPI', 'UART', 'LoRaWAN', 'Zigbee', 'BLE', 'MQTT', 'broker', 'topic', 'QoS', 'retain', 'testament', 'Mosquitto', 'InfluxDB', 'Grafana', 'MicroPython', 'Mirai']
});
reg({
cours: { id: 'voip', match: /VoIP|téléphonie|SIP|RTP|Asterisk|ToIP/i,
titre: 'Téléphonie sur IP : SIP, RTP, qualité de service et Asterisk', duree: '',
niveau: 'BTS SIO SISR · BTS CIEL IR · BUT R&T parcours Réseaux · TSSR',
prerequis: ['TCP et UDP', 'VLAN', 'NAT'],
competences: ['BTS SIO SISR · Bloc 2 · Installer un service de communication', 'BTS CIEL · C04 · Installer un réseau de téléphonie', 'BUT R&T · Compétence « Connecter »'],
intro: 'Le standard téléphonique d’un établissement passe désormais par le réseau informatique : postes IP, softphones, passerelles vers les opérateurs. La voix est pourtant exigeante : quelques pour cent de pertes ou une gigue de quelques dizaines de millisecondes suffisent à rendre une conversation inaudible. Ce module présente la signalisation SIP, le transport RTP, les codecs, la qualité de service et un serveur Asterisk, puis la méthode de diagnostic des problèmes de voix.',
cm: [
{ t: 'Signalisation et média', d: '', html: 'Un appel en téléphonie sur IP utilise deux flux distincts. La <b>signalisation</b>, avec <b>SIP</b> (Session Initiation Protocol, RFC 3261, port 5060 ou 5061 en TLS), établit, modifie et termine l’appel. Le <b>média</b>, la voix elle-même, est transporté par <b>RTP</b> sur UDP, sur des ports dynamiques négociés pendant la signalisation grâce à <b>SDP</b> ; RTCP remonte des statistiques de qualité. SRTP chiffre le média.' },
{ t: 'Un appel SIP', d: '', html: 'Le poste appelant envoie un <b>INVITE</b> contenant sa description SDP (adresse, port, codecs acceptés). Le serveur répond <b>100 Trying</b>, puis le poste appelé <b>180 Ringing</b>, puis <b>200 OK</b> quand il décroche, avec sa propre description SDP. L’appelant confirme par <b>ACK</b>, et les flux RTP s’établissent directement entre les deux adresses négociées. <b>BYE</b> termine l’appel. Au préalable, chaque poste s’est enregistré auprès du serveur par <b>REGISTER</b>, avec une authentification par défi (401 puis requête avec digest).', exemple: 'INVITE sip:2204@lycee.local SIP/2.0\nVia: SIP/2.0/UDP 10.62.50.21:5060\nFrom: <sip:2112@lycee.local>;tag=a73k\nTo: <sip:2204@lycee.local>\nContent-Type: application/sdp\n\nc=IN IP4 10.62.50.21\nm=audio 18234 RTP/AVP 9 8 0\na=rtpmap:9 G722/8000' },
{ t: 'Codecs et bande passante', d: '', html: 'Le <b>codec</b> numérise et compresse la voix. <b>G.711</b> (PCMU, PCMA) : 64 kbit/s, qualité téléphonique, aucune compression. <b>G.722</b> : 64 kbit/s en « HD voice ». <b>Opus</b> : adaptatif de 6 à 510 kbit/s, robuste aux pertes, utilisé par la visioconférence. Aux 64 kbit/s de G.711 s’ajoutent les en-têtes RTP, UDP, IP et Ethernet : avec des paquets toutes les 20 ms, un appel consomme environ <b>87 kbit/s</b> dans chaque sens sur Ethernet.' },
{ t: 'Qualité de service', d: '', html: 'La voix tolère mal trois phénomènes. La <b>latence</b> : au-delà d’environ 150 ms dans un sens, la conversation devient pénible (recommandation UIT-T G.114). La <b>gigue</b> : variation du délai entre paquets, compensée par un tampon au prix d’un peu de latence. Les <b>pertes</b> : au-delà de 1 %, la voix se hache.<br><br>Pour protéger la voix, on la place dans un <b>VLAN voix</b> dédié (souvent annoncé aux postes par LLDP-MED) et on la marque en <b>DSCP EF</b> (46) pour qu’elle passe en priorité dans les files d’attente des switchs et routeurs. Les postes sont souvent alimentés par le switch en <b>PoE</b>.' },
{ t: 'Asterisk', d: '', html: '<b>Asterisk</b> est un autocommutateur logiciel libre (IPBX). Les postes sont déclarés dans la configuration <b>PJSIP</b> (<code>pjsip.conf</code>) et le routage des appels dans le <b>plan de numérotation</b> (<code>extensions.conf</code>), organisé en contextes. On y définit les numéros internes, la messagerie vocale, les files d’attente, le serveur vocal interactif et les sorties vers l’opérateur via un trunk SIP.', exemple: '; pjsip.conf\n[2204]\ntype=endpoint\ncontext=interne\nallow=!all,g722,alaw\nauth=2204-auth\naors=2204\n\n; extensions.conf\n[interne]\nexten => _22XX,1,Dial(PJSIP/${EXTEN},20)\n same => n,VoiceMail(${EXTEN}@lycee)\n same => n,Hangup()' },
{ t: 'NAT, sécurité et fraude', d: '', html: 'SIP transporte des adresses IP dans ses messages : derrière un NAT, un poste annonce son adresse privée et le média n’arrive pas. Symptôme classique : l’appel s’établit mais le son ne passe que dans un sens, ou pas du tout. Les réponses : paramètres NAT d’Asterisk (external_media_address, rtp_symmetric), ouverture de la plage RTP, ou un SBC (Session Border Controller) en bordure.<br><br>Un IPBX exposé sur Internet subit en permanence des tentatives d’enregistrement : un compte compromis sert à passer des appels surtaxés à l’international, avec des factures de plusieurs milliers d’euros en une nuit. On limite l’accès SIP par adresse, on impose des mots de passe robustes, on installe fail2ban et on bloque les destinations internationales non nécessaires.' }
],
synthese: ['SIP pour la signalisation (5060/5061), RTP sur UDP pour la voix, SDP pour négocier', 'INVITE, 180, 200 OK, ACK, BYE ; REGISTER avec authentification', 'G.711 ≈ 87 kbit/s par sens sur Ethernet', 'Latence < 150 ms, gigue faible, pertes < 1 %', 'VLAN voix, DSCP EF, PoE', 'Asterisk : pjsip.conf et extensions.conf', 'Son dans un seul sens = NAT ; protéger contre la fraude'],
qcm: [
['Quel protocole transporte la voix ?', ['SIP', 'RTP', 'SDP', 'DHCP'], 1, 'Sur UDP.'],
['Que signifie 180 Ringing ?', ['Appel terminé', 'Le poste appelé sonne', 'Erreur', 'Authentification'], 1, 'Réponse provisoire.'],
['Un appel s’établit mais le son ne passe que dans un sens. Cause la plus probable ?', ['Codec', 'NAT ou pare-feu sur le flux RTP', 'DNS', 'PoE'], 1, 'Signalisation OK, média bloqué.'],
['Quel marquage DSCP pour la voix ?', ['AF11', 'EF (46)', 'CS0', 'BE'], 1, 'Expedited Forwarding.'],
['Latence maximale conseillée dans un sens ?', ['15 ms', '150 ms', '1 s', 'Aucune'], 1, 'UIT-T G.114.'],
['Pourquoi limiter les appels internationaux sur l’IPBX ?', ['Qualité', 'Limiter la fraude en cas de compte compromis', 'Obligation légale', 'Bande passante'], 1, 'Appels surtaxés.']
],
td: [
{ n: 'Application', c: 'Calculer la bande passante nécessaire pour 30 appels simultanés en G.711 vers l’opérateur.', r: '30 × 87 ≈ 2,6 Mbit/s dans chaque sens (prévoir une marge).' },
{ n: 'Application', c: 'Écrire la configuration Asterisk de deux postes internes 2201 et 2202 qui peuvent s’appeler, avec messagerie vocale.', r: 'pjsip.conf : endpoint, auth, aor pour chaque poste, context=interne · extensions.conf : exten => _22XX,1,Dial(PJSIP/${EXTEN},20) puis VoiceMail puis Hangup.' },
{ n: 'Approfondissement', c: 'Proposer la configuration réseau d’un switch pour des postes IP chaînés avec un PC (un seul câble par bureau).', r: 'Port en accès VLAN données, VLAN voix déclaré (switchport voice vlan 60), LLDP-MED activé, PoE, confiance DSCP pour les postes, QoS avec file prioritaire pour EF.' }
],
tp: { type: 'Lab VM', url: 'apercu-labs.html', desc: 'Asterisk et deux softphones.', etapes: ['Installer Asterisk', 'Déclarer deux postes PJSIP', 'Écrire le plan de numérotation', 'Passer un appel et capturer SIP et RTP', 'Lire les statistiques de qualité', 'Installer fail2ban'] },
plusLoin: [['RFC 3261 · SIP', 'https://www.rfc-editor.org/rfc/rfc3261'], ['Documentation Asterisk', 'https://docs.asterisk.org/'], ['Wireshark · VoIP calls', 'https://wiki.wireshark.org/VoIP_calls']] },
plus: { cas: { titre: '', texte: '' },
resolu: { enonce: 'Depuis le passage au nouveau fournisseur SIP, les appels entrants sonnent et décrochent, mais l’appelant extérieur n’entend rien.', etapes: [
['Observer la signalisation', 'asterisk -rx "pjsip set logger on" puis appel test\n<-- INVITE … c=IN IP4 203.0.113.80 m=audio 31000\n--> 200 OK … c=IN IP4 10.62.40.60 m=audio 12044\n→ Asterisk annonce son adresse privée 10.62.40.60 au fournisseur, qui ne peut pas lui envoyer de voix.'],
['Confirmer côté réseau', 'tcpdump -ni wan0 udp portrange 10000-20000\n(aucun paquet RTP entrant)\n→ Le média entrant n’arrive jamais.'],
['Corriger la configuration NAT', 'pjsip.conf, transport :\nexternal_media_address=203.0.113.10\nexternal_signaling_address=203.0.113.10\nlocal_net=10.62.0.0/16\nendpoint du trunk : rtp_symmetric=yes, force_rport=yes, rewrite_contact=yes\n→ Asterisk annonce l’adresse publique vers l’extérieur.'],
['Ouvrir le média', 'nftables : DNAT et forward pour udp 10000-20000 depuis les adresses du fournisseur uniquement vers 10.62.40.60.\n→ Le RTP entrant atteint le serveur.'],
['Vérifier', 'Appel test : son dans les deux sens ; asterisk -rx "rtp show stats" : perte 0 %, gigue 3 ms.\n→ Compte rendu : cause NAT, correction, et restriction des flux aux seules adresses du fournisseur.']
] },
erreurs: ['Oublier le média dans les règles de pare-feu', 'Voix et données dans le même VLAN sans QoS', 'IPBX exposé sans filtrage ni fail2ban', 'Mots de passe SIP faibles', 'Sous-dimensionner le lien opérateur', 'Codec imposé sans compatibilité avec le fournisseur'],
memo: [['Commande', 'Usage'], ['asterisk -rvvv', 'console Asterisk'], ['pjsip show endpoints', 'postes et état d’enregistrement'], ['pjsip set logger on', 'afficher les messages SIP'], ['core show channels', 'appels en cours'], ['rtp show stats', 'qualité des flux'], ['dialplan reload · module reload res_pjsip.so', 'recharger la configuration'], ['sngrep', 'visualiser les échanges SIP'], ['tcpdump -ni ens18 port 5060 or portrange 10000-20000', 'capturer SIP et RTP'], ['fail2ban-client status asterisk', 'adresses bannies']],
examen: { titre: 'Sujet type · 20 points', q: ['Décrire l’établissement d’un appel SIP avec un diagramme. (5 pts)', 'Calculer une bande passante voix. (3 pts)', 'Proposer la configuration réseau pour la voix. (4 pts)', 'Configurer deux postes et le plan de numérotation Asterisk. (5 pts)', 'Diagnostiquer un son unidirectionnel. (3 pts)'], r: ['INVITE … BYE', 'codec + en-têtes', 'VLAN voix, DSCP EF, PoE', 'pjsip.conf, extensions.conf', 'NAT / RTP'] },
prof: { deroule: [['Ouverture', 'Appel entre deux softphones de la salle'], ['Cours', 'SIP, RTP, codecs'], ['Pratique', 'Asterisk'], ['Cours', 'QoS et NAT'], ['Incident', 'Son dans un seul sens'], ['Clôture', 'Quiz flash']], diff: 'Élèves en difficulté : configuration fournie à compléter. Élèves avancés : SRTP, file d’attente, serveur vocal.', eval: 'Appel réussi avec capture analysée, sujet type.' } },
exemples: [
['Vérifier les enregistrements', 'Un poste ne sonne pas.', 'asterisk -rx "pjsip show contacts"', 'Contact: 2201/sip:2201@10.62.50.21:5060 Avail 12.4ms\nContact: 2204/sip:2204@10.62.50.33:5060 Unavail', 'Le poste 2204 n’est plus joignable : vérifier son alimentation PoE, son VLAN et son enregistrement.'],
['Suivre un appel', 'Échec d’appel.', 'sngrep', '10.62.50.21 → 10.62.40.60 INVITE\n10.62.40.60 → 10.62.50.21 407 Proxy Authentication Required\n10.62.50.21 → 10.62.40.60 INVITE\n10.62.40.60 → 10.62.50.21 403 Forbidden', 'Authentification refusée : mot de passe du poste erroné.'],
['Mesurer la qualité', 'Voix hachée.', 'asterisk -rx "rtp show stats"', 'Peer RLost RJitter Tx TLost TJitter\n10.62.50.21 4.8% 38 ms … 0.2% 4 ms', '4,8 % de pertes et 38 ms de gigue en réception depuis ce poste : problème réseau sur son chemin (Wi-Fi, switch sans QoS).'],
['Vérifier le marquage', 'Les switchs priorisent-ils la voix ?', 'tcpdump -ni ens18 -v -c 1 udp portrange 10000-20000', 'IP (tos 0xb8, ttl 64, …) 10.62.50.21.18234 > 10.62.40.60.12044: UDP, length 172', 'tos 0xb8 correspond à DSCP 46 (EF) : le poste marque correctement.'],
['Détecter une attaque', 'Journaux saturés.', 'grep "Failed to authenticate" /var/log/asterisk/messages | awk \'{print $NF}\' | sort | uniq -c | sort -rn | head -2', ' 8412 \'"100" <sip:100@203.0.113.10>\' failed for \'185.53.88.12:5082\'\n 2210 … \'45.143.220.9:5070\'', 'Des milliers de tentatives depuis Internet : fail2ban et restriction SIP aux adresses du fournisseur.'],
['Tester le plan de numérotation', 'Nouveau numéro interne.', 'asterisk -rx "dialplan show 2204@interne"', '\'_22XX\' => 1. Dial(PJSIP/${EXTEN},20)\n 2. VoiceMail(${EXTEN}@lycee)', 'Le numéro correspond bien au motif _22XX.']
],
termes: ['VoIP', 'SIP', 'RTP', 'RTCP', 'SDP', 'SRTP', 'INVITE', 'REGISTER', '200 OK', 'ACK', 'BYE', 'codec', 'G.711', 'G.722', 'Opus', 'latence', 'gigue', 'DSCP', 'EF', 'VLAN voix', 'PoE', 'LLDP-MED', 'Asterisk', 'PJSIP', 'plan de numérotation', 'SBC', 'fail2ban']
});
})();