{"id":15056680,"url":"https://github.com/ilieschibane/projet-iot-cloud-bigdata","last_synced_at":"2026-01-01T23:06:54.556Z","repository":{"id":225562735,"uuid":"766293337","full_name":"IliesChibane/Projet-IoT-Cloud-BigData","owner":"IliesChibane","description":"Implémentation d'une pipeline permettant de faire la prédiction de la maladie de parkinson via des outils d'IoT, Cloud, et Big Data","archived":false,"fork":false,"pushed_at":"2024-03-03T23:23:29.000Z","size":912,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-21T02:09:06.383Z","etag":null,"topics":["big-data","cassandra","cloud","flask","hadoop-hdfs","iot","kafka","machine-learning","mongodb","mqtt","python","rest-api","sickit-learn","spark"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/IliesChibane.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-02T21:23:44.000Z","updated_at":"2024-03-03T20:36:56.000Z","dependencies_parsed_at":"2024-03-02T22:30:01.411Z","dependency_job_id":"880c78a0-faa4-40d7-b438-0029052f9b14","html_url":"https://github.com/IliesChibane/Projet-IoT-Cloud-BigData","commit_stats":null,"previous_names":["ilieschibane/projet-iot-cloud-bigdata"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IliesChibane%2FProjet-IoT-Cloud-BigData","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IliesChibane%2FProjet-IoT-Cloud-BigData/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IliesChibane%2FProjet-IoT-Cloud-BigData/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IliesChibane%2FProjet-IoT-Cloud-BigData/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IliesChibane","download_url":"https://codeload.github.com/IliesChibane/Projet-IoT-Cloud-BigData/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243538312,"owners_count":20307150,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["big-data","cassandra","cloud","flask","hadoop-hdfs","iot","kafka","machine-learning","mongodb","mqtt","python","rest-api","sickit-learn","spark"],"created_at":"2024-09-24T21:55:04.210Z","updated_at":"2026-01-01T23:06:54.445Z","avatar_url":"https://github.com/IliesChibane.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Création d'une plateforme IoT Cloud et Big Data pour le diagnostique de la maladie de parkinson via des données de capteurs\n\n## Introduction \n\nDans ce tutoriel nous allons voir comment réaliser un pipeline permettant de récupérer des données de capteur et les exploiter de manière optimal afin d'obtenir une plateforme scalable permettant de se mettre à jour aisément dans le cadre du diagnostique de parkison.\n\nLe pipeline réalisé dans ce tutoriel sera comme illustré dans la figure ci dessous :\n\n![pipeline](readme-images/final_pipeline.png?raw=true)\n\nCe data pipeline collecte des données de capteurs, d'API et d'appareils IoT via MQTT. Les données sont ensuite stockées dans un data lake Hadoop envoyé ensuite via kafka vers Spark qui traite les données et les stocke dans Cassandra. Ces données sont par la suite communiqué à une API REST créer avec flask conteant un modèle de machine learning disponible dans la bibliothéque Sickit-Learn retournant les résultats du modèle qui sont par la suite stocké dans MongoDB et puis envoyé vers Atlas permetant de visualiser les différentes métriques obtenus.\n\nCe pipeline est un exemple de la façon dont les données peuvent être collectées, stockées, traitées et analysées pour générer des informations utiles. Il peut être utilisé dans une variété d'applications, telles que la surveillance des performances, la détection de fraude, l'analyse des sentiments et la recommandation de produits.\n\nL'intégralité des outils illustré dans le pipeline seront intégrés en localhost via le langage de programmation Python et avec le système d'exploitation Ubuntu, nous passerons en revue l'integralité des installations nécessaire ainsi que la programation et paramètrage à réaliser pour faire fonctionner la pipeline.\n\nDans un but d'accéssebilité et de simplicité nous simulerons les capteurs en utilisant le dataset  [Gait in Parkinson's Disease](https://physionet.org/content/gaitpdb/1.0.0/) un dataset contenant différent fichier txt représentant les données retourner par les capteurs sur différents patients.\n\n## Intallation des différents outils :\n\n### Python :\n\nEtant donné que nous utilisons Ubuntu comme système d'exploitation Python est dèja installé cependant si vous ne l'avez pas il suffit simplement d'exécuter la commande suivante dans votre terminal :\n\n```bash\nsudo apt install python3\n```\n\n### MQTT :\nCe guide explique comment installer le broker MQTT Mosquitto sur Ubuntu.\n\n**Étape 1 :** Ajout du dépôt Mosquitto\nAjoutez le PPA Mosquitto à vos sources de logiciels pour obtenir la dernière version de Mosquitto.\n```bash\nsudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa\n```\n\n![MQTT 1](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/457d0a91-6f6f-4967-8f28-d13e092d79f1)\n\nMettez à jour la liste des paquets avec la commande suivante :\n```bash\nsudo apt-get update\n```\n![MQTT 2](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/ea9d4760-1f67-4c57-912c-79497c252a81)\n\n\n**Étape 2 :** Installation de Mosquitto\nInstallez le broker Mosquitto avec la commande suivante :\n```bash\nsudo apt-get install mosquitto\n```\nLa sortie indique les paquets qui seront installés, y compris les dépendances et le paquet Mosquitto lui-même.\n![MQTT 3](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/2e7c3712-4180-47ec-bdcd-3a9a188b002d)\n\n**Étape 3 :** Installation des clients Mosquitto\nInstallez les clients Mosquitto, qui fournissent les commandes 'mosquitto_pub' et 'mosquitto_sub' pour publier et s'abonner aux topics MQTT.\n```bash\nsudo apt-get install mosquitto-clients\n```\n![MQTT 4](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/72b6650f-8f44-49bb-8c6f-97ed4f03c469)\n\n**Étape 4 :** Vérification du statut du service Mosquitto\nVérifiez que le service Mosquitto est actif et en cours d'exécution :\n```bash\nsudo service mosquitto status\n```\n![MQTT 5](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/13615498-a204-4d00-8160-56182aa7f7b6)\nLe service Mosquitto MQTT Broker est maintenant actif et fonctionnel.\n\n**Étape 5 :** Installation de la librairie python pour l'utilisation de MQTT\n```bash\npip install paho-mqtt\n```\n\n### Kafka :\nCe guide vous aidera à installer et démarrer Apache Kafka.\n\n**Étape 1 :** Extraction de Kafka\nAprès avoir téléchargé la dernière version de Kafka depuis le [site officiel](https://www.apache.org/dyn/closer.cgi?path=/kafka/3.7.0/kafka_2.13-3.7.0.tgz), extrayez le contenu du fichier tar.gz en utilisant la commande suivante :\n```bash\ntar -xzf kafka_2.13-3.6.1.tgz\n```\nEnsuite, accédez au répertoire de Kafka :\n```bash\ncd kafka_2.13-3.6.1\n```\n\n![KAFKA 1](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/ef6716a3-9b5d-4cd9-8f3a-dea68c8802bf)\n\n\n**Étape 2 :** Démarrage du Serveur Kafka\nInitialisez le stockage de Kafka et démarrez le serveur avec les commandes suivantes :\n\n1. Générez un UUID pour le stockage Kafka et formatez-le :\n```bash\nbin/kafka-storage.sh random-uuid\nbin/kafka-storage.sh format -t \u003cUUID\u003e -c config/kraft/server.properties\n```\n2. Démarrez le serveur Kafka :\n```bash\nbin/kafka-server-start.sh config/kraft/server.properties\n```\nLa sortie dans le terminal devrait ressembler à ce qui suit, indiquant que le serveur est actif.\n![KAFKA 2](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/b81eca2b-523a-44f5-8339-e5fd662ab4b6)\n\n**Étape 3 :** Installation de la librairie python pour l'utilisation de kafka\n```bash\npip install kafka-python confluent_kafka\n```\n\n### Cassandra :\nCe guide vous aidera à installer Apache Cassandra sur votre système.\n\n**Étape 1 :** Prérequis\nVérifiez la version de Java installée sur votre système avec la commande suivante :\n```bash\njava -version\n```\n![Cassandra 1](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/ffa62dbf-f3fe-4a3f-804c-d4d5a0579cb9)\n\n![Cassandra 2](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/627d5b78-8940-44b9-9250-d50ac885b979)\n\n**Étape 2 :** Téléchargement de Cassandra\nTéléchargez la dernière version de [Cassandra](https://cassandra.apache.org/_/download.html) à l'aide de 'curl' :\n```bash\ncurl -OL https://dlcdn.apache.org/cassandra/4.1.3/apache-cassandra-4.1.3-bin.tar.gz\n```\n![Cassandra 3](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/fce42517-396c-488a-8742-7a2e1c0ad71b)\n\n**Étape 3 :** Vérification de l'intégrité du téléchargement\nVérifiez l'intégrité du fichier téléchargé avec :\n```bash\ngpg --print-md SHA256 apache-cassandra-4.1.3-bin.tar.gz\n```\n![Cassandra 4](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/f7449822-b792-4cb4-92c6-52a7e7d291ab)\n\nTéléchargez le fichier de signature SHA256 et vérifiez-le avec :\n```bash\ncurl -L https://downloads.apache.org/cassandra/4.1.3/apache-cassandra-4.1.3-bin.tar.gz.sha256\n```\n![Cassandra 5](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/75166060-3569-48ce-92bd-2dc3aefade07)\n\n\n**Étape 4 :** Extraction de l'archive Cassandra\nExtrayez Cassandra avec :\n```bash\ntar xzvf apache-cassandra-4.1.3-bin.tar.gz\n```\n![Cassandra 6](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/c09da049-2189-49df-ac09-20e9da200bed)\n\n\n**Étape 5 :** Démarrage de Cassandra\nAccédez au répertoire de Cassandra et démarrez le serveur :\n```bash\ncd apache-cassandra-4.1.3 \u0026\u0026 bin/cassandra\n```\n![Cassandra 7](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/16d9658f-99ab-4f83-89e9-0d3295322947)\n\n**Étape 6 :** Vérification du statut de Cassandra\nUtilisez la commande nodetool pour vérifier l'état du cluster Cassandra :\n```bash\nbin/nodetool status\n```\n![Cassandra 8](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/3dfb8ebe-5eeb-4f79-97ab-4df7118a89c8)\n\n**Étape 7 :** Installation de la librairie python pour l'utilisation de Cassandra\n```bash\npip install cassandra-driver\n```\n\n### MongoDB :\nCe guide explique comment installer MongoDB sur Ubuntu.\n\n**Étape 1 :** Installation des dépendances\nInstallez les paquets nécessaires pour ajouter un nouveau référentiel sur votre système :\n```bash\nsudo apt install software-properties-common gnupg apt-transport-https ca-certificates -y\n```\n![MongoDB 1](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/2fdbeffd-8481-4458-b5cb-f087931f19fc)\n![MongoDB 2](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/8da1aa37-c6f3-497a-9932-b24f7d183c25)\n\n**Étape 2 :** Ajout du référentiel MongoDB\nAjoutez la clé GPG officielle de MongoDB :\n```bash\ncurl -fsSL https://www.mongodb.com/server-7.0.asc | sudo gpg --dearmor -o /usr/share/keyrings/mongodb-server-7.0.gpg\n```\nAjoutez le référentiel de MongoDB à votre système :\n```bash\necho \"deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse\" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list\n```\n![MongoDB 3](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/e69f0003-2fb5-49b1-a281-e38eac7d6e61)\n\n**Étape 3 :** Mise à jour de la liste des paquets\nMettez à jour la liste des paquets pour inclure les paquets de MongoDB :\n```bash\nsudo apt update\n```\n![MongoDB 4](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/f271b708-dfd1-4c77-989a-9f2d72d1494c)\n\n**Étape 4 :** Installation de MongoDB\nInstallez MongoDB en utilisant la commande suivante :\n```bash\nsudo apt install mongodb-org -y\n```\n![MongoDB 5](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/2bf396ae-2937-4113-899e-aab793a0cae2)\n\n**Étape 5 :** Démarrage du service MongoDB\nDémarrez le service MongoDB et vérifiez son statut :\n```bash\nsudo systemctl start mongod\nsudo systemctl status mongod\n```\n**Étape 6 :** Vérification de l'installation\nVérifiez que MongoDB est correctement installé en vérifiant la version :\n```bash\nmongod --version\n```\n![MongoDB 6](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/48b6e78d-a43c-4281-ba16-585b577aed3f)\n\n**Étape 7 :** Installation de la librairie python pour l'utilisation de MongoDB\n```bash\npip install pymongo\n```\n\n### Hadoop :\nSuivez ce guide pour configurer un environnement Hadoop sur votre système.\n\n**Étape 1 :** Installation de Java\nVérifiez que Java est correctement installé et configuré sur votre système.\n\n![Hadoop 2](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/177ba3c4-be48-4c95-b33c-7f92fc052f52)\n\n\n**Étape 2 :** Création d'un utilisateur Hadoop\nCréez un utilisateur spécifique pour Hadoop et configurez les informations d'utilisateur nécessaires.\n\n![Hadoop 1](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/e6a934d4-1104-4892-80f4-f029e436d2c6)\n\n**Étape 3 :** Génération des clés SSH\nGénérez une paire de clés SSH pour permettre à l'utilisateur Hadoop de se connecter en SSH sans mot de passe.\n\n![Hadoop 3](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/012432aa-ebe0-48cc-aad8-243f040818fe)\n\n**Étape 4 :** Téléchargement de Hadoop\nUtilisez wget pour télécharger la distribution tarball de Hadoop depuis le [site officiel d'Apache](https://hadoop.apache.org/releases.html).\n\n![Hadoop 4](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/d6f352a4-3be4-4628-bc2d-6f58f02222f2)\n\n**Étape 5 :** Extraction de Hadoop\nExtrayez l'archive téléchargée et déplacez le dossier Hadoop vers un emplacement souhaité.\n\n![Hadoop 5](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/39436973-1987-4dba-b52b-0017f1edabe8)\n\n**Étape 6 :** Configuration de l'environnement Hadoop\nDéfinissez les variables d'environnement pour Java et Hadoop dans le fichier `.bashrc` de l'utilisateur.\n\n![Hadoop 6](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/2be5a03c-0ecd-4f52-bd83-e07619d8b61a)\n\nMettez à jour le fichier .bashrc pour prendre en compte les nouvelles variables d'environnement.\n\n![Hadoop 7](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/8decb0b0-d00a-4331-a486-f1dcfeec897e)\n\nAjoutez le chemin d'accès à Java dans le fichier de configuration Hadoop.\n\n![Hadoop 8](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/1a198cd3-a65c-4eb2-bb88-c6db87516932)\n\n**Étape 7 :** Configuration du système de fichiers HDFS\nConfigurez le système de fichiers HDFS en modifiant les fichiers de configuration de Hadoop, notamment `core-site.xml`.\n\n![Hadoop 9](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/d95bffe8-1467-413b-a0b0-900a3287a8b9)\n\n![Hadoop 10](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/8f8ef206-31f9-47a9-94fc-ca1cca1b23bb)\n\nDéfinissez le répertoire pour le NameNode et le DataNode.\n\n![Hadoop 11](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/5f83f846-360a-4dde-bf8f-b6e1d09f5cbe)\n\n**Étape 8 :** Configuration de MapReduce\nDéfinissez le framework MapReduce en modifiant le fichier `mapred-site.xml`.\n![Hadoop 12](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/45b8a037-83ea-4b09-8479-75b3048e75af)\n\n**Étape 9 :** Configuration de YARN\nConfigurez YARN en modifiant le fichier yarn-site.xml pour définir le gestionnaire de ressources et d'autres propriétés.\n\n![Hadoop 13](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/8c6063b0-82e7-4025-879e-140675ca1697)\n\n**Étape 10 :** Formatage du NameNode\nFormatez le NameNode pour initialiser le système de fichiers HDFS.\n\n![Hadoop 14](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/43ffa409-495f-420a-acbf-7c2966fce12b)\n\n**Étape 11 :** Démarrage des daemons Hadoop\nDémarrez les daemons Hadoop, y compris le NameNode, le DataNode et les services YARN.\n\n![Hadoop 15](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/a346d562-2893-422f-9903-4f76a228cd0d)\n\n![Hadoop 16](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/92c1a37f-13cb-4f3b-86f7-5099727a8eef)\n\n![Hadoop 17](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/3cdce8fb-d346-4f51-a397-3793c025ef1b)\n\n![Hadoop 18](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/144664907/813e31e8-1984-4835-a62d-51534d4d0ead)\n\n**Étape 12 :** Installation de la librairie python pour l'utilisation de Hadoop\n```bash\npip install hdfs\n```\n\n### Spark :\n\n**Étape 1 :** Mettre à jour les paquets système\nPour commencer le processus d'installation, ouvrez un terminal et mettez à jour les paquets de votre système en exécutant la commande suivante :\n```bash\nsudo apt-get update\n```\n\n**Étape 2 :** Télécharger Apache Spark \nAccédez au site officiel d'[Apache Spark](https://spark.apache.org/downloads.html) et téléchargez la dernière version stable d'Apache Spark en sélectionnant le package approprié pour votre système. Vous pouvez utiliser la commande wget pour télécharger le package directement depuis le terminal.\n```bash\nwget https://dlcdn.apache.org/spark/spark-3.4.0/spark-3.4.0-bin-hadoop3.tgz\n```\n\n**Étape 3 :** Extraire le package Apache Spark\nUne fois le téléchargement terminé, extrayez le package en utilisant la commande tar :\n```bash\ntar xvf spark-3.4.0-bin-hadoop3.tgz\n```\n**Étape 4 :** Déplacer le répertoire Spark\nDéplacez le répertoire Spark extrait vers l'emplacement souhaité, tel que `/opt` :\n```bash\nsudo mv spark-3.4.0-bin-hadoop3 /opt/spark\n```\n**Étape 5 :** Configurer les variables d'environnement\nPour garantir que Apache Spark sur Ubuntu est accessible de n'importe où sur votre système, vous devez configurer les variables d'environnement nécessaires. Ouvrez le fichier `.bashrc` à l'aide d'un éditeur de texte :\n```bash\nnano ~/.bashrc\n```\nRajouter les lignes suivantes a la fin du fichier :\n```bash\nexport SPARK_HOME=/opt/spark\nexport PATH=$PATH:$SPARK_HOME/bin\n```\nSave the file and exit the text editor. Then, reload the `.bashrc` file:\n```bash\nsource ~/.bashrc\n```\n**Étape 6 :** Vérifier l'installation\nPour vérifier que Apache Spark est correctement installé sur Ubuntu, ouvrez un nouveau terminal et saisissez la commande suivante :\n```bash\nspark-shell\n```\n**Étape 7 :** Installation de la librairie python pour l'utilisation de Spark\n```bash\npip install pyspark\n```\n\n### Flask et Scikit Learn :\nPour installer flask et sickit learn il suffit d'executer la commande suivante :\n```bash\npip install Flask scikit-learn\n```\n## Réalisation de la plateforme :\n\n### 1) Récupération des données des capteurs avec MQTT :\n\nOn commence par créer le fichier python [sensors_data_receiver.py](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/blob/main/sensors_data_sender.py)  et on y importe les libraires nécessaire :\n\n```python\nimport paho.mqtt.client as mqttClient\nimport time\nimport os\nimport pandas as pd\n```\n\nPar la suite on crée les fonctions permettant de nous connecter et d'envoyer des messages avec notre broket MQTT comme suit :\n\n```python\ndef on_connect(client, userdata, flags, rc):\n    \"\"\"\n    Fonction de rappel pour gérer la connexion au courtier MQTT.\n    \"\"\"\n    if rc == 0:\n        print(\"Connecté au courtier MQTT\")\n        global Connected\n        Connected = True\n    else:\n        print(\"Échec de la connexion\")\n\ndef on_publish(client, userdata, result):\n    \"\"\"\n    Fonction de rappel pour gérer la publication réussie des données.\n    \"\"\"\n    print(\"Données publiées \\n\")\n    pass\n```\n\nMaintenant qu'on a notre fonction nous permettant de nous connecter à notre broker MQTT et de publier des messages nous pouvons passer a la création de notre client MQTT :\n\n```python\nConnected = False\nbroker_address = \"localhost\"\nport = 1883\n\nclient = mqttClient.Client(\"Python_publisher\")  # Créer une nouvelle instance\nclient.on_connect = on_connect  # Attacher la fonction à l'événement de connexion\nclient.on_publish = on_publish  # Attacher la fonction à l'événement de publication\nclient.connect(broker_address, port=port)  # Se connecter au courtier\nclient.loop_start()  # Démarrer la boucle\n\nwhile not Connected:  # Attendre la connexion\n    time.sleep(0.1)\n\nprint(\"Maintenant connecté au courtier: \", broker_address, \"\\n\")\n```\n\nPour résumer jusqu'ici nous avons créé un client MQTT qui se connecte à un courtier local via le protocole MQTT. Il initialise des variables, définit des fonctions de rappel pour la gestion des événements de connexion et de publication, puis tente de se connecter au courtier. La boucle principale attend que la connexion soit établie, utilisant une pause de 0.1 seconde pour éviter une consommation excessive de ressources. Une fois la connexion réussie, le programme affiche un message confirmant la connexion au courtier.\n\n\n\nLa prochaine étape consiste à envoyer les données, pour cela nous récupérons les données de notre dataset fichier par fichier et ligne par la ligne que nous envoyons sous format JSON qui est le format supporté par les messages MQTT.\n\n```python\ntry:\n    while True:\n        folder_path = 'gait-in-parkinsons-disease-1.0.0'\n        txt_files = [file for file in os.listdir(folder_path) if file.endswith('.txt')][2:]\n\n        # Obtenir l'index du fichier 'SHA256SUMS.txt'\n        txt_files.index('SHA256SUMS.txt')\n\n        # Retirer l'index de la liste\n        txt_files.pop(txt_files.index('SHA256SUMS.txt'))\n\n        for file in txt_files:\n            df_p = pd.read_csv(folder_path + \"/\" + file, sep='\\t')\n\n            # Renommer les colonnes pour un accès plus facile\n            df_p.columns = ['time', 'L1', 'L2', 'L3', 'L4', 'L5', 'L6', 'L7', 'L8', 'R1', 'R2', 'R3', 'R4', 'R5', 'R6', 'R7', 'R8', 'L', 'R']\n\n            for row in df_p.to_numpy():\n                message = {\"Patient\": file.split('.')[0]}\n                for c, r in zip(df_p.columns, row):\n                    message[c] = r\n                topic = \"test/parkinson\"\n                client.publish(topic, payload=str(message))\n                time.sleep(1)\n                print(\"Message publié avec succès vers test/parkinson\")\nexcept KeyboardInterrupt:\n    print(\"Sortie de la boucle\")\n    client.disconnect()\n    client.loop_stop()\n```\n\nComme dit précédement nous effectuons une lecture continue de fichiers texte contenant des données liées à la maladie de Parkinson. En utilisant la bibliothèque Pandas, il renomme les colonnes pour faciliter l'accès, extrait le nom du patient du nom du fichier, puis publie ces données sous forme de messages structurés sous format json sur le topic MQTT \"test/parkinson\". La boucle infinie assure une exécution continue, avec une pause d'une seconde entre chaque publication. Le tout pouvant etre interrompue à n'importe quel moment via le clavier.\n\n### 2) Réception des données et stockage dans un Data Lake avec Hadoop HDFS :\n\nLa réception se faisant dans un programme a part nous créeons le fichier [sensors_data_receiver.py](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/blob/main/sensors_data_receiver.py) ou nous y important toutes les librairies dont nous avons besoin :\n\n```python\nimport paho.mqtt.client as mqtt\nimport time\nimport json\nfrom hdfs import InsecureClient\n```\n\nUne fois fait comme lors de l'envoie nous créeons la fonction de connexion et la fonction de réception a la place de la fonction d'envoie :\n\n```python\ndef on_connect(client, userdata, flags, rc):\n    \"\"\"\n    Fonction de rappel pour gérer la connexion au courtier MQTT.\n    \"\"\"\n    if rc == 0:\n         print(\"Connecté au broker\")\n         global Connected                \n         Connected = True               \n    else:\n         print(\"Échec de la connexion\")\n\ndef on_message(client, userdata, message):\n    \"\"\"\n    Fonction de rappel pour gérer les messages MQTT.\n    \"\"\"\n    json_object = json.loads(str(message.payload.decode(\"utf-8\")).replace(\"'\", '\"'))\n    # Stocker les valeurs de données du message dans une chaîne\n    data_values = \"\"\n    for key, value in json_object.items():\n        if key != \"Patient\":\n            data_values += str(value) + \";\"\n    data_values = data_values[:-1]\n    # Enregistrer la chaîne dans un fichier CSV avec la clé comme nom de colonne du fichier\n    local_file = json_object[\"Patient\"]+'.csv'\n    with open(\"csv data/\"+local_file, 'a') as file:\n        file.write(data_values + \"\\n\")\n\n    hdfs_file_path = f\"{data_lake_path}/{local_file}\"\n    if not hdfs_client.status(hdfs_file_path, strict=False): # Si le fichier n'existe pas dans HDFS on le sauvegarde\n        hdfs_client.upload(hdfs_file_path, \"csv data/\"+local_file)\n    \n    print(\"Données enregistrées dans HDFS\")\n```\n\nIci la fonction `on_message` est une fonction de rappel pour la gestion des messages MQTT. Elle convertit le payload JSON du message, extrait les valeurs de données à l'exception de la clé \"Patient\", les enregistre localement dans un fichier CSV portant le nom du patient, et effectue un téléchargement vers un data lake en utilisant le système de stockage distribué Hadoop Distributed File System (HDFS)  sur lequel nous reviendrons par la suite.\n\nMaintenant nous pouvons créer notre client MQTT chargé de recevoir les messages mais aussi d'initialisé notre data lake avec hadoop qui se doit d'etre créer avant le lancement de notre client.\n\n```python\nprint(\"Création d'une nouvelle instance\")\nclient = mqtt.Client(\"python_test\")\nclient.on_message = on_message          # Attacher la fonction au rappel\nclient.on_connect = on_connect\nprint(\"Connexion au broker\")\n\n# Création du data lake\nhdfs_url = \"http://localhost:9870\"\nhdfs_client = InsecureClient(hdfs_url)\ndata_lake_path = \"data_lake/parkinson_data\"\nif not hdfs_client.status(data_lake_path, strict=False): # Si le répertoire n'existe pas dans HDFS on le crée\n    hdfs_client.makedirs(data_lake_path)\n\nclient.connect(broker_address, port)  # Connexion au broker\nclient.loop_start()                   # Démarrer la boucle\n\n\nwhile not Connected:                  # Attendre la connexion\n    time.sleep(0.1)\n \nprint(\"Abonnement au sujet\", \"test/parkinson\")\nclient.subscribe(\"test/parkinson\")\n \ntry:\n    while True: \n        time.sleep(1)\n\nexcept KeyboardInterrupt:\n    print(\"Sortie\")\n    client.disconnect()\n    client.loop_stop()\n```\n\nCe segment de code réalise tout ce qu'on avait décrit précédemment en établissant une connexion avec un courtier MQTT en utilisant la bibliothèque `paho.mqtt.client`. Une instance du client est créée, des fonctions de rappel sont attachées pour la gestion des événements de connexion et de réception de messages, et une connexion est établie avec le courtier spécifié. Parallèlement, un système de stockage distribué, représenté par Hadoop Distributed File System (HDFS), est préparé avec un répertoire dédié (\"parkinson_data\") pour le stockage des fichiers. Le programme s'abonne au sujet MQTT \"test/parkinson\" pour recevoir les messages correspondants. En entrant dans une boucle infinie, le code réagit aux messages reçus en utilisant la fonction de rappel `on_message`, enregistrant les données localement dans des fichiers CSV nommés par le patient, puis transférant ces données vers le Data Lake. L'exécution de la boucle peut être interrompue par un signal de clavier, déclenchant la déconnexion du client MQTT du courtier.\n\n**IMPORTANT :** Les deux programmes [sensors_data_receiver.py](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/blob/main/sensors_data_sender.py) et [sensors_data_receiver.py](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/blob/main/sensors_data_receiver.py) doivent etre exécuté simultanément pour le bon fonctionnement de la plateforme.\n\n### 3) Envoie des données du Data Lake via kafka :\n\nPour cette étape nous créons un nouveau fichier python se nommant [hdfs_read.py](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/blob/main/hdfs_read.py) et on y importe les librairies nécessaires :\n\n```python\nfrom hdfs import InsecureClient\nfrom confluent_kafka import Producer\nimport json\nimport pandas as pd\n```\n\nDans ce programme 2 fonctions sont nécessaire la première assez simple consiste simplement à indiquer si kafka a été en mesure de déliver le message.\n\n```python\ndef delivery_report(err, msg):\n    \"\"\"\n    Fonction de rappel pour gérer les retours de livraison des messages Kafka.\n    \"\"\"\n    if err is not None:\n        print('Échec de livraison du message : {}'.format(err))\n    else:\n        print('Message livré pour le prétraitement')\n```\n\nla seconde fonction elle est celle de l'envoie du message via kafka :\n\n```python\ndef produce_sensor_data(producer, topic, file_name, file_content):\n    \"\"\"\n    Fonction pour produire des données de capteur vers Kafka.\n    \"\"\"\n    group = file_name[2:4]\n\n    message = {\n        \"file_name\": file_name,\n        \"content\": file_content,\n        \"group\": group\n    }\n   \n    producer.produce(topic, key=file_name, value=json.dumps(message), callback=delivery_report)\n    producer.poll(0)\n    producer.flush()\n```\n\nla focntion prend en paramètres un producteur Kafka (`producer`), un sujet Kafka (`topic`), le nom d'un fichier (`file_name`), et le contenu de ce fichier (`file_content`). La fonction extrait la classe du patient (malade ou saint) à partir des deux premiers caractères du nom de fichier. Elle crée ensuite un message structuré avec le nom du fichier, son contenu, et sa classe. Ce message est ensuite produit sur le sujet Kafka en utilisant la méthode `produce` du producteur Kafka, avec le nom du patient comme clé, la représentation JSON du message comme valeur, et une fonction de rappel (`delivery_report`). Enfin, la fonction assure que le message est envoyé immédiatement en utilisant `producer.poll(0)` et termine en vidant le tampon du producteur avec `producer.flush()`.\n\nLa prochaine étape consiste simplement à récupérer les données de notre datalake comme suit :\n\n```python\n# Remplacez avec les détails de votre cluster HDFS\nhdfs_url = \"http://localhost:9870\"\ndata_lake_path = \"data_lake/parkinson_data\"\n\nclient = InsecureClient(hdfs_url)\n\n# Liste des fichiers dans le répertoire Data Lake\nfiles_in_data_lake = client.list(data_lake_path)\n```\n\nAprès ça, on se connecter à notre producer kafka avec le code suivant :\n\n```python\n# Configuration du producteur Kafka\nproducer_conf = {\n    'bootstrap.servers': 'localhost:9092',\n    'client.id': 'python-producer'\n}\n\n# Création de l'instance du producteur Kafka\nproducer = Producer(producer_conf)\n```\n\nMaintenant qu'on accès aux données de note data lake et que notre producer kafka est pret nous envoyons le contenu de nos fichier CSV ligne par ligne pour ne pas dépasser la limite de taille des messages autorisé sur kafka on parcours donc l'intégralité de nos fichier ligne par ligne comme montrer dans la code suivant :\n\n```python\n# Lire le contenu de chaque fichier\nfor file_name in files_in_data_lake:\n    hdfs_file_path = f\"{data_lake_path}/{file_name}\"\n    \n    with client.read(hdfs_file_path, encoding='utf-8') as reader:\n        file_content = reader.read()\n    \n    for line in file_content.split(\"\\n\"):\n        if line == \"\":\n            continue\n        produce_sensor_data(producer, \"sensor_data\", file_name.split(\".\")[0], line)\n\nprint(\"Toutes les données du data lake on était transmises pour prétraitement\")\n```\n\nUne fois terminé le programme indique qu'il envoyé l'integralité des données et s'arrete.\n\n### 4) Réception des données et prétraitement avec Spark :\n\nLes données sont transmises à un notre programme coder dans le fichier [data_preprocess.py](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/blob/main/data_preprocess.py) qui a recours aux librairies suivantes :\n\n```python\nfrom confluent_kafka import Consumer, KafkaError\nimport json\nfrom pyspark.sql import SparkSession\nfrom pyspark.sql.types import StructType, StructField, IntegerType, FloatType\nfrom pyspark.sql.functions import col, row_number\nfrom pyspark.sql import Window\nfrom pyspark.sql.functions import mean\nimport numpy as np\n```\n\nCette partie nécessite 2 fonctions la première consistant à récupérer les données transmises par kafka comme montrer dans le bloc de code ci dessous :\n\n```python\ndef retrieve_data(consumer, topic):\n    \"\"\"\n    Récupérer les données à partir d'un topic Kafka.\n    \"\"\"\n    consumer.subscribe([topic])\n    patient_data = dict()\n    print(\"En attente de messages...\")\n    first_message = False\n    count = 0\n    while True:\n        msg = consumer.poll(1.0)\n\n        if msg is None:\n            if first_message:\n                break\n            else:\n                continue\n        if msg.error():\n            if msg.error().code() == KafkaError._PARTITION_EOF:\n                continue\n            else:\n                print(msg.error())\n                break\n\n        try:\n            first_message = True\n            data = json.loads(msg.value())\n            row = data[\"content\"].split(\";\")\n            if len(row) == 19:\n                row = [float(x) for x in row]\n                row.append(0 if data[\"group\"] == \"Co\" else 1)\n                if data[\"file_name\"] not in patient_data:\n                    patient_data[data[\"file_name\"]] = []\n                patient_data[data[\"file_name\"]].append(row)\n            \n        except json.JSONDecodeError as e:\n            print(f\"Erreur de décodage JSON : {e}\")\n        except KeyError as e:\n            print(f\"Clé manquante dans le JSON : {e}\")\n\n    consumer.close()\n    print(\"Terminé\")\n    return patient_data\n```\n\nCette fonction est conçue pour récupérer des données depuis un topic Apache Kafka. Elle prend en paramètres un consommateur Kafka (`consumer`) et le sujet Kafka depuis lequel les données doivent être récupérées (`topic`). La fonction souscrit au sujet spécifié, initialise un dictionnaire vide pour stocker les données des patients, puis entre dans une boucle qui écoute continuellement les messages Kafka. Lorsqu'un message est reçu, la fonction le décode depuis le format JSON, extrait et transforme les données de la colonne \"content\" au format liste de nombres, ajoute une valeur binaire indiquant le groupe du patient, et stocke la ligne résultante dans le dictionnaire sous la clé correspondant au nom du fichier. La boucle continue jusqu'à ce qu'aucun nouveau message ne soit reçu pendant une seconde. Finalement, le consommateur Kafka est fermé, et le dictionnaire contenant les données des patients est renvoyé.\n\nCela facilitant le travail de la deuxième fonction chargé du prétraitement des données qui prend en entré le résultat de la fonction précédante et qui réalise le traitement des données comme suit :\n\n```python\ndef preprocess_data(patient_data):\n    \"\"\"\n    Prétraiter les données en calculant la moyenne pour chaque groupe de 100 lignes.\n    \"\"\"\n    spark = SparkSession.builder.appName('PatientData').getOrCreate()\n    spark.sparkContext.setLogLevel(\"ERROR\")\n\n    schema = StructType([ \n        StructField(\"Time\", FloatType(), True),  \n        StructField(\"L1\", FloatType(), True), \n        StructField(\"L2\", FloatType(), True), \n        StructField(\"L3\", FloatType(), True),\n        StructField(\"L4\", FloatType(), True),\n        StructField(\"L5\", FloatType(), True),\n        StructField(\"L6\", FloatType(), True),\n        StructField(\"L7\", FloatType(), True),\n        StructField(\"L8\", FloatType(), True),\n        StructField(\"R1\", FloatType(), True), \n        StructField(\"R2\", FloatType(), True), \n        StructField(\"R3\", FloatType(), True),\n        StructField(\"R4\", FloatType(), True),\n        StructField(\"R5\", FloatType(), True),\n        StructField(\"R6\", FloatType(), True),\n        StructField(\"R7\", FloatType(), True),\n        StructField(\"R8\", FloatType(), True),\n        StructField(\"L\", FloatType(), True),\n        StructField(\"R\", FloatType(), True),\n        StructField(\"Class\", IntegerType(), True)\n    ])\n\n    for patient in patient_data:\n        mean_values = []\n        patient_data[patient] = spark.createDataFrame(patient_data[patient], schema)\n        lenght = patient_data[patient].count()\n\n        for i in range(0, lenght, 100):\n            df_with_row_number = patient_data[patient].withColumn(\"row_number\", row_number().over(Window.orderBy(\"Time\")))\n\n            if i+100 \u003e lenght:\n                end = lenght\n            else:\n                end = i+100\n            result_df = df_with_row_number.filter((col(\"row_number\") \u003e= i) \u0026 (col(\"row_number\") \u003c end))\n\n            result_df = result_df.drop(\"row_number\")\n\n            mean_values.append(np.asarray(result_df.select(mean(result_df.L1), mean(result_df.L2), mean(result_df.L3), \\\n                            mean(result_df.L4), mean(result_df.L5), mean(result_df.L6), \\\n                            mean(result_df.L7), mean(result_df.L8), mean(result_df.R1), \\\n                            mean(result_df.R2), mean(result_df.R3), mean(result_df.R4), \\\n                            mean(result_df.R5), mean(result_df.R6), mean(result_df.R7), \\\n                            mean(result_df.R8), mean(result_df.L), mean(result_df.R), \\\n                            mean(result_df.Class)).collect()).tolist()[0])\n        \n        patient_data[patient] = mean_values\n\n    return patient_data\n```\n\nConçue pour effectuer le prétraitement des données en utilisant Apache Spark. Elle prend en entrée un dictionnaire de données de patients (`patient_data`) et calcule la moyenne pour chaque groupe de 100 lignes dans chaque jeu de données du patient. La fonction utilise la bibliothèque Spark pour créer un DataFrame avec un schéma spécifié, puis itère sur chaque patient dans le dictionnaire. Pour chaque patient, elle divise le DataFrame en groupes de 100 lignes, calcule la moyenne pour chaque groupe sur les colonnes spécifiées, et stocke les valeurs moyennes dans une liste. Le résultat final est une mise à jour du dictionnaire `patient_data` avec les nouvelles valeurs moyennes pour chaque patient.\n\nUne fois terminer il suffit simplement de lancer le consomateur kafka et de faire appel à nos 2 fonctions :\n\n```python\n# Configuration du consommateur Kafka\nconsumer_conf = {\n    'bootstrap.servers': 'localhost:9092',\n    'group.id': 'python-consumer',\n    'auto.offset.reset': 'earliest'\n}\n\n# Création de l'instance du consommateur Kafka\nconsumer = Consumer(consumer_conf)\n\npatient_data = retrieve_data(consumer, \"sensor_data\")\n\npreprocessed_data = preprocess_data(patient_data)\n```\n\nCela nous donne un ensemble de données prétraitées qui suffit simplement de stocker pour les utiliser ultérieurement.\n\n### 5) Stockage des données prétraitées dans Cassandra :\n\nTojours sur le meme fichier python [data_preprocess.py](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/blob/main/data_preprocess.py) nous stockons les données obtenu après le prétraitement dans une base de données cassandra, pour cela nous rajoutons à nos import la ligne de code suivante :\n\n```python\nfrom cassandra.cluster import Cluster\n```\n\nPar la suite nous créons la classe suivante :\n\n```python\nclass Cassandra:\n    def __init__(self, create_keyspace_command, data):\n        \"\"\"\n        Initialiser une connexion à Cassandra, créer un espace de clés et une table,\n        puis insérer des données dans la table.\n        \"\"\"\n        self.cluster = Cluster()\n        self.session = self.cluster.connect()\n        self.session.execute(create_keyspace_command)\n        self.session.execute(\"USE Parkinson\")\n        self.session.execute(\"\"\"\n            CREATE TABLE IF NOT EXISTS data (\n                L1 FLOAT,\n                L2 FLOAT,\n                L3 FLOAT,\n                L4 FLOAT,\n                L5 FLOAT,\n                L6 FLOAT,\n                L7 FLOAT,\n                L8 FLOAT,\n                R1 FLOAT,\n                R2 FLOAT,\n                R3 FLOAT,\n                R4 FLOAT,\n                R5 FLOAT,\n                R6 FLOAT,\n                R7 FLOAT,\n                R8 FLOAT,\n                L FLOAT,\n                R FLOAT,\n                Class INT,\n            )\n        \"\"\")\n        self.session.execute(\"TRUNCATE data\")\n        self.insert_data(data)\n\n    def insert_data(self, data):\n        \"\"\"\n        Insérer des données dans la table Cassandra.\n        \"\"\"\n        for d in data:\n            self.session.execute(f\"\"\"\n                INSERT INTO data (\n                    L1, L2, L3, L4, L5, L6, L7, L8, R1, R2, R3, R4, R5, R6, R7, R8, L, R, Class\n                ) VALUES (\n                    {d[0]}, {d[1]}, {d[2]}, {d[3]}, {d[4]}, {d[5]}, {d[6]}, {d[7]}, {d[8]}, {d[9]}, {d[10]}, {d[11]}, {d[12]}, {d[13]}, {d[14]}, {d[15]}, {d[16]}, {d[17]}, {d[18]}\n                )\n            \"\"\")\n\n    def close(self):\n        \"\"\"\n        Fermer la connexion Cassandra.\n        \"\"\"\n        self.cluster.shutdown()\n```\n\nCette classe Python, nommée `Cassandra`, est conçue pour faciliter l'intégration et la manipulation de données dans Cassandra. Son constructeur prend en paramètres une commande pour créer un keyspace Cassandra (`create_keyspace_command`) et des données à insérer (`data`). La classe initialise une connexion à Cassandra, crée un keyspace et une table appelée \"data\" avec des colonnes spécifiques représentant des valeurs de capteur et une classe. Ensuite, elle insère les données fournies dans la table à l'aide de la méthode `insert_data`.\n\nLa méthode `insert_data` itère sur les données fournies et exécute des requêtes d'insertion Cassandra pour chaque ensemble de données. La méthode `close` permet de fermer proprement la connexion à Cassandra.\n\nPour finir, nous créons la requete permettant de créer l'espace de clés cassandra et nous sauvegardons les données dans la base de données :\n\n```python\n# Définition des paramètres de l'espace de clés Cassandra\nkeyspace_name = 'ParkinsonData'\nreplication_strategy = 'SimpleStrategy'\nreplication_factor = 3\n\n# Création de la requête de création de l'espace de clés\ncreate_keyspace_query = f\"\"\"\n    CREATE KEYSPACE IF NOT EXISTS {keyspace_name}\n    WITH replication = {{'class': '{replication_strategy}', 'replication_factor': {replication_factor}}};\n\"\"\"\n\n# Initialisation de l'instance Cassandra, insertion des données, sélection des données et fermeture de la connexion\ncassandra = Cassandra(create_keyspace_query, preprocessed_data)\ncassandra.close()\n```\n\n### 6) Création du API REST de machine learning avec Flask et Sickit-learn :\n\nL'objectif principale de notre plateforme étant le diagnostique des patient il est temps de créer l'API REST contenant le modèle réalisant le diagnostic. Pour cela nous créons le fichier [model_api.py](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/blob/main/model_api.py) et nous importons les librairies suivantes :\n\n```python\nfrom flask import Flask, request, jsonify\nfrom flask_cors import CORS, cross_origin\nimport pandas as pd\nimport numpy as np\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score, roc_curve, auc\nfrom sklearn.metrics import confusion_matrix\nfrom sklearn.model_selection import train_test_split\nfrom mlxtend.evaluate import bias_variance_decomp\nfrom sklearn.neighbors import KNeighborsClassifier\nimport pickle\n```\n\nNous commençons par initialiser notre application flask comme suit :\n\n```python\napp = Flask(__name__)\nCORS(app, resources={r\"/*\": {\"origins\": \"*\", \"allow_headers\": {\"Access-Control-Allow-Origin\"}}})\napp.config['CORS_HEADERS'] = 'Content-Type'\n```\n\nPuis nous créons notre endpoint de la manière suivante :\n\n```python\n@app.route('/api/model', methods=['POST'])\n@cross_origin(origin='*', headers=['content-type'])\ndef model():\n    \"\"\"\n    API endpoint pour entraîner un modèle KNN sur les données fournies.\n    \"\"\"\n    if request.method == 'POST':\n        data = request.files.get('data')\n        columns_name = [\"L1\", \"L2\", \"L3\", \"L4\", \"L5\", \"L6\", \"L7\", \"L8\", \"R1\", \"R2\", \"R3\", \"R4\", \"R5\", \"R6\", \"R7\", \"R8\", \"L\", \"R\", 'Class']\n        df = pd.DataFrame(data)\n\n        X = df.drop('Class', axis=1)\n        y = df['Class']\n        \n        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n        \n        clf = KNeighborsClassifier(n_neighbors=5)\n        clf.fit(X_train, y_train)\n\n        # sauvegarder le modèle avec pickle\n        filename = 'knn.sav'\n        pickle.dump(clf, open(filename, 'wb'))\n\n        # charger le modèle avec pickle\n        loaded_model = pickle.load(open(filename, 'rb'))\n        \n        y_pred = clf.predict(X_test)\n\n        # Évaluer les performances du classifieur\n        accuracy = accuracy_score(y_test, y_pred)\n        precision = precision_score(y_test, y_pred, average='weighted')\n        recall = recall_score(y_test, y_pred, average='weighted')\n        f1 = f1_score(y_test, y_pred, average='weighted')\n\n        # Courbe ROC pour une classification multi-classe\n        y_prob = clf.predict_proba(X_test).argmax(axis=1)\n        macro_roc_auc_ovo = roc_auc_score(y_test.to_numpy(), y_prob, multi_class=\"ovo\", average=\"macro\")\n\n        # Matrice de confusion\n        cm = confusion_matrix(y_test, y_pred)\n\n        # Obtenir les valeurs TP, TN, FP, FN\n        FP = cm.sum(axis=0) - np.diag(cm)  \n        FN = cm.sum(axis=1) - np.diag(cm)\n        TP = np.diag(cm)\n        TN = cm.sum() - (FP + FN + TP)\n\n        # Obtenir le biais et la variance du classifieur\n        loss, bias, var = bias_variance_decomp(clf, X_train, y_train.to_numpy(), X_test, y_test.to_numpy(), loss='0-1_loss', random_seed=23)\n\n        return jsonify({'model': filename,\n                        'accuracy': accuracy,\n                        'precision': precision,\n                        'recall': recall,\n                        'f1': f1,\n                        'macro_roc_auc_ovo': macro_roc_auc_ovo,\n                        'confusion_matrix': cm,\n                        'TP': TP,\n                        'TN': TN,\n                        'FP': FP,\n                        'FN': FN,\n                        'bias': bias,\n                        'variance': var,\n                        'loss': loss})\n```\n\nNotre endpoint est accessible par la méthode HTTP POST. Lorsqu'une requête POST est reçue, la fonction `model` est déclenchée. Cette fonction charge des données envoyées dans la requête, les transforme en DataFrame Pandas, puis divise les données en ensembles d'entraînement et de test. Un modèle de classification des k plus proches voisins (KNN) est ensuite entraîné sur les données d'entraînement. Le modèle est sauvegardé en utilisant le module pickle, puis rechargé. Les performances du modèle sont évaluées à l'aide de métriques telles que l'exactitude, la précision, le rappel et le score F1. Une courbe ROC est générée pour une classification multi-classe, et une matrice de confusion est calculée. Les valeurs des vrais positifs, vrais négatifs, faux positifs et faux négatifs sont obtenues, tout comme le biais, la variance et la perte du classifieur. Les résultats de l'évaluation du modèle ainsi que diverses métriques sont renvoyés sous forme de réponse JSON.\n\nPour terminer on lance notre API avec le code suivant :\n\n```python\nif __name__ == '__main__':\n    app.run(debug=True)\n```\n\n### 7) Envoie des données de Cassandra a l'API :\n\nNotre API étant maintenant opérationel il est temps de lui faire appel en lui envoyant les données qu'on avait stocké sur cassandra. Nous réaliserons cela dans un programme créer dans le fichier [request_model.py](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/blob/main/request_model.py). Comme à notre habitude nous débutons par importer les libraires dont nous avons besoin :\n\n```python\nimport requests\nfrom cassandra.cluster import Cluster\nimport numpy as np\n```\n\nEnsuite, nous recréons notre classe Cassandra sans cependant recréer les espaces de clés ou la table et sans non plus réaliser l'insertion cela ayant dèja été effectué plus tot, cependant nous ajoutons une nouvelle fonction `get_data` dans notre classe qui via une requete CQL très simple nous permet de récupérer l'intégralité de nos données stockées.\n\n```python\nclass Cassandra:\n    def __init__(self):\n        \"\"\"\n        Initialiser une connexion à Cassandra et utiliser l'espace de clés Parkinson.\n        \"\"\"\n        self.cluster = Cluster()\n        self.session = self.cluster.connect()\n        self.session.execute(\"USE Parkinson\")\n\n    def get_data(self):\n        \"\"\"\n        Récupérer les données à partir de la table Cassandra.\n        \"\"\"\n        return np.asarray(self.session.execute(\"SELECT * FROM data\"))\n\n    def close(self):\n        \"\"\"\n        Fermer la connexion à Cassandra.\n        \"\"\"\n        self.cluster.shutdown()\n```\n\nMaintenant nous récupérons nos données de la base sous format de `numpy array` et nous les envoyons à notre API via une requete `POST` nous et en utilisant son endpoint comme url.\n\n```python\nurl = 'http://127.0.0.1:5000/api/model'\n\n# Initialiser la connexion à Cassandra, récupérer les données et fermer la connexion\ncassandra = Cassandra()\ndataset = cassandra.get_data()\ncassandra.close()\n\n# Envoyer les données au serveur Flask\nresponse = requests.post(url, files={'data': dataset})\n```\n\n### 8) Stockage des données retournées par l'API dans MongoDB :\n\nLes résultats de notre modèle ayant été récupéré il faut maintenant les stocker, pour cela nous utilisons MongoDB et cela toujours dans le meme programme en ajoutant simplement pour commencer cette ligne de code à nos import :\n\n```python\nimport pymongo\n```\n\nEt a la fin de notre code nous ajoutons ceci :\n\n```python\n# Initialiser la connexion à MongoDB\nmyclient = pymongo.MongoClient(\"mongodb://localhost:27017\")\nmydb = myclient[\"mydatabase\"]\nmycol = mydb[\"parkinson\"]\n\n# Insérer un document de test, puis le supprimer\nmycol.insert_one({\"test\": \"test\"})\nmycol.drop()\n\n# Réinitialiser la collection\nmycol = mydb[\"parkinson\"]\n\n# Vérifier si la base de données existe\ndblist = myclient.list_database_names()\nif \"mydatabase\" in dblist:\n    print(\"La base de données existe.\")\nelse:\n    print(\"La base de données n'existe pas.\")\n\n# Insérer le résultat de la requête Flask dans MongoDB\nmycol.insert_one(response.json())\n\nprint(\"Modèle et métriques d'évaluation sauvegardés dans MongoDB.\")\n```\n\nUne connexion à une base de données MongoDB locale. une base de données nommée `mydatabase` aisni qu'une collection appelée `parkinson` sont créé au sein de cette base de données. Ensuite, la collection est réinitialisée et vérifiée pour confirmer son existence. Si la base de données `mydatabase` existe, elle est imprimée dans la console, sinon, un message indiquant qu'elle n'existe pas est affiché.\n\nLe script insère ensuite le résultat de notre requête Flask dans la collection MongoDB `parkinson`. Enfin, un message indiquant que le modèle et les métriques d'évaluation ont été sauvegardés dans MongoDB est affiché dans la console.\n\n### 9) Visualisation des données avec MongoDB Atlas:\nPour la visualisation des données, on va avoir recours à la plateforme MongoDB Atlas vu sa simplicité d'utilisation \net son intégration avec la MongoDB\n\nOn commence d'abord par créer un compte sur le site de MongoDB atlas et choisir le plan \"gratuit\"\n\n![image](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/53356222/371c77fb-0558-4d2a-9a0f-32b414f5f266)\n\nUne fois le compte crée, il faut se connecter sur la base de données MongoDB en local. Pour ce faire, il suffit d'aller sur l'onglet Database et puis choisir l'option connect pour configurer la connexion. On va choisir de se connecter via Compass.\n\n![image](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/53356222/d75f3e93-5685-47b0-9059-d60b494d0bdb)\n\nOn va ensuite installer Compass en choisissant la configuration de notre système \n\n![image](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/53356222/6c72ff5b-3217-4351-9218-676bd66570d7)\n\nFinalement, on va copier le string de connexion qui va permettre de se connecter à Atlas\n\n![image](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/53356222/2baf5d30-29e8-4799-a122-38557f3d9480)\n\nAprès, on va exporter la base de données depuis le local en utilisant cette commande:\n```python\nmongodump --uri=\"mongodb://localhost:27017/parkinson\" --archive=mydatabase.dump\n```\nPour ensuite l'importer avec le string de connection qu'on a eu:\n```python\nmongorestore --uri=\"String ici\" --archive=mydatabase.dump\n```\n\nMaintenant qu'on a les données sur Atlas, on procède au volet Charts et on construit les graphes désirés.\nPour notre cas, on a obtenu ceci:\n\n![WhatsApp Image 2024-03-03 at 23 07 21_955a86af](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/53356222/91927e0e-8df2-41e3-9893-c1b346f9321d)\n\n![WhatsApp Image 2024-03-03 at 23 09 20_370148ca](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/53356222/65b267df-a813-4e58-a15b-223470dc8a12)\n\n![WhatsApp Image 2024-03-03 at 23 10 01_36b1eec7](https://github.com/IliesChibane/Projet-IoT-Cloud-BigData/assets/53356222/b8ab3c9c-f4c1-41c5-be1d-a732ed03062a)\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filieschibane%2Fprojet-iot-cloud-bigdata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filieschibane%2Fprojet-iot-cloud-bigdata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filieschibane%2Fprojet-iot-cloud-bigdata/lists"}