SAÉ 203 - Mettre en place une solution informatique pour l'entreprise
Retour aux SAE
By / Robin Eliott & Auduberteau Emilien
Contexte :
L'objectif de cette SAE était de concevoir une plateforme IoT permettant de collecter, stocker et visualiser des données issues d'objets connectés, à l'aide du protocole MQTT pour la transmission des données, d'une base de données pour leur stockage, et d'un site web dynamique ainsi que des programmes Python pour leur présentation. Faute d'utiliser un capteur physique, nous avions la possibilité d'exploiter les données de notre choix. Pour ma part, j'ai choisi de récupérer les valeurs de la température, de l'humidité ainsi que de la pression atmosphérique à Mont-de-Marsan.

Dans une seconde partie, j'ai dû rédiger un rapport de cybersécurité, dans lequel j'ai analysé les vulnérabilités potentielles de la plateforme IoT que j'avais mise en place, ainsi que les mesures de sécurité à mettre en place pour protéger les données et l'infrastructure.
Déroulement :
Dans un premier temps, j'ai écrit un programme Python qui permet de récupérer les données météos au format JSON de Mont-de-Marsan via une API météo publique. Puis, dans un second temps, j'ai appris à utiliser le protocole MQTT pour envoyer (publish) et recevoir (subscribe) des données grâce à deux programmes Python, le premier permet de "publish" les données récupérées via l'API au Broker MQTT, le second programme permet de s'abonner à un topic: dès qu'une nouvelle information est publiée sur le Broker MQTT concernant ce topic, le programme Python reçoit automatiquement les données et les affiche. Par la suite, j'ai stocké ces données dans une base de données SQLite.

Ensuite, pour rendre la visualisation de ces valeurs plus intuitive et lisible, j'ai développer un site web qui permet d'afficher ces données sous forme de graphiques. De plus, j'ai écrit un programme Python qui permet de créer des graphiques dans un document au format PDF.
Conclusion :
Cette SAE m'a permis de faire mes premiers pas dans le domaine des systèmes d'information. J'ai pu comprendre ce qu'est un système d'information, à quoi il sert, et comment en concevoir un de manière concrète.

Aussi, cette SAE m'a permis de comprendre l'importance du format JSON pour structurer efficacement les messages échangés. En travaillant avec des données issues du web, j'ai appris à en extraire des informations. Par ailleurs, j'ai pris conscience de nombreuses vulnérabilités en cybersécurité liées aux architectures IoT, comme les attaques réseau, les capteurs défaillants ou les données falsifiées.

Enfin, j'ai été amené à documenter et sécuriser l'ensemble de la plateforme, en identifiant les failles potentielles et en proposant des mesures de protection adaptées. Vous trouverez les documents ci-dessous.
Documents :
Partie 1 - Le Système d'information
Schéma de l'architecture :
Programme : MQTT_Publish.py
                        
                            
    import random
    from datetime import *
    import requests
    from paho.mqtt import client as mqtt_client
    import json
    import time
    from zoneinfo import ZoneInfo

    # Broker MQTT
    broker = 'broker.hivemq.com'
    port = 1883
    topic = "/foo/iot/"

    client_id = f'python-mqtt-{random.randint(0, 1000)}'
    dico = {}
    responses = []

    url_mont2 = "https://api.openweathermap.org/data/2.5/weather?lat=43.8936&lon=-0.5027&        appid=941593ac76e57c2ed4c2b93a80b72745&units=metric"
    url_marseille= "https://api.openweathermap.org/data/2.5/weather?lat=43.2961743&lon=5.3699525&appid=941593ac76e57c2ed4c2b93a80b72745&units=metric"
    url_lille= "https://api.openweathermap.org/data/2.5/weather?lat=50.633333&lon=3.066667&appid=941593ac76e57c2ed4c2b93a80b72745&units=metric"

    def connect_mqtt():
        def on_connect(client, userdata, flags, rc, properties=None):
            if rc == 0:
                print("Connecté au MQTT Broker!")
            else:
                print("Erreur de connexion, code:", rc)

        client = mqtt_client.Client(
            client_id=client_id,
            protocol=mqtt_client.MQTTv311,
            callback_api_version=mqtt_client.CallbackAPIVersion.VERSION2
        )
        client.on_connect = on_connect
        client.connect(broker, port)
        return client

    def publish(client):
        while True:
            #Construire le payload avec les 3 villes
            response_mont2 = requests.get(url_mont2)
            response_marseille = requests.get(url_marseille)
            response_lille = requests.get(url_lille)
            responses.extend([response_mont2, response_marseille, response_lille])
            villes = ["Mont-de-Marsan", "Marseille", "Lille"]
            i = 0

            for response in responses:
                if response.status_code == 200:
                    msg = response.json()
                    data = msg['main']

                    #Mettre la date au bon format + à l'heure
                    time1 = msg['dt']
                    utc_var = datetime.fromtimestamp(time1, tz=timezone.utc)
                    dt_paris = utc_var.astimezone(ZoneInfo("Europe/Paris")).isoformat() 
                    dt = datetime.fromisoformat(dt_paris)
                    formatted = dt.strftime("%Y-%m-%dT%H:%M")
                    data['dt'] = formatted

                    dico[f"{villes[i]}"] = data 
                    i+=1

                else:
                    print("Erreur API météo:", response.status_code)
                        
            payload = json.dumps(dico)
            result = client.publish(topic, payload)
            if result.rc == 0:
                print(f"Envoyé à {payload}")
            else:
                print(f"Échec envoi {topic}")

            time.sleep(600)  # Publier toutes les 10 minutes

    def run():
        client = connect_mqtt()
        client.loop_start()
        publish(client)

    if __name__ == '__main__':
        run()
                        
Programme : MQTT_subscribe.py
                        
                            
    import random
    import sqlite3
    import datetime as dt
    from paho.mqtt import client as mqtt_client
    import json

    # Broker MQTT
    broker = 'broker.hivemq.com'
    port = 1883
    topic = "/foo/iot/"
    client_id = f'python-mqtt-{random.randint(0, 100)}'

    connection = sqlite3.connect("bdd.db")

    def connect_mqtt():
        def on_connect(client, userdata, flags, rc, properties=None):
            if rc == 0:
                print("Connecté au MQTT Broker!")
            else:
                print("Erreur de connexion, code:", rc)

        client = mqtt_client.Client(
            client_id=client_id,
            protocol=mqtt_client.MQTTv311,
            callback_api_version=mqtt_client.CallbackAPIVersion.VERSION2
        )
        client.on_connect = on_connect
        client.connect(broker, port)
        return client

    def subscribe(client: mqtt_client):
        
        client.subscribe(topic)

        def on_message(client, userdata, msg):
            # Convertir le payload JSON en dictionnaire Python
            cursor = connection.cursor()
            value = json.loads(msg.payload.decode("utf-8"))
            print(value)

            for ville, data in value.items():
                # Extraire les données
                temp = data['temp']
                press = data['pressure']
                hum = data['humidity']
                date = data['dt']

                # Requête SQL
                cursor.execute(
                    "INSERT INTO mesures (ville, temp, press, hum, date) VALUES (?, ?, ?, ?, ?)",
                    (ville, temp, press, hum, date)
                )
            
                connection.commit()
                
            print("Mis dans la bdd!")

        client.on_message = on_message


    def run():
        client = connect_mqtt()
        subscribe(client)
        client.loop_forever()

    if __name__ == '__main__':
        run()
                        
Page principale du site Web
Partie 2 - Rapport Cybersécurité
Fichiers à télécharger :