Vous travaillez pour une startup spécialisée dans les objets connectés. Votre mission est de développer le logiciel embarqué d'une **station météo connectée** basée sur un SoC (System on Chip).
Cette station doit :
- Collecter des données de capteurs (température, humidité, pression)
- Traiter ces données localement (calculs de moyennes, détection d'anomalies)
- Simuler l'envoi vers le cloud
- Optimiser la consommation énergétique
L'objectif est de comprendre comment fonctionne un système embarqué sur SoC et les contraintes associées.
---
## Objectifs pédagogiques
- Comprendre le fonctionnement d'un système embarqué
- Manipuler des données de capteurs simulés
- Implémenter des algorithmes de traitement de données
- Appréhender les contraintes de ressources limitées
- Découvrir les concepts de l'IoT
---
## Partie 1 : Simulation des capteurs
### 1.1. Classe Capteur
Un capteur embarqué a des caractéristiques spécifiques :
Les systèmes embarqués ont une mémoire limitée. On utilise un **buffer circulaire** pour stocker les N dernières mesures sans allouer de mémoire dynamiquement.
```python
class BufferCirculaire:
"""
Buffer circulaire pour stocker les dernières mesures.
Mémoire fixe, adapté aux systèmes embarqués.
"""
def __init__(self, taille):
"""
Initialise le buffer.
:param taille: (int) Nombre maximum d'éléments
"""
self.taille = taille
self.donnees = [None] * taille # Pré-allocation
self.index = 0
self.compte = 0
def ajouter(self, valeur):
"""
Ajoute une valeur au buffer.
Écrase la plus ancienne si plein.
:param valeur: La valeur à ajouter
"""
# À compléter
pass
def moyenne(self):
"""
Calcule la moyenne des valeurs stockées.
:return: (float) Moyenne ou None si vide
"""
# À compléter
pass
def min_max(self):
"""
Retourne le minimum et le maximum.
:return: (tuple) (min, max) ou (None, None) si vide
"""
# À compléter
pass
def est_plein(self):
"""Vérifie si le buffer est plein."""
return self.compte >= self.taille
def __len__(self):
return self.compte
```
**Principe du buffer circulaire :**
```
Taille = 5, après ajout de 1, 2, 3, 4, 5, 6, 7 :
Étape 1-5 : [1, 2, 3, 4, 5] (remplissage normal)
Étape 6 : [6, 2, 3, 4, 5] (6 écrase 1)
Étape 7 : [6, 7, 3, 4, 5] (7 écrase 2)
L'index "tourne" : index = (index + 1) % taille
```
---
## Partie 3 : Station météo complète
### 3.1. Classe StationMeteo
Assembler les composants pour créer la station :
```python
class StationMeteo:
"""
Station météo IoT simulant un système sur SoC.
"""
def __init__(self, nom, taille_buffer=10):
"""
Initialise la station.
:param nom: (str) Identifiant de la station
:param taille_buffer: (int) Taille des buffers de données
"""Sauvegarde les données en local (simulation de mémoire flash)."""
pass
def charger_local(self, fichier="backup.json"):
"""Charge les données depuis la sauvegarde locale."""
pass
```
### 6.3. Protocole de communication
Simuler un protocole de communication simple (type MQTT) :
```python
def publier(self, topic, message):
"""Publie un message sur un topic (simulation MQTT)."""
print(f"[MQTT] {topic} -> {message}")
```
### 6.4. Multi-stations
Créer un réseau de plusieurs stations qui communiquent entre elles et agrègent leurs données.
---
## Questions de synthèse
1. Pourquoi utilise-t-on un buffer circulaire plutôt qu'une liste dynamique sur un système embarqué ?
2. Quels sont les compromis à faire entre fréquence de mesure et consommation énergétique ?
3. Comment un vrai système IoT gère-t-il la perte de connexion réseau ?
4. Quelles sont les différences entre le code Python de simulation et le code réel sur un microcontrôleur ?
5. Comment l'architecture SoC permet-elle d'optimiser la consommation dans ce type d'application ?
---
## Barème indicatif
| Partie | Points |
|--------|--------|
| Partie 1 : Capteurs | 3 |
| Partie 2 : Buffer circulaire | 4 |
| Partie 3 : Station complète | 5 |
| Partie 4 : Gestion énergie | 3 |
| Partie 5 : Programme principal | 3 |
| Partie 6 : Bonus | 2 |
| **Total** | **20** |
---
Auteur : Florian Mathieu
Licence CC BY NC
<arel="license"href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><imgalt="Licence Creative Commons"style="border-width:0"src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png"/></a><br/>Ce cours est mis à disposition selon les termes de la <arel="license"href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.